Slide 1

Slide 1 text

Floats are Friends: Making the Most of
 IEEE 754.000000002 David Wolever @wolever

Slide 2

Slide 2 text

@wolever Floats are Friends They aren’t the best They also aren’t the worst But we are definitely stuck with them

Slide 3

Slide 3 text

@wolever Why do Floats Exist?

Slide 4

Slide 4 text

@wolever Whole Numbers (Integers)

Slide 5

Slide 5 text

@wolever Whole Numbers (Integers) Pretty easy

Slide 6

Slide 6 text

@wolever Whole Numbers (Integers) Pretty easy 0 0 0 0 0 0 0

Slide 7

Slide 7 text

@wolever Whole Numbers (Integers) Pretty easy 0 0 0 0 0 0 0 1 0 0 0 0 0 1

Slide 8

Slide 8 text

@wolever Whole Numbers (Integers) Pretty easy 0 0 0 0 0 0 0 1 0 0 0 0 0 1 2 0 0 0 0 1 0

Slide 9

Slide 9 text

@wolever Whole Numbers (Integers) Pretty easy 0 0 0 0 0 0 0 1 0 0 0 0 0 1 42 1 0 1 0 1 0 2 0 0 0 0 1 3 0 0 0 0 1 1 ⋮ 0

Slide 10

Slide 10 text

@wolever Whole Numbers (Integers) Two’s Complement

Slide 11

Slide 11 text

@wolever Whole Numbers (Integers) Work Pretty Well INT_MIN (32 bit): −2,147,483,648 INT_MAX (32 bit): +2,147,483,647

Slide 12

Slide 12 text

@wolever Whole Numbers (Integers) Work Pretty Well INT_MIN (32 bit): −2,147,483,648 INT_MAX (32 bit): +2,147,483,647 LONG_MIN (64 bit): −9,223,372,036,854,775,808 LONG_MAX (64 bit): +9,223,372,036,854,775,807

Slide 13

Slide 13 text

@wolever Fractional Numbers (Reals) A Bit More Difficult

Slide 14

Slide 14 text

@wolever Fractional Numbers (Reals) A Bit More Difficult 0 0 0 0 0 .

Slide 15

Slide 15 text

@wolever Fractional Numbers (Reals) A Bit More Difficult 0 0 0 0 0 . 0.125 0 0 0 1 .

Slide 16

Slide 16 text

@wolever Fractional Numbers (Reals) A Bit More Difficult 0 0 0 0 0 . 0.125 0 0 0 1 . 0.25 0 0 1 0 .

Slide 17

Slide 17 text

@wolever Fractional Numbers (Reals) A Bit More Difficult 0 0 0 0 0 . 0.125 0 0 0 1 . 0.25 0 0 1 0 . 0.375 0 0 1 1 . 0.5 0 1 0 0 . 0.875 0 1 1 1 . ⋮

Slide 18

Slide 18 text

@wolever Fractional Numbers (Reals) A Bit More Difficult FIXED (16, 16) smallest: 1.5 ⋅ 10−5 ≈ 2−16 FIXED (16, 16) largest: 131,071.999985 ≈ 217 − 2−16

Slide 19

Slide 19 text

@wolever Fractional Numbers (Reals) A Bit More Difficult FIXED (16, 16) smallest: 1.5 ⋅ 10−5 ≈ 2−16 FIXED (16, 16) largest: 131,071.999985 ≈ 217 − 2−16 FIXED (32, 32) smallest: 2.3 ⋅ 10−10 = 2−32 FIXED (32, 32) largest: 4,294,967,296 ≈ 232 − 2−32

Slide 20

Slide 20 text

@wolever Fractional Numbers (Reals) A Bit More Difficult FIXED (16, 16) smallest: 1.5 ⋅ 10−5 ≈ 2−16 FIXED (16, 16) largest: 131,071.999985 ≈ 217 − 2−16 FIXED (32, 32) smallest: 2.3 ⋅ 10−10 = 2−32 FIXED (32, 32) largest: 4,294,967,296 ≈ 232 − 2−32 (ignoring negative numbers)

Slide 21

Slide 21 text

@wolever Fractional Numbers (Reals) A Bit More Difficult

Slide 22

Slide 22 text

@wolever Fractional Numbers (Reals) A Bit More Difficult Pluto: 7.5e12 M (7.5 billion kilometres)
 Water molecule: 2.8e-10 M (0.28 nanometers)

Slide 23

