Inverse confusion about floating point precision
Bengt Richter
bokr at oz.net
Mon May 9 23:27:00 EDT 2005
On 9 May 2005 11:06:22 -0700, "Dan Bishop" <danb_83 at yahoo.com> wrote:
>Skip Montanaro wrote:
>> I understand why the repr() of float("95.895") is
>"95.894999999999996".
>> What I don't understand is why if I multiply the best approximation
>to
>> 95.895 that the machine has by 10000 I magically seem to get the lost
>> precision back. To wit:
>>
>> % python
>> Python 2.3.4 (#12, Jul 2 2004, 09:48:10)
>> [GCC 3.3.2] on sunos5
>> Type "help", "copyright", "credits" or "license" for more
>information.
>> >>> 95.895
>> 95.894999999999996
>> >>> 95.895 * 10000
>> 958950.0
>>
>> Why isn't the last result "958949.99999999996"? IOW, how'd I get
>back the
>> lost bits?
>
>You were just lucky.
>
>The floating-point representation of 95.895 is exactly 6748010722917089
>* 2**-46.
>
>Multiplying by 10000 gives you 67480107229170890000 * 2**-46. But
>floats can have only 53 significant bits, so this gets normalized to
>8237317776998399.658203125 * 2**-33 and rounded to 8237317776998400 *
>2**-33, which happens to be exactly equal to 958950.
>
>For analogy, consider a decimal calculator with only 3 significant
>digits. On this calculator, 1/7=0.143, an error of 1/7000.
>Multiplying 0.143 by 7 gives 1.001, which is rounded to 1.00, and so
>you get an exact answer for 1/7*7 despite roundoff error in the
>intermediate step.
>
In bits, the above appears as
>>> prb(95.895)
'1011111.1110010100011110101110000101000111101011100001'
>>> len(prb(95.895).split('.')[1])
46
>>> prb(95.895*2**46)
'10111111110010100011110101110000101000111101011100001'
>>> int(prb(95.895*2**46),2)
6748010722917089L
>>> int(prb(95.895*2**46),2)*10000
67480107229170890000L
>>> prb(int(prb(95.895*2**46),2)*10000)
'111010100001111001011111111111111111111111111111111111010100010000'
>>> prb(int(prb(95.895*2**46),2)*10000)[:53]
'11101010000111100101111111111111111111111111111111111'
>>> int(prb(int(prb(95.895*2**46),2)*10000),2)/2.**46
958950.0
>>> prb(int(prb(int(prb(95.895*2**46),2)*10000),2)/2.**46)
'11101010000111100110'
Regards,
Bengt Richter
More information about the Python-list
mailing list