Inexact representation cases (Re: Against PEP 240)
Tim Peters
tim.one at home.com
Sat Jun 2 16:13:51 EDT 2001
[Clark C . Evans]
> >>> 1.1
> 1.1000000000000001
> >>> 7.35
> 7.3499999999999996
>
> What is the general pattern for these types
> of inexact represenatation?
Unsure what you're looking for. In general, a non-zero decimal number D is
exactly representable in a binary fp format if and only it can be written in
the form
D = I/2**J
for some (possibly large) integers I and J, and where the possible values of
I and J are constrained by how many bits the fp format devotes to them. For
IEEE-754 doubles (which is what a Python float becomes on most machines), it
must have 1 <= I < 2**53 (that is, I has no more than 53 bits), and the
range on J is roughly plus or minus 1000 (yes, it can be made exact, but who
cares <wink>).
So look at 1.1 == 11/10. Can that be written in the form I/2**J? If so,
then 11*2**J == 10*I too. 5 divides 10 evenly, so also divides 10*I. But
if 10*I == 11*2**J and 5 divides the left side, then 5 must also divide the
right side. But 5 doesn't divide 11 or 2**J, so can't (because 5 is prime)
divide their product evenly either. IOW, no matter how many bits you use,
1.1 can't be represented exactly in a binary fp format.
It turns out that the closest you can get in IEEE double is
1.1 ~= 2476979795053773 / 2**51
which is, as a *decimal* number, *exactly*
1.100000000000000088817841970012523233890533447265625
*Rounding* that to 17 significant decimal digits is where
1.10000000000000001
comes from in the display.
Similarly the best double approximation to 7.35 is
4137682157646643 / 2**49
which is exactly
7.3499999999999996447286321199499070644378662109375
in decimal, which rounds to
7.3499999999999996
for display. Note that the situation isn't symmetric: not every finite
decimal fraction is exactly representable as a finite base 2 fraction, but
every finite binary fraction *is* exactly representable as a finite base 10
fraction (if you start with I/2**J, just multiply top and bottom by 5**J to
get (I*5**J)/10**J). But afraid that's just another stumbling block at
first ...
More information about the Python-list
mailing list