Slide 23 text

@wolever Fractional Numbers (Reals) A Bit More Difficult Pluto: 7.5e12 M (7.5 billion kilometres)
 Water molecule: 2.8e-10 M (0.28 nanometers) >>> distance_to_pluto = number(7.5, scale=12)
 >>> size_of_water = number(2.8, scale=-10)

Slide 24

Slide 24 text

@wolever And that’s what floats do!

Slide 25

Slide 25 text

@wolever Floating Point Numbers ± E E E E F F F F F F F

Slide 26

Slide 26 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -)

Slide 27

Slide 27 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -) Exponent

Slide 28

Slide 28 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -) Exponent Fraction

Slide 29

Slide 29 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -) Exponent Fraction (also called mantissa)

Slide 30

Slide 30 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -) Exponent (if you’re trying to sound fancy) Fraction (also called mantissa)

Slide 31

Slide 31 text

@wolever Floating Point Numbers ± E E E E F F F F F F F Sign (+ or -) Exponent (if you’re trying to sound fancy) frac × 2exp value = sign × Fraction (also called mantissa)

Slide 32

Slide 32 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5

Slide 33

Slide 33 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 1 × 23−4

Slide 34

Slide 34 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 1 × 23−4 Exponent bias: half the exponent’s maximum value

Slide 35

Slide 35 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 1 × 23−4

Slide 36

Slide 36 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 0 1 0 1 1 1 0 1 3.25 1 × 23−4 13 × 23−5

Slide 37

Slide 37 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 0 1 0 1 1 1 0 1 3.25 1 × 23−4 13 × 23−5 1 0 0 0 1 0 1 1 -88 11 × 23−0

Slide 38

Slide 38 text

@wolever Floating Point Numbers 0 1 0 0 0 0 0 1 0.5 0 1 0 1 1 1 0 1 3.25 1 × 23−4 13 × 23−5 1 0 0 0 1 0 1 1 -88 11 × 23−0 1 1 1 0 0 0 0 1 -0.0125 1 × 23−6

Slide 39

Slide 39 text

@wolever Neat!

Slide 40

Slide 40 text

@wolever Floating Point Numbers exponent fraction smallest largest 32 bit (float) 8 bits 23 bits 1.18e-38 3.4e+38 64 bit (double) 11 bits 52 bits 2.2e-308 1.8e+308

Slide 41

Slide 41 text

@wolever Floating Point Numbers 179,769,313,486,231,570,814,527,423,731,704,356,798, 070,567,525,844,996,598,917,476,803,157,260,780,028, 538,760,589,558,632,766,878,171,540,458,953,514,382, 464,234,321,326,889,464,182,768,467,546,703,537,516, 986,049,910,576,551,282,076,245,490,090,389,328,944, 075,868,508,455,133,942,304,583,236,903,222,948,165, 808,559,332,123,348,274,797,826,204,144,723,168,738, 177,180,919,299,881,250,404,026,184,124,858,368

Slide 42

Slide 42 text

@wolever Floating Point Numbers A Tradeoff

Slide 43

Slide 43 text

@wolever Floating Point Numbers A Tradeoff Precision How small can we get?

Slide 44

Slide 44 text

@wolever Floating Point Numbers A Tradeoff Precision Magnitude How small can we get? How big can we get?

Slide 45

Slide 45 text

@wolever Floating Point Numbers A Tradeoff Precision Magnitude How small can we get? How big can we get? We can measure the distance to Pluto
 (but it won’t be reliable down to the meter)

Slide 46

Slide 46 text

@wolever Floating Point Numbers A Tradeoff Precision Magnitude How small can we get? How big can we get? We can measure the distance to Pluto
 (but it won’t be reliable down to the meter) We can measure the size of a water molecule
 (but not a billion of them at the same time)

Slide 47

Slide 47 text

@wolever Floating Point Numbers wat >>> 1.0
 1.0
 >>> 1e20
 1e+20
 >>> 1e20 + 1
 1e+20
 >>> 1e20 + 1 == 1e20
 True

Slide 48

Slide 48 text

@wolever Floating Point Numbers wat >>> 1.0
 1.0
 >>> 1e20
 1e+20
 >>> 1e20 + 1
 1e+20
 >>> 1e20 + 1 == 1e20
 True

Slide 49

Slide 49 text

@wolever Floating Point Numbers wat >>> 1.0
 1.0
 >>> 1e20
 1e+20
 >>> 1e20 + 1
 1e+20
 >>> 1e20 + 1 == 1e20
 True

