So I think I basically understand how floating-point works and why we can't have "precise" results for some operations.
I got confused by this SO-question, where @MikeMüller suggests rounding.
My understanding is the following.
If we write decimal places it would look like this:1000 100 10 1 . 1/10 1/100 1/1000
It would look like this in binary:8 4 2 1 . 1/2 1/4 1/8
So we store 0.5 or 0.25 or 0.125 precisely in memory but not e.g. 0.3
So why does python output the following:
print(0.1)
print(0.2)
print(0.3)
print(0.1 + 0.2)
>>>0.1
>>>0.2
>>>0.3
>>>0.30000000000000004
I think it should output
>>>0.1
>>>0.2
>>>0.30000000000000004
>>>0.30000000000000004
Where am I wrong?
My Question is NOT a duplicate of Is floating point math broken? because OP does not understand why 0.1+0.2 != 0.3. This is not topic of my question!
Because they're not the same, as 0.1
and 0.2
isn't correctly represented already. So:
>>>print("%.20f" % (0.1+0.2))
0.30000000000000004441
>>>print("%.20f" % 0.3)
0.29999999999999998890
>>>print(0.29999999999999998890)
0.3
So it's all up to the Python rules for printing stuff, especially considering that pure 0.3
representation is much closer to actual 0.3
than 0.1 + 0.2
.
Here's the related excerpt from Python docs:
Interestingly, there are many different decimal numbers that share the same nearest approximate binary fraction. For example, the numbers
0.1
and0.10000000000000001
and0.1000000000000000055511151231257827021181583404541015625
are all approximated by3602879701896397 / 2 ** 55
. Since all of these decimal values share the same approximation, any one of them could be displayed while still preserving the invarianteval(repr(x)) == x
.Historically, the Python prompt and built-in
repr()
function would choose the one with 17 significant digits,0.10000000000000001
. Starting with Python 3.1, Python (on most systems) is now able to choose the shortest of these and simply display0.1
.
From the docs on floating point in Python 3,
Interestingly, there are many different decimal numbers that share the same nearest approximate binary fraction. For example, the numbers 0.1 and 0.10000000000000001 and 0.1000000000000000055511151231257827021181583404541015625 are all approximated by 3602879701896397 / 2 ** 55. Since all of these decimal values share the same approximation, any one of them could be displayed while still preserving the invariant eval(repr(x)) == x.
Historically, the Python prompt and built-in repr() function would choose the one with 17 significant digits, 0.10000000000000001. Starting with Python 3.1, Python (on most systems) is now able to choose the shortest of these and simply display 0.1.
So that is why it shows 0.3
when it can -- because that is the shortest string that is stored as that binary representation. The slightly higher result of 0.1 + 0.2
cannot be shown as a shorter string than 0.30000000000000004
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With