> > > [Tim] >> 1. Python's float "%" is unsuitable for argument reduction; e.g., > >> > >> >>> -1e-14 % 360.0 > >> 360.0 > >> > >> `math.fmod` is suitable, because it's exact: > >> > >> >>> math.fmod(-1e-14, 360.0) > >> -1e-14 >
> [Greg Ewing] > So why doesn't float % use math.fmod? > [Chris Angelico] > > https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations > https://docs.python.org/3/reference/expressions.html#id17 > https://docs.python.org/3/reference/expressions.html#id18 > > (the latter two being footnotes from the section in the first link) > > With real numbers, divmod (and thus the // and % operators) would > always return values such that: > > div, mod = divmod(x, y): > 1) div*y + mod == x > 2) sign(mod) == sign(y) > 3) 0 <= abs(mod) < abs(y) > > But with floats, you can't guarantee all three of these. The divmod > function focuses on the first, guaranteeing the fundamental arithmetic > equality, but to do so, it sometimes has to bend the third one and > return mod==y. > > It's more that #2 is viewed as fundamental (because that's most useful for positive integer y), and _given that_ sometimes results are fiddled to keep #1 approximately true, and strict inequality in #3 may be sacrificed. For `fmod`, sign(mod) == sign(x) instead. >>> -2 % 3 1 >>> -2.0 % 3.0 1.0 >>> math.fmod(-2.0, 3.0) -2.0 All mod functions, m(x, y), strive to return a result that's mathematically exactly equal to x-n*y (for some mathematical integer `n` that may not even be representable in the programming language). `fmod()` is exact in that sense, but Python's floating "%" may not be. and no float scheme such that sign(m(x, y)) = sign(y) can be (see the original example at the top: the only mathematical integer `n` such that the mathematical -1e-14 - n*360.0 is exactly representable as a double is n==0). The most useful mod function for floats _as floats_ would actually satisfy abs(m(x, y)) <= abs(y) / 2 That can be done exactly too - but then the sign of the result has approximately nothing to do with the signs of the arguments.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/