Slide 50

Slide 50 text

@wolever Floating Point Numbers wat >>> 1.0
 1.0
 >>> 1e20
 1e+20
 >>> 1e20 + 1
 1e+20
 >>> 1e20 + 1 == 1e20
 True

Slide 51

Slide 51 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits

Slide 52

Slide 52 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits 2. Precision is lost when adding or subtracting
 numbers with different magnitudes:

Slide 53

Slide 53 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits 2. Precision is lost when adding or subtracting
 numbers with different magnitudes: >>> 12345 + 1e15
 1000000000012345
 >>> 12345 + 1e16
 10000000000012344
 >>> 12345 + 1e17
 100000000000012352

Slide 54

Slide 54 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits 2. Precision is lost when adding or subtracting
 numbers with different magnitudes: >>> 12345 + 1e15
 1000000000012345
 >>> 12345 + 1e16
 10000000000012344
 >>> 12345 + 1e17
 100000000000012352

Slide 55

Slide 55 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits 2. Precision is lost when adding or subtracting
 numbers with different magnitudes: >>> 12345 + 1e15
 1000000000012345
 >>> 12345 + 1e16
 10000000000012344
 >>> 12345 + 1e17
 100000000000012352

Slide 56

Slide 56 text

@wolever Floating Point Numbers wat do? 1. Rule of thumb: doubles have 15 significant digits 2. Precision is lost when adding or subtracting
 numbers with different magnitudes: >>> 12345 + 1e15
 1000000000012345
 >>> 12345 + 1e16
 10000000000012344
 >>> 12345 + 1e17
 100000000000012352 (multiplication and division are fine, though!)

Slide 57

Slide 57 text

@wolever Floating Point Numbers wat do? 3. Use a library to sum floats:

Slide 58

Slide 58 text

@wolever Floating Point Numbers wat do? 3. Use a library to sum floats: >>> sum([-1e20, 1, 1e20])
 0.00000000000000000000
 >>> math.fsum([-1e20, 1, 1e20])
 1.00000000000000000000
 >>> np.sum([-1e20, 1, 1e20])
 0.00000000000000000000

Slide 59

Slide 59 text

@wolever Floating Point Numbers wat do? 3. Use a library to sum floats: >>> sum([-1e20, 1, 1e20])
 0.00000000000000000000
 >>> math.fsum([-1e20, 1, 1e20])
 1.00000000000000000000
 >>> np.sum([-1e20, 1, 1e20])
 0.00000000000000000000

Slide 60

Slide 60 text

@wolever Floating Point Numbers wat do? 3. Use a library to sum floats: >>> sum([-1e20, 1, 1e20])
 0.00000000000000000000
 >>> math.fsum([-1e20, 1, 1e20])
 1.00000000000000000000
 >>> np.sum([-1e20, 1, 1e20])
 0.00000000000000000000

Slide 61

Slide 61 text

@wolever Floating Point Numbers wat do? 3. Use a library to sum floats: >>> sum([-1e20, 1, 1e20])
 0.00000000000000000000
 >>> math.fsum([-1e20, 1, 1e20])
 1.00000000000000000000
 >>> np.sum([-1e20, 1, 1e20])
 0.00000000000000000000 See also: accupy

Slide 62

Slide 62 text

@wolever Floating Point Numbers A Tradeoff Every real number can’t be represented Some are infinite: π, e, etc Some can’t be expressed as a binary fraction: 0.1

Slide 63

Slide 63 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555

Slide 64

Slide 64 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555 >>> "%0.20f" %(0.1, )
 0.10000000000000000555 Note: floating point values will be
 shown to 20 decimal places:

Slide 65

Slide 65 text

@wolever Floating Point Numbers A Tradeoff

Slide 66

Slide 66 text

@wolever Floating Point Numbers A Tradeoff 0.5 1.0 0

Slide 67

Slide 67 text

@wolever Floating Point Numbers A Tradeoff 0.1 0.100000005 0.5 1.0 0

Slide 68

Slide 68 text

@wolever Floating Point Numbers A Tradeoff 0.1 3.1415926… 0.100000005 3.1416 0.5 1.0 0

Slide 69

Slide 69 text

@wolever Floating Point Numbers A Tradeoff 0.1 3.1415926… 0.100000005 3.1416 0.5 1.0 (the difference between a real number and
 the nearest number that can be represented
 is called "relative error")

Slide 70

