[Python-ideas] Python Float Update
jim.witschey at gmail.com
Mon Jun 1 05:21:36 CEST 2015
Teachable moments about the implementation of floating-point aside,
something in this neighborhood has been considered and rejected before, in
PEP 240. However, that was in 2001 - it was apparently created the same day
as PEP 237, which introduced transparent conversion of machine ints to
bignums in the int type.
I think hiding hardware number implementations has been a success for
integers - it's a far superior API. It could be for rationals as well.
Has something like this thread's original proposal - interpeting
decimal-number literals as fractional values and using fractions as the
result of integer arithmetic - been seriously discussed more recently than
PEP 240? If so, why haven't they been implemented? Perhaps enough has
changed that it's worth reconsidering.
On Sun, May 31, 2015 at 22:49 Chris Angelico <rosuav at gmail.com> wrote:
> On Mon, Jun 1, 2015 at 12:25 PM, u8y7541 The Awesome Person
> <surya.subbarao1 at gmail.com> wrote:
> > I will be presenting a modification to the float class, which will
> improve its speed and accuracy (reduce floating point errors). This is
> applicable because Python uses a numerator and denominator rather than a
> sign and mantissa to represent floats.
> > First, I propose that a float's integer ratio should be accurate. For
> example, (1 / 3).as_integer_ratio() should return (1, 3). Instead, it
> returns(6004799503160661, 18014398509481984).
> I think you're misunderstanding the as_integer_ratio method. That
> isn't how Python works internally; that's a service provided for
> parsing out float internals into something more readable. What you
> _actually_ are working with is IEEE 754 binary64. (Caveat: I have no
> idea what Python-the-language stipulates, nor what other Python
> implementations use, but that's what CPython uses, and you did your
> initial experiments with CPython. None of this discussion applies *at
> all* if a Python implementation doesn't use IEEE 754.) So internally,
> 1/3 is stored as:
> 0 <-- sign bit (positive)
> 01111111101 <-- exponent (1021)
> 0101010101010101010101010101010101010101010101010101 <-- mantissa (52
> bits, repeating)
> The exponent is offset by 1023, so this means 1.010101.... divided by
> 2²; the original repeating value is exactly equal to 4/3, so this is
> correct, but as soon as it's squeezed into a finite-sized mantissa, it
> gets rounded - in this case, rounded down.
> That's where your result comes from. It's been rounded such that it
> fits inside IEEE 754, and then converted back to a fraction
> afterwards. You're never going to get an exact result for anything
> with a denominator that isn't a power of two. Fortunately, Python does
> offer a solution: store your number as a pair of integers, rather than
> as a packed floating point value, and all calculations truly will be
> exact (at the cost of performance):
> >>> one_third = fractions.Fraction(1, 3)
> >>> one_eighth = fractions.Fraction(1, 8)
> >>> one_third + one_eighth
> Fraction(11, 24)
> This is possibly more what you want to work with.
> Python-ideas mailing list
> Python-ideas at python.org
> Code of Conduct: http://python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-ideas