Why is the result of below code 0 in python3?
a = "4.15129406851375e+17"
a = float(a)
b = "415129406851375001"
b = float(b)
a-b
Why is the result of below code 0 in python3?
a = "4.15129406851375e+17"
a = float(a)
b = "415129406851375001"
b = float(b)
a-b
Copyright © 2021 Jogjafile Inc.
This happens because both
415129406851375001and4.15129406851375e+17are greater than the integer representational limits of a Cdouble(which is what a Pythonfloatis implemented in terms of).Typically, C
doubles are IEEE 754 64 bit binary floating point values, which means they have 53 bits of integer precision (the last consecutive integer valuesfloatcan represent are2 ** 53 - 1followed by2 ** 53; it can't represent2 ** 53 + 1). Problem is,415129406851375001requires 59 bits of integer precision to store ((415129406851375001).bit_length()will provide this information). When a value is too large for the significand (the integer component) alone, the exponent component of the floating point value is used to scale a smaller integer value by powers of 2 to be roughly in the ballpark of the original value, but this means that the representable integers start to skip, first by 2 (as you require >53 bits), then by 4 (for >54 bits), then 8 (>55 bits), then 16 (>56 bits), etc., skipping twice as far between representable values for each bit of magnitude you have that can't be represented in 53 bits.In your case, both numbers, converted to
float, have an integer value of415129406851374976(print(int(a), int(b))will show you the true integer value; they're too large to have any fractional component), having lost precision in the low digits.If you need arbitrarily precise base-10 floating point math, replace your use of
floatwithdecimal.Decimal(conveniently, your values are already strings, so you don't risk loss of precision between how you type afloatand the actual value stored); the default precision will handle these values, and you can increase it if you need larger values. If you do that, you get the behavior you expected:which outputs
-1. If you echoed it in an interactive interpreter instead of usingprint, you'd seeDecimal('-1'), which is thereprform ofDecimals, but it's numerically-1, and if converted toint, or stringified via any method that doesn't use therepr, e.g.print, it displays as just-1.Try it online!