Python -- floating point arithmetic

Mark Dickinson dickinsm at gmail.com
Thu Jul 8 17:54:27 EDT 2010


On Jul 8, 9:52 pm, Wolfram Hinderer <wolfram.hinde... at googlemail.com>
wrote:
> JFTR, it works because a+b == a+b (while I don't think that a+b == b+a
> holds for all a and b).

Actually, that's one of the few identities that's safe.  Well, for non-
NaN IEEE 754 floating-point, at any rate.  And assuming that there's
no use of extended precision to compute intermediate results (in which
case one side could conceivably be computed with different precision
from the other;  but that applies to a+b == a+b, too).  And assuming
that no FPE signals occur and halt the program... (e.g., for overflow,
or from doing -inf + inf).  Okay, maybe not that safe, then.  :)

For NaNs, there are two problems:  first, if exactly one of a and b is
a NaN then a+b and b+a will both be NaNs, so a + b == b + a will be
false, even though they're identical.  Second, if a and b are *both*
NaNs, and you're feeling really fussy and care about signs and
payloads, then a + b and b + a won't even necessarily be bitwise
identical:  a + b will have the sign and payload of a, while b + a has
the sign and payload of b.  You can see something similar with the
Decimal module:

>>> Decimal('NaN123') + Decimal('-NaN456')
Decimal('NaN123')
>>> Decimal('-NaN456') + Decimal('NaN123')
Decimal('-NaN456')

Or more directly (just for fun), using the struct module to create
particular nans:

>>> import struct
>>> x = struct.unpack('<d', '\xff\xff\xff\xff\xff\xff\xff\xff')[0]
>>> y = struct.unpack('<d', '\xfe\xff\xff\xff\xff\xff\xff\xff')[0]
>>> x
nan
>>> y
nan
>>> struct.pack('<d', x+y)   # identical to x
'\xff\xff\xff\xff\xff\xff\xff\xff'
>>> struct.pack('<d', y+x)   # identical to y
'\xfe\xff\xff\xff\xff\xff\xff\xff'

Isn't floating-point a wonderful thing.  :)

--
Mark


--
Mark



More information about the Python-list mailing list