bug in modulus?

Tim Peters tim.peters at gmail.com
Sun Apr 23 14:03:20 EDT 2006


[jantod at gmail.com]
> I think there might be something wrong with the implementation of
> modulus.
>
> Negative float values close to 0.0 break the identity "0 <= abs(a % b) < abs(b)".

While that's a mathematical identity, floating point has finite
precision.  Many mathematical identities can fail when using floats. 
For example,

    (x+y)+z = x+(y+z)

doesn't always hold when using floats either.

>     print 0.0 % 2.0 # => 0.0
>     print -1e-010 % 2.0 # =>1.9999999999
>
> which is correct, but:
>
>     print -1e-050 % 2.0 # => 2.0
>     print -1e-050 % 2.0 < 2.0 # => False

See footnote 5.2 in the Language (not Library) reference manual,
section 5.6 "Binary arithmetic operations":

    While abs(x%y) < abs(y) is true mathematically, for floats it may
not be true
    numerically due to roundoff.  For example, and assuming a platform on which
    a Python float is an IEEE 754 double-precision number, in order that
     -1e-100 % 1e100 have the same sign as 1e100, the computed result is
    -1e-100 + 1e100, which is numerically exactly equal to 1e100.
Function fmod()
    in the math module returns a result whose sign matches the sign of the first
    argument instead, and so returns -1e-100 in this case. Which
approach is more
    appropriate depends on the application.

> This means I can't use modulus to "wrap around" before it reaches a
> certain value.

It's simply not possible to deliver a float result in all cases that
satisfies all desirable identities.  % and math.fmod make different
tradeoffs, but neither is suitable for all applications, and it's
possble that the neither is suitable for a particular application --
pick your poison, or brew your own.

> I'm using Python 2.4.2 on WindowsXP.

Because it's inherent to using finite-precision approximations to real
numbers, this is a cross-platorm and cross-language phenomenon.  If
you can't tolerate approximations, rework your logic to use integers
instead.



More information about the Python-list mailing list