Reputation: 39859
I stumbled accross some precision "error" when using floating number in Python and when I wanted to play a little with it, I discovered an odd pattern.
This is the little floating issue:
1.15 * 100 # Returns 114.99999999999999
So I tried with * 1
, then * 10
and that number was correct (showing 15, not 14...).
But, when I ran a script to display the multiples of 10 for that number, this is what I found:
lvl = 1
for i in range(0, 15):
lvl = lvl * 10
1.15 * lvl
Showed the following:
11.5 # 10
114.99999999999999 # 100
1150.0 # 1.000
11500.0 # 10.000
114999.99999999999 # 100.000
1150000.0 # 1.000.000
11500000.0 # 10.000.000
114999999.99999999 # 100.000.000
1150000000.0 # 1.000.000.000
11500000000.0 # 10.000.000.000
114999999999.99998 # 100.000.000.000
1150000000000.0 # 1.000.000.000.000
11500000000000.0 # 10.000.000.000.000
114999999999999.98 # 100.000.000.000.000
1150000000000000.0 # 1.000.000.000.000.000
What bothers me, is that the floating number changes from 15 to 14 when the multiplier is "hundreds" of something (hundreds, hundreds of thousands, hundreds of millions, etc).
Why is that? Why hundreds?
Upvotes: 0
Views: 153
Reputation: 222660
When 1.15 is converted to IEEE-754 binary64 format, the result is, in hexadecimal, 0x1.2666666666666. (1.15 is 23/20, and it has a repeating pattern in hexadecimal for the same reason that 2/3 has a repeating pattern in decimal.) Note that this number has 53 bits in its significand, including the final 0 bit—from the leading 1 to the low bit of the final 6, there are 53 bits.
This value is slightly below 1.15; it is 1.149999999999999911182158029987476766109466552734375. When we multiply that by powers of 10, the real-number results are 11.4999…, 114.999…, and so on. The only way we can get a result in which the significant digits are 115 is if the multiplication rounds up when rounding the product to fit in the floating-point format.
Observe that 0x1.2666666666666 has a pattern that repeats every four bits. So, if we rounded this at the last bit, then at the second-to-last bit, then third-to-last, and so on, we would see a pattern repeating every four terms.
However, we multiply by 10, 100, 1000, and so on. Consider that log210 is about 3.322, a little under 3⅓. (Equivalently, 103=1000 is near 210=1024.) So where powers of 10 lie relative to powers of 2 has a pattern repeating every three terms until the fractions add up:
Thus, until the approximation issue disrupts this pattern, the powers of ten form a “every fourth” bit pattern with a cycle of three powers of ten.
(I have omitted some details here—it is actually the powers of five that matter, since they influence the significant digits of the results, and it is those significant digits that must be rounded, not the powers of ten. But this is not a mathematical proof, and cannot be because the pattern does not continue long; it is merely a coincidence in a small region, so this explanation is merely intended to explain the coincidence intuitively.)
So, what we are seeing is that, in the cycle of three terms, two of them round up and produce significant digits of 115, and one of them rounds down and produces 114.999…. It is merely a coincidence and not a deep mathematical truth.
Upvotes: 3