Mark Dickinson <dicki...@gmail.com> added the comment: > Mark, I tried `Fraction(10**23) // 1e22`, and I got 10.
Sorry: that result was with your PR (as it was at the time I wrote that comment). On master, you do indeed get 10. > I think the fact that floating-point rounding error sometimes causes > strange results is not a reason to do really unexpected things like > making 1.0 // 1/10 equal 9.0, if that can be reasonably avoided. I understand, but I think in this case, the cure is worse than the disease. I don't think converting the float to a Fraction in mixed-type operations is going to work, for a number of reasons: - it's changing the behaviour for _all_ the arithmetic operations, not just // and %; that widens the scope for accidental breakage. For example, with the latest commit 038664e6a6288f6113ab96103e57d3b25b39a8c2 on your PR: >>> Fraction(1) + math.inf inf >>> math.inf + Fraction(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/mdickinson/Python/cpython/Lib/fractions.py", line 391, in reverse return float(fallback_operator(Fraction(a), b)) File "/Users/mdickinson/Python/cpython/Lib/fractions.py", line 130, in __new__ self._numerator, self._denominator = numerator.as_integer_ratio() OverflowError: cannot convert Infinity to integer ratio But on master, we have: >>> import math >>> from fractions import Fraction >>> math.inf + Fraction(1) inf >>> Fraction(1) + math.inf inf - it's counter to the spirit of the numeric tower, where for most arithmetic operations, values are propagated _up_ the tower (from Integral -> Rational -> Real -> Complex) to the first common type before the operation is performed. That keeps things simple; having some cases where values are converted down the tower is going to cause confusion. (Comparisons are necessarily a special case: the need to preserve transitivity of equality and trichotomy means that using the same rules as for arithmetic operations won't fly) - it introduces a non-obvious difference between mixed-mode Fraction-float and int-float operations. For an int x and a float y, I'd expect the result of `x <some_op> y` to be identical to the result of `Fraction(x) <some_op> y`. So I'm sorry, but I do think having 1.0 // Fraction(1, 10) give 9.0 rather than 10.0 is the least worst option here. It's a surprise, but it's not a _new_ surprise: it's a surprise that's already there in the world of floating-point arithmetic. >>> 1.0 // 0.1 9.0 You're evaluating a discontinuous function _at_ a discontinuity, using a type that's known for its inexactness. In that situation, getting the value for _either_ side of that discontinuity is reasonable. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue32968> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com