division of integers should result in fractions not floats
Hi list, when dividing two integers, the result is a float, which means we immediately lose precision. This is not good if you want to use code which supports higher precision. Decimals come to mind, but also sympy. This loss of precision could be avoided if the result of a division is a fraction instead: a fraction is exact. So when writing Decimal(1/3), currently we lose the precision in the division, something that the Decimal module cannot undo. With my proposal, the entire precision is retained, and it works as expected. This is even more clear for sympy, a Package for symbolic calculations: currently, sympy cannot do much about "1/2 * m * v**2", although it looks like a perfectly fine formula. But sympy only sees "0.5" instead of "1/2", which is not usable in symbolic calculations. I am aware that this would be a huge change. But we have had such a change in the past, from integers having a floor division in Python 2, to a float in Python 3. Compared to this, this is actually a small change: the value of the result is only different by the small pecision loss of floats. The bigger problem is caused by the fact that some code may rely on the fact that a value is a float. This can be fixed easily by simply calling float(), which is also backwards-compatible, it will work on older versions of Python as well. I have prototyped this here: https://github.com/tecki/cpython/tree/int-divide-fraction The prototype uses the fractions.Fraction class written in Python as result for integer true divisions. I expected that to go horribly wrong, but astonishingly it did not. Only a small number of tests of Python fail, mostly those where it is explicitly tested whether an object is a float. So I lowered the bar even more and tried to compile and test numpy. And also there, except some tests that very explicitly require floats, it worked fine. In order to showcase how that would look like, let me give an example session: >>> 5/6-4/15 17/30 >>> a=22/7 >>> f"{a}" '22/7' >>> f"{a:f}" '3.142857' >>> from decimal import Decimal >>> Decimal(1/3) Decimal('0.3333333333333333333333333333') As a comparison, the same with current Python: >>> 5/6-4/15 0.5666666666666667 >>> a=22/7 >>> f"{a}" '3.142857142857143' >>> f"{a:f}" '3.142857' >>> from decimal import Decimal >>> Decimal(1/3) Decimal('0.333333333333333314829616256247390992939472198486328125') Cheers Martin
participants (24)
-
André Roberge
-
Chris Angelico
-
Christopher Barker
-
David Mertz
-
Eric V. Smith
-
Ethan Furman
-
Guido van Rossum
-
Ir. Robert Vanden Eynde
-
Joao S. O. Bueno
-
Jonathan Fine
-
Martin Teichmann
-
Michael Smith
-
micro codery
-
Oscar Benjamin
-
Paul Bryan
-
Paul Moore
-
Richard Damon
-
Ricky Teachey
-
Rob Cliffe
-
Sergey B Kirpichev
-
Serhiy Storchaka
-
Shreyan Avigyan
-
Stephen J. Turnbull
-
Steven D'Aprano