Slide 70 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 71

Slide 71 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 72

Slide 72 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 73

Slide 73 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 74

Slide 74 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 75

Slide 75 text

@wolever Floating Point Numbers wat >>> 0.1
 0.10000000000000000555
 >>> 0.2
 0.20000000000000001110
 >>> 0.3
 0.29999999999999998890
 >>> 0.1 + 0.2
 0.30000000000000004441
 >>> sum([0.1] * 10)
 0.99999999999999988898
 >>> 0.1 * 10
 1.00000000000000000000

Slide 76

Slide 76 text

@wolever Floating Point Numbers wat do? 1. Remember that every operation introduces some error
 (nothing you can do about this)

Slide 77

Slide 77 text

@wolever Floating Point Numbers wat do? 1. Remember that every operation introduces some error
 (nothing you can do about this) 2. Be careful when comparing floats (especially to 0.0)

Slide 78

Slide 78 text

@wolever Floating Point Numbers wat do? 1. Remember that every operation introduces some error
 (nothing you can do about this) 2. Be careful when comparing floats (especially to 0.0) >>> np.isclose(0.1 + 0.2 - 0.3, 0.0)
 True
 >>> def isclose(a, b, epsilon=1e-8):
 ... return abs(a - b) < epsilon
 >>> isclose(0.1 + 0.2, 0.3)
 True

Slide 79

Slide 79 text

@wolever Floating Point Numbers wat do? 3. Round floats to the precision you need before
 displaying them: >>> "%0.2f" %(0.1, )
 '0.10'
 >>> "%0.2f" %(0.1 + 0.2, )
 '0.30'
 >>> "%0.2f" %(sum([0.1] * 10), )
 '1.00'

Slide 80

Slide 80 text

@wolever the weird parts

Slide 81

Slide 81 text

@wolever the weird parts Infinity 0

Slide 82

Slide 82 text

@wolever the weird parts inf / -inf 01 1 1 0 0 0 0 ±

Slide 83

Slide 83 text

@wolever the weird parts inf / -inf 01 1 1 0 0 0 0 ± >>> inf = float('inf')
 >>> inf > 1e308
 True
 >>> inf > inf
 False

Slide 84

Slide 84 text

@wolever the weird parts inf / -inf >>> 1e308 + 1e308
 inf
 >>> -1e308 - 1e308
 -inf Result of overflowing a large number:

Slide 85

Slide 85 text

@wolever the weird parts inf / -inf >>> np.array([1.0]) / np.array([0.0])
 RuntimeWarning: divide by zero encountered in divide
 array([inf])
 >>> 1.0 / 0.0
 …
 ZeroDivisionError: float division by zero Result of dividing by zero (sometimes):

Slide 86

Slide 86 text

@wolever the weird parts inf / -inf >>> np.array([1.0]) / np.array([0.0])
 RuntimeWarning: divide by zero encountered in divide
 array([inf])
 >>> 1.0 / 0.0
 …
 ZeroDivisionError: float division by zero Result of dividing by zero (sometimes):

Slide 87

Slide 87 text

@wolever the weird parts inf / -inf lim x→0 1 x = ± ∞

Slide 88

Slide 88 text

@wolever the weird parts -0 0

Slide 89

Slide 89 text

@wolever the weird parts -0 00 0 0 0 0 0 0 ±

Slide 90

Slide 90 text

@wolever the weird parts -0 00 0 0 0 0 0 0 ± >>> float('-0')
 -0.0
 >>> -1e-323 / 10
 -0.0 Result of underflowing a small number:

Slide 91

Slide 91 text

@wolever the weird parts -0 "Useful" to know the sign of inf when dividing by 0: >>> np.array([1.0, 1.0]) /
 ... np.array([float('0'), float('-0')])
 array([ inf, -inf])

Slide 92

Slide 92 text

@wolever the weird parts -0 Otherwise behaves like 0: >>> float('-0') == float('0')
 True
 >>> float('-0') / 42.0
 -0.0

Slide 93

Slide 93 text

@wolever the weird parts nan 0 Not A Number

Slide 94

Slide 94 text

@wolever the weird parts nan 01 1 1 0 0 0 1 ±

Slide 95

Slide 95 text

@wolever the weird parts nan >>> float('inf') / float('inf')
 nan Result of mathematically undefined operations: 01 1 1 0 0 0 1 ±

Slide 96

Slide 96 text

@wolever the weird parts nan >>> float('inf') / float('inf')
 nan Result of mathematically undefined operations: 01 1 1 0 0 0 1 ± >>> math.sqrt(-1)
 ValueError: math domain error Although Python is more helpful:

Slide 97

Slide 97 text

@wolever the weird parts nan >>> nan = float('nan')
 >>> nan == nan
 False
 >>> 1 > nan
 False
 >>> 1 < nan
 False
 >>> 1 + nan
 nan Wild, breaks everything:

Slide 98

Slide 98 text

@wolever the weird parts nan >>> nan = float('nan')
 >>> nan == nan
 False
 >>> 1 > nan
 False
 >>> 1 < nan
 False
 >>> 1 + nan
 nan Wild, breaks everything:

Slide 99

Slide 99 text

@wolever the weird parts nan >>> nan = float('nan')
 >>> nan == nan
 False
 >>> 1 > nan
 False
 >>> 1 < nan
 False
 >>> 1 + nan
 nan Wild, breaks everything:

Slide 100

Slide 100 text

@wolever the weird parts nan >>> nan = float('nan')
 >>> nan == nan
 False
 >>> 1 > nan
 False
 >>> 1 < nan
 False
 >>> 1 + nan
 nan Wild, breaks everything:

Slide 101

Slide 101 text

@wolever the weird parts nan >>> nan in [nan]
 True

Slide 102

Slide 102 text

@wolever the weird parts nan >>> a = np.array([1.0, 0.0, 3.0])
 >>> b = np.array([5.0, 0.0, 7.0])
 >>> np.nanmean(a / b)
 0.3142857142857143 Useful if you want to ignore invalid values:

Slide 103

Slide 103 text

@wolever the weird parts nan >>> math.isnan(nan)
 True
 >>> nan != nan
 True Check for nan with isnan or x != x:

Slide 104

Slide 104 text

@wolever the weird parts nan Pop quiz: how many nans are there?

Slide 105

Slide 105 text

@wolever the weird parts nan Pop quiz: how many nans are there? 252

Slide 106

Slide 106 text

@wolever the weird parts nan Pop quiz: how many nans are there? 252 01 1 1 X X X X ±

Slide 107

Slide 107 text

@wolever What a waste!

Slide 108

Slide 108 text

@wolever the weird parts nan Why not us all those nans as pointers? * The top 16-bits denote the type of the encoded JSValue: * * Pointer { 0000:PPPP:PPPP:PPPP * / 0001:****:****:**** * Double { ... * \ FFFE:****:****:**** * Integer { FFFF:0000:IIII:IIII (from WebKit’s JSCJSValue.h)

Slide 109

Slide 109 text

@wolever the weird parts nan JsObj JsObj_add(JsObj a, JsObj b) {
 if (JS_IS_DOUBLE(a) && JS_IS_DOUBLE(b))
 return a + b
 if (JS_IS_STRING_REF(a) && JS_IS_STRING_REF(b))
 return JsString_concat(a, b)
 ...
 }

Slide 110

Slide 110 text

@wolever the weird parts nan JsObj JsObj_add(JsObj a, JsObj b) {
 if (JS_IS_DOUBLE(a) && JS_IS_DOUBLE(b))
 return a + b
 if (JS_IS_STRING_REF(a) && JS_IS_STRING_REF(b))
 return JsString_concat(a, b)
 ...
 }

Slide 111

Slide 111 text

@wolever the weird parts nan JsObj JsObj_add(JsObj a, JsObj b) {
 if (JS_IS_DOUBLE(a) && JS_IS_DOUBLE(b))
 return a + b
 if (JS_IS_STRING_REF(a) && JS_IS_STRING_REF(b))
 return JsString_concat(a, b)
 ...
 }

Slide 112

Slide 112 text

@wolever

Slide 113

Slide 113 text

@wolever decimal

Slide 114

Slide 114 text

@wolever decimal The decimal module provides support for decimal floating point arithmetic

Slide 115

Slide 115 text

@wolever decimal

Slide 116

Slide 116 text

@wolever decimal Exact representations of decimal numbers

Slide 117

Slide 117 text

@wolever decimal Exact representations of decimal numbers The "nearest number" rounding will still happen, but it will be more sensible

Slide 118

Slide 118 text

@wolever decimal Exact representations of decimal numbers The "nearest number" rounding will still happen, but it will be more sensible Precision still needs to be specified…

Slide 119

Slide 119 text

@wolever decimal Exact representations of decimal numbers The "nearest number" rounding will still happen, but it will be more sensible Precision still needs to be specified… … but the default is 28 decimal places

Slide 120

Slide 120 text

@wolever decimal >>> from decimal import Decimal
 >>> d = Decimal('0.1')
 >>> d + d + d + d + d + d + d + d + d + d
 Decimal('1.0')
 >>> pi = Decimal(math.pi)
 >>> pi
 Decimal('3.141592653589793115997963…')

Slide 121

Slide 121 text

@wolever decimal >>> from decimal import Decimal
 >>> d = Decimal('0.1')
 >>> d + d + d + d + d + d + d + d + d + d
 Decimal('1.0')
 >>> pi = Decimal(math.pi)
 >>> pi
 Decimal('3.141592653589793115997963…')

Slide 122

Slide 122 text

@wolever decimal >>> from decimal import Decimal
 >>> d = Decimal('0.1')
 >>> d + d + d + d + d + d + d + d + d + d
 Decimal('1.0')
 >>> pi = Decimal(math.pi)
 >>> pi
 Decimal('3.141592653589793115997963…')

Slide 123

Slide 123 text

@wolever decimal >>> from decimal import Decimal
 >>> d = Decimal('0.1')
 >>> d + d + d + d + d + d + d + d + d + d
 Decimal('1.0')
 >>> pi = Decimal(math.pi)
 >>> pi
 Decimal('3.141592653589793115997963…')

Slide 124

Slide 124 text

@wolever decimal In [1]: d = Decimal('42')
 In [2]: %timeit d * d
 100,000 loops, best of 3: 7.28 µs per loop
 In [3]: f = 42.0
 In [4]: %timeit f * f
 10,000,000 loops, best of 3: 44.6 ns per loop

Slide 125

Slide 125 text

@wolever decimal In [1]: d = Decimal('42')
 In [2]: %timeit d * d
 100,000 loops, best of 3: 7.28 µs per loop
 In [3]: f = 42.0
 In [4]: %timeit f * f
 10,000,000 loops, best of 3: 44.6 ns per loop

Slide 126

Slide 126 text

@wolever decimal In [1]: d = Decimal('42')
 In [2]: %timeit d * d
 100,000 loops, best of 3: 7.28 µs per loop
 In [3]: f = 42.0
 In [4]: %timeit f * f
 10,000,000 loops, best of 3: 44.6 ns per loop

Slide 127

Slide 127 text

@wolever decimal >>> from pympler.asizeof import asizeof
 >>> asizeof(42.0)
 24
 >>> asizeof(1e308)
 24
 >>> asizeof(Decimal('42'))
 168
 >>> asizeof(Decimal('1e308'))
 192

Slide 128

Slide 128 text

@wolever decimal >>> from pympler.asizeof import asizeof
 >>> asizeof(42.0)
 24
 >>> asizeof(1e308)
 24
 >>> asizeof(Decimal('42'))
 168
 >>> asizeof(Decimal('1e308'))
 192

Slide 129

Slide 129 text

@wolever decimal >>> from pympler.asizeof import asizeof
 >>> asizeof(42.0)
 24
 >>> asizeof(1e308)
 24
 >>> asizeof(Decimal('42'))
 168
 >>> asizeof(Decimal('1e308'))
 192

Slide 130

Slide 130 text

@wolever decimal >>> from pympler.asizeof import asizeof
 >>> asizeof(42.0)
 24
 >>> asizeof(1e308)
 24
 >>> asizeof(Decimal('42'))
 168
 >>> asizeof(Decimal('1e308'))
 192

Slide 131

Slide 131 text

@wolever decimal Is great!
 
 Use decimal when precision is important.

Slide 132

Slide 132 text

Thanks! David Wolever @wolever

Slide 133

Slide 133 text

Selected References • "What Every Computer Scientist Should Know About Floating-Point Arithmetic": http://docs.sun.com/source/806-3568/ncg_goldberg.html
 (note: very math and theory heavy; not especially useful) • "Points on Floats": https://matthew-brett.github.io/teaching/ floating_point.html#floating-point
 (much more approachable) • "Float Precision–From Zero to 100+ Digits": https:// randomascii.wordpress.com/2012/03/08/float-precisionfrom-zero- to-100-digits-2/
 (a good series of blog posts on floats and precision) • John von Neumann’s thoughts on floats: https://library.ias.edu/files/ Prelim_Disc_Logical_Design.pdf (section 5.3; page 18)