Tim Peters <t...@python.org> added the comment:
Thanks, Steven! I'll go on to suggest that the best intro to these issues for Python programmers is in Python's own tutorial: https://docs.python.org/3/tutorial/floatingpoint.html Raymond, `divmod(a, b)[0]` IS the mathematical `floor(a/b)`, where the latter is computed (as if) with infinite precision. Rounding `a/b` to a float _before_ taking the floor is quite different, and was never seriously considered for Python. For one thing, the result is ill-defined unless you control the rounding mode used by HW float division (4.0 / 0.4 == 10.0 only if the rounding mode is to-nearest/even or to-plus-infinity; it's 1 ULP less if to-minus-infinity or to-zero; then taking the floor gives 10 in the former cases but 9 in the latter). It makes scant sense for the result of // to depend on rounding mode: the very name - "floor division" - implies rounding is forced. More fundamentally, a = (a // b)*b + (a % b) is the invariant Guido was most keen to preserve. In any conforming C implementation (by the standard today, but by best practice at the time), fmod(4.0, 0.4) == 0.3999999999999998 on a box with 754 doubles, and Python had no interest in building its own idea of "mod" entirely from scratch. Given that, 4 // 0.4 has to return 9. That said, C's fmod makes more sense for floats than Python's % (which latter makes more sense for integers than C's integer %), because fmod is always exact. Python's float % cannot be, because it retains the sign of the modulus: in, e.g., 1 % -1e100, there is no mathematical integer `n` such that the mathematical 1 + n*-1e100 is both negative and representable as a float. >>> 1 % -1e100 -1e+100 # negative, but not exactly 1 + 1*-1e100 >>> math.fmod(1, -1e100) 1.0 # is exactly 1 + 0*-1e100, but not negative In any case, none of this is going to change after 30 years ;-) For Python 3 I had thought Guido agreed to change a % b for floats to return an exact result (exactly equal to the mathematical a - q*b for some mathematical integer q) such that abs(a % b) <= abs(b)/2, which is most useful most often for floats. But that didn't happen. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue36028> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com