[Python-3000] bug in modulus?
Tim Peters
tim.peters at gmail.com
Thu May 4 21:07:23 CEST 2006
[Guido]
> This is way above my head. :-)
Of course it's not, but the issues are subtle and messy enough that
it's a burden to make sufficient time for them. I'm sympathetic to
that ;-)
> The only requirement *I* would like to see is that for floats that
> exactly represent ints (or longs for that matter) the result ought of
> x%y ought to have the same value as the same operation on the
> corresponding ints (except if the result can't be represented exactly
> as a float -- I don't know what's best then).
>
> We're fixing this for / in Py3k, so passing an int into an algorithm
> written for floats won't be harmful and won't require defensiev
> float() casting everywhere. It would be a shame if we *introduced* a
> new difference between ints and floats for %.
I'm sympathetic to that too. I explained in detail in a different
message why the C99 definition of % is a much better definition for
floats, and why the Python-int flavor of % cannot (as in "impossible,
not even in theory") meet all reasonable integer-derived expectations
when applied to floats.
If Python switched to C99's definition of % for both integers and
floats, that would work out better so far as it goes. But Python's %
makes much more sense for integers, so that would be a flea on the
tail of the dog wagging the guy walking the dog (float % is rare in
real life).
A variant on what you sketched above would be an odd but probably
workable compromise: keep __mod__ and __divmod__ for floats, but make
them exceptional when the arguments aren't exact integers, or the
result can't be represented exactly as a float (e.g., -1.0 %
2.0**100). Then if someone uses "small enough" integers that happen
to be in floating format, % and divmod work and deliver the same
result as integer %/divmod. If floating %/divmod are allowed to
return longs, then cases like -1.0 % 2.0**100 could also deliver
surprise-free results (although that seems so useless, given that the
_inputs_ were floats, I'd rather raise an exception).
The surprise comes when they apply % or divmod to a non-integral
float, and then the exception can clearly point to a spelling of mod
that makes sense for floats (math.fmod already does -- that's the C99
float %). That spelling can't have the same definition as integer %,
but since you have to explicitly ask for it I don't see that as a real
problem.
The decimal module should change to the same kind of approach, whatever it is:
>>> from decimal import Decimal as D
>>> D(-1) % D(2)
Decimal("-1")
is already inconsistent with -1 % 2.
BTW, this came up on c.l.py earlier this week:
>>> from math import atan2
>>> atan2(-0, -1)
3.1415926535897931
>>> atan2(-0.0, -1)
-3.1415926535897931
Gotta love signed zeroes :-(
More information about the Python-3000
mailing list