Upgrade to Pro — share decks privately, control downloads, hide ads and more …

我搞不懂浮點數

Yung-Luen Lan
September 22, 2019

 我搞不懂浮點數

Yung-Luen Lan

September 22, 2019
Tweet

More Decks by Yung-Luen Lan

Other Decks in Programming

Transcript

  1. 你可能知道浮點數怪怪的 You may know the behavior of floating point number

    is weird https://0.30000000000000004.com print(0.1 + 0.2) // 0.30000000000000004
  2. 浮點數是⼀一種資料型態 type Floating Point Number is a data type •

    Values
 UInt8: 0,1,2,…,255 
 FruitEnum: ,,, • How to encode/decode values
 0x4B: 75 in UInt8 or 'K' in ASCII When we talk about types, we have two aspects to concern:
  3. 1.0 2.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8

    1.9 1.75 1.00 10.00 1.10 1.01 1.11
  4. 1.0 2.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8

    1.9 1.75 1.00 10.00 1.10 1.01 1.11
  5. 1 2

  6. 1 2

  7. … 1 2 0.5 0.25 0.125 0.0625 4 2k ×

    1.00, 1.01, 1.10, 1.11 …, -2 , -1, 0, 1, 2, 3, … 浮點數的形式 The form of FP
  8. 2k × 1.000000, 1.000001, 1.000010, …, 1.111111 ± .exponent .significand

    .sign .significandBitPattern Double.significandBitCount 52
  9. 2k × 1.000000, 1.000001, 1.000010, …, 1.111111 ± .exponent .significand

    .sign .significandBitPattern Double.exponentBitCount 11 Double.significandBitCount 52
  10. 2k × 1.000000, 1.000001, 1.000010, …, 1.111111 ± .exponent .significand

    .sign .exponentBit Pattern .significandBitPattern Double.exponentBitCount 11 Double.significandBitCount 52
  11. 01111111111 10000000000 10000000001 … … 0 1 2 -1 01111111110

    11111111111 00000000000 .exponent .exponentBitPattern 1022 1023 1024 1025 0 -1023 2047 1024
  12. 01111111111 10000000000 10000000001 … … 0 1 2 -1 01111111110

    11111111111 00000000000 1022 1023 1024 1025 .exponentBitPattern = .exponent + shift Double.exponentBitCount - 1 shift = 2 - 1
  13. 19.9 10011.1110011001100... ≈ = 21 × 1001.11110011001100… = 22 ×

    100.111110011001100… = 24 × 1.00111110011001100…
  14. … 1 2 0.5 0.25 0.125 0.0625 4 .exponent select

    the range .significand mark the index inside the range .ulp(unit in the last place) is the width inside the range
  15. … 1 2 0.5 0.25 0.125 0.0625 4 .exponent select

    the range .significand mark the index inside the range .ulp(unit in the last place) is the width inside the range
  16. … 1 2 0.5 0.25 0.125 0.0625 4 .exponent select

    the range .significand mark the index inside the range .ulp(unit in the last place) is the width inside the range
  17. … 1 2 0.5 0.25 0.125 0.0625 4 .exponent select

    the range .significand mark the index inside the range .ulp(unit in the last place) is the width inside the range
  18. 0 -1022 00000000001 -1021 00000000010 -1 0000 00000000000 Subnormal (Denormal)

    Number -1074 Double.leastNonzeroMagnitude = 2 =0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000494065645841246544176568792868 22137236505980261432476442558568250067550727020875186529983636163599237979656469544571773 09266567103559397963987747960107818781263007131903114045278458171678489821036887186360569 98730723050006387409153564984387312473397273169615140031715385398074126238565591171026658 55668676818703956031062493194527159149245532930545654440112748012970999954193198940908041 65633245247571478690147267801593552386115501348035264934720193790268107107491703332226844 75333572083243193609238289345836806010601150616980975307834227731832924790498252473077637 59272478746560847782037344696995336470179726777175851256605511991315048911014510378627381 67250955837389733598993664809941164205702637090279242767544565229087538682506419718265533 447265625
  19. 1023 1111111110 1022 1111111101 1020 111111100 019 011 .infinity .isNan

    !== true .greatestFiniteMagnitude = 2 - 2 1024 971 =17976931348623157081452742373170435679807056752584499659891747680315726078 002853876058955863276687817154045895351438246423432132688946418276846754670 353751698604991057655128207624549009038932894407586850845513394230458323690 322294816580855933212334827479782620414472316873817718091929988125040402618 4124858368
  20. Quiz let add = 0.1 + 0.1 + 0.1 +

    0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 let mul = 0.1 * 9
  21. Quiz let add = 0.1 + 0.1 + 0.1 +

    0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 let mul = 0.1 * 9 // add: 0.89999999999999991 // mul: 0.90000000000000002
  22. Quiz 19.9 * 10 * 10 == 19.9 * 100

    let add = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 let mul = 0.1 * 9 // add: 0.89999999999999991 // mul: 0.90000000000000002
  23. Quiz 19.9 * 10 * 10 == 19.9 * 100

    let add = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 let mul = 0.1 * 9 // add: 0.89999999999999991 // mul: 0.90000000000000002 // 1990 // 1989.9999999999998
  24. var m: Float = 0 for _ in 0..<1000000 {

    m += 0.01 } m // 9865.22363 DON’T: Use floating point type to store money!
  25. var m: Float = 0 for _ in 0..<1000000 {

    m += 0.01 } m // 9865.22363 DON’T: Use floating point type to store money! var money: Decimal = 0 for _ in 0..<1000000 { money += Decimal(1) / Decimal(100) } money // 10000.000000 DO: Use Decimal type to store money
  26. Use Double if possible - Minecraft coordinate was float. -

    Kurt J. Mac hit the 2-pixel offset at his show “Far Land or Bust” at distance 2,097,152.
  27. Use Double if possible typealias TimeInterval = !Float? Duration 1

    sec 3 hr 1 day 4 months 3 years Precision 0.12 µs 1ms 8ms 1 secs 8 secs What if…
  28. What could go wrong? func interpolate(end: Date, length: TimeInterval, now:

    Date) -> Double { let start = end - length return now.timeIntervalSince(start) / length }
  29. What could go wrong? func interpolate(end: Date, length: TimeInterval, now:

    Date) -> Double { let start = end - length return now.timeIntervalSince(start) / length } let d = Date(timeIntervalSince1970: 1569132000) // Sep 22, 2019 at 2:00 PM interpolate(end: d, length: 0.9999999403953552, now: d) // 1.000000059604648
  30. End Length Start Now func interpolate(end: Date, length: TimeInterval, now:

    Date) -> Double { return (length - (end.timeIntervalSince(now))) / length }
  31. What could go wrong? func sample(range: Range<Double>) { var point

    = range.lowerBound while point < range.upperBound { // process(point) point += 0.01 } }
  32. What could go wrong? func sample(range: Range<Double>) { var point

    = range.lowerBound while point < range.upperBound { // process(point) point += 0.01 } } sample(range: 1125899906842624.0..<1125899906842626.0)
  33. What could go wrong? func sample(range: Range<Double>) { var point

    = range.lowerBound while point < range.upperBound { // process(point) point += 0.01 } } sample(range: 1125899906842624.0..<1125899906842626.0) Infinity Loop!
  34. 0.01 Point func sample(range: Range<Double>) { var point = range.lowerBound

    while point < range.upperBound { // process(point) point += max(0.01, point.ulp) } }
  35. What could go wrong? var a: Double = //... var

    b: Double = //... if a == b { // .. }
  36. What could go wrong? var a: Double = //... var

    b: Double = //... if a == b { // .. } if abs(a - b) < 0.0001 { // .. }
  37. What could go wrong? var a: Double = //... var

    b: Double = //... if a == b { // .. } if abs(a - b) < 0.0001 { // .. } if abs((a - b)/b) < 0.0001 { // .. }
  38. What is the return value? @interface IPlaygroundSession : NSObject -

    (double) score; @end @implementation IPlaygroundSession - (double) score { return 100.0; } @end IPlaygroundSession *mySession = nil; [mySession score]; // what's the value?
  39. What is the return value? @interface IPlaygroundSession : NSObject -

    (double) score; @end @implementation IPlaygroundSession - (double) score { return 100.0; } @end IPlaygroundSession *mySession = nil; [mySession score]; // what's the value? 0.0
  40. Before OSX 10.4 (ppc) https://opensource.apple.com/source/objc4/objc4-237/runtime/Messengers.subproj/ objc-msg-ppc.s.auto.html LMsgSendNilSelf: mflr r0 ;

    load new receiver bcl 20,31,1f ; 31 is cr7[so] 1:mflr r11 addis r11,r11,ha16(__objc_nilReceiver-1b) lwz r11,lo16(__objc_nilReceiver-1b)(r11) mtlr r0 cmplwi r11,0 ; return nil if no new receiver beqlr mrr3,r11 ; send to new receiver b LMsgSendReceiverOk
  41. How to fix this? pow(M_E, Double.pi) - Double.pi // 19.99909997918947

    19.9990999791894757672664429846690444960689368432251 0617247010181721…