annotate Doc/tutorial/floatingpoint.rst @ 80661:94de77bd0b4b 2.7

Issue #16194: document imp.load_dynamic problems when read several extension modules from the same binary object file.
author Andrew Svetlov <andrew.svetlov@gmail.com>
date Thu, 29 Nov 2012 19:51:28 +0200
parents b36cb4602e21
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
1 .. _tut-fp-issues:
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
2
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
3 **************************************************
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
4 Floating Point Arithmetic: Issues and Limitations
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
5 **************************************************
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
6
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
7 .. sectionauthor:: Tim Peters <tim_one@users.sourceforge.net>
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
8
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
9
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
10 Floating-point numbers are represented in computer hardware as base 2 (binary)
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
11 fractions. For example, the decimal fraction ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
12
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
13 0.125
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
14
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
15 has value 1/10 + 2/100 + 5/1000, and in the same way the binary fraction ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
16
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
17 0.001
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
18
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
19 has value 0/2 + 0/4 + 1/8. These two fractions have identical values, the only
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
20 real difference being that the first is written in base 10 fractional notation,
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
21 and the second in base 2.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
22
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
23 Unfortunately, most decimal fractions cannot be represented exactly as binary
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
24 fractions. A consequence is that, in general, the decimal floating-point
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
25 numbers you enter are only approximated by the binary floating-point numbers
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
26 actually stored in the machine.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
27
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
28 The problem is easier to understand at first in base 10. Consider the fraction
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
29 1/3. You can approximate that as a base 10 fraction::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
30
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
31 0.3
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
32
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
33 or, better, ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
34
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
35 0.33
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
36
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
37 or, better, ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
38
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
39 0.333
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
40
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
41 and so on. No matter how many digits you're willing to write down, the result
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
42 will never be exactly 1/3, but will be an increasingly better approximation of
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
43 1/3.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
44
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
45 In the same way, no matter how many base 2 digits you're willing to use, the
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
46 decimal value 0.1 cannot be represented exactly as a base 2 fraction. In base
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
47 2, 1/10 is the infinitely repeating fraction ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
48
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
49 0.0001100110011001100110011001100110011001100110011...
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
50
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
51 Stop at any finite number of bits, and you get an approximation.
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
52
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
53 On a typical machine running Python, there are 53 bits of precision available
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
54 for a Python float, so the value stored internally when you enter the decimal
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
55 number ``0.1`` is the binary fraction ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
56
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
57 0.00011001100110011001100110011001100110011001100110011010
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
58
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
59 which is close to, but not exactly equal to, 1/10.
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
60
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
61 It's easy to forget that the stored value is an approximation to the original
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
62 decimal fraction, because of the way that floats are displayed at the
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
63 interpreter prompt. Python only prints a decimal approximation to the true
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
64 decimal value of the binary approximation stored by the machine. If Python
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
65 were to print the true decimal value of the binary approximation stored for
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
66 0.1, it would have to display ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
67
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
68 >>> 0.1
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
69 0.1000000000000000055511151231257827021181583404541015625
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
70
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
71 That is more digits than most people find useful, so Python keeps the number
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
72 of digits manageable by displaying a rounded value instead ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
73
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
74 >>> 0.1
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
75 0.1
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
76
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
77 It's important to realize that this is, in a real sense, an illusion: the value
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
78 in the machine is not exactly 1/10, you're simply rounding the *display* of the
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
79 true machine value. This fact becomes apparent as soon as you try to do
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
80 arithmetic with these values ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
81
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
82 >>> 0.1 + 0.2
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
83 0.30000000000000004
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
84
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
85 Note that this is in the very nature of binary floating-point: this is not a
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
86 bug in Python, and it is not a bug in your code either. You'll see the same
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
87 kind of thing in all languages that support your hardware's floating-point
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
88 arithmetic (although some languages may not *display* the difference by
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
89 default, or in all output modes).
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
90
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
91 Other surprises follow from this one. For example, if you try to round the
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
92 value 2.675 to two decimal places, you get this ::
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
93
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
94 >>> round(2.675, 2)
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
95 2.67
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
96
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
97 The documentation for the built-in :func:`round` function says that it rounds
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
98 to the nearest value, rounding ties away from zero. Since the decimal fraction
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
99 2.675 is exactly halfway between 2.67 and 2.68, you might expect the result
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
100 here to be (a binary approximation to) 2.68. It's not, because when the
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
101 decimal string ``2.675`` is converted to a binary floating-point number, it's
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
102 again replaced with a binary approximation, whose exact value is ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
103
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
104 2.67499999999999982236431605997495353221893310546875
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
105
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
106 Since this approximation is slightly closer to 2.67 than to 2.68, it's rounded
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
107 down.
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
108
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
109 If you're in a situation where you care which way your decimal halfway-cases
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
110 are rounded, you should consider using the :mod:`decimal` module.
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
111 Incidentally, the :mod:`decimal` module also provides a nice way to "see" the
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
112 exact value that's stored in any particular Python float ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
113
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
114 >>> from decimal import Decimal
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
115 >>> Decimal(2.675)
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
116 Decimal('2.67499999999999982236431605997495353221893310546875')
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
117
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
118 Another consequence is that since 0.1 is not exactly 1/10, summing ten values
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
119 of 0.1 may not yield exactly 1.0, either::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
120
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
121 >>> sum = 0.0
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
122 >>> for i in range(10):
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
123 ... sum += 0.1
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
124 ...
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
125 >>> sum
57428
337ebb829b8c Fix some documentation examples involving the repr of a float.
Mark Dickinson <dickinsm@gmail.com>
parents: 51775
diff changeset
126 0.9999999999999999
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
127
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
128 Binary floating-point arithmetic holds many surprises like this. The problem
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
129 with "0.1" is explained in precise detail below, in the "Representation Error"
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
130 section. See `The Perils of Floating Point <http://www.lahey.com/float.htm>`_
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
131 for a more complete account of other common surprises.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
132
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
133 As that says near the end, "there are no easy answers." Still, don't be unduly
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
134 wary of floating-point! The errors in Python float operations are inherited
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
135 from the floating-point hardware, and on most machines are on the order of no
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
136 more than 1 part in 2\*\*53 per operation. That's more than adequate for most
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
137 tasks, but you do need to keep in mind that it's not decimal arithmetic, and
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
138 that every float operation can suffer a new rounding error.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
139
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
140 While pathological cases do exist, for most casual use of floating-point
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
141 arithmetic you'll see the result you expect in the end if you simply round the
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
142 display of your final results to the number of decimal digits you expect. For
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
143 fine control over how a float is displayed see the :meth:`str.format` method's
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
144 format specifiers in :ref:`formatstrings`.
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
145
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
146
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
147 .. _tut-fp-error:
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
148
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
149 Representation Error
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
150 ====================
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
151
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
152 This section explains the "0.1" example in detail, and shows how you can
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
153 perform an exact analysis of cases like this yourself. Basic familiarity with
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
154 binary floating-point representation is assumed.
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
155
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
156 :dfn:`Representation error` refers to the fact that some (most, actually)
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
157 decimal fractions cannot be represented exactly as binary (base 2) fractions.
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
158 This is the chief reason why Python (or Perl, C, C++, Java, Fortran, and many
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
159 others) often won't display the exact decimal number you expect::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
160
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
161 >>> 0.1 + 0.2
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
162 0.30000000000000004
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
163
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
164 Why is that? 1/10 and 2/10 are not exactly representable as a binary
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
165 fraction. Almost all machines today (July 2010) use IEEE-754 floating point
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
166 arithmetic, and almost all platforms map Python floats to IEEE-754 "double
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
167 precision". 754 doubles contain 53 bits of precision, so on input the computer
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
168 strives to convert 0.1 to the closest fraction it can of the form *J*/2**\ *N*
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
169 where *J* is an integer containing exactly 53 bits. Rewriting ::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
170
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
171 1 / 10 ~= J / (2**N)
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
172
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
173 as ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
174
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
175 J ~= 2**N / 10
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
176
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
177 and recalling that *J* has exactly 53 bits (is ``>= 2**52`` but ``< 2**53``),
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
178 the best value for *N* is 56::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
179
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
180 >>> 2**52
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
181 4503599627370496
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
182 >>> 2**53
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
183 9007199254740992
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
184 >>> 2**56/10
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
185 7205759403792793
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
186
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
187 That is, 56 is the only value for *N* that leaves *J* with exactly 53 bits.
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
188 The best possible value for *J* is then that quotient rounded::
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
189
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
190 >>> q, r = divmod(2**56, 10)
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
191 >>> r
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
192 6
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
193
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
194 Since the remainder is more than half of 10, the best approximation is obtained
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
195 by rounding up::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
196
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
197 >>> q+1
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
198 7205759403792794
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
199
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
200 Therefore the best possible approximation to 1/10 in 754 double precision is
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
201 that over 2\*\*56, or ::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
202
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
203 7205759403792794 / 72057594037927936
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
204
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
205 Note that since we rounded up, this is actually a little bit larger than 1/10;
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
206 if we had not rounded up, the quotient would have been a little bit smaller
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
207 than 1/10. But in no case can it be *exactly* 1/10!
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
208
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
209 So the computer never "sees" 1/10: what it sees is the exact fraction given
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
210 above, the best 754 double approximation it can get::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
211
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
212 >>> .1 * 2**56
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
213 7205759403792794.0
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
214
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
215 If we multiply that fraction by 10\*\*30, we can see the (truncated) value of
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
216 its 30 most significant decimal digits::
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
217
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
218 >>> 7205759403792794 * 10**30 // 2**56
42604
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
219 100000000000000005551115123125L
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
220
9e1529bf0442 Move the 3k reST doc tree in place.
Georg Brandl <georg@python.org>
parents:
diff changeset
221 meaning that the exact number stored in the computer is approximately equal to
63319
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
222 the decimal value 0.100000000000000005551115123125. In versions prior to
a1e2af6537df Update the floating-point section of the tutorial for the short float repr.
Mark Dickinson <dickinsm@gmail.com>
parents: 57428
diff changeset
223 Python 2.7 and Python 3.1, Python rounded this value to 17 significant digits,
63751
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
224 giving '0.10000000000000001'. In current versions, Python displays a value
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
225 based on the shortest decimal fraction that rounds correctly back to the true
c15acd1e916b More tweaks to floating-point section of the tutorial.
Mark Dickinson <dickinsm@gmail.com>
parents: 63319
diff changeset
226 binary value, resulting simply in '0.1'.