Re: [Python-ideas] Python-ideas Digest, Vol 103, Issue 10
Thanks Stefan for quicktions! On Mon, Jun 1, 2015 at 1:18 PM, <python-ideas-request@python.org> wrote:
Send Python-ideas mailing list submissions to python-ideas@python.org
To subscribe or unsubscribe via the World Wide Web, visit https://mail.python.org/mailman/listinfo/python-ideas or, via email, send a message with subject or body 'help' to python-ideas-request@python.org
You can reach the person managing the list at python-ideas-owner@python.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Python-ideas digest..."
Today's Topics:
1. Re: Python-ideas Digest, Vol 103, Issue 3 (u8y7541 The Awesome Person) 2. Re: Python Float Update (Stefan Behnel)
----------------------------------------------------------------------
Message: 1 Date: Mon, 1 Jun 2015 12:22:40 -0700 From: u8y7541 The Awesome Person <surya.subbarao1@gmail.com> To: python-ideas@python.org Subject: Re: [Python-ideas] Python-ideas Digest, Vol 103, Issue 3 Message-ID: <CA+o1fZMHxNybOjMWr7Uqk8= AKBncpAKXy+QO+vhF8ENtAXL6qg@mail.gmail.com> Content-Type: text/plain; charset="utf-8"
Maybe we could make a C implementation of the Fraction module? That would be nice.
On Sun, May 31, 2015 at 8:28 PM, <python-ideas-request@python.org> wrote:
Send Python-ideas mailing list submissions to python-ideas@python.org
To subscribe or unsubscribe via the World Wide Web, visit https://mail.python.org/mailman/listinfo/python-ideas or, via email, send a message with subject or body 'help' to python-ideas-request@python.org
You can reach the person managing the list at python-ideas-owner@python.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Python-ideas digest..."
Today's Topics:
1. Re: Python Float Update (Chris Angelico) 2. Re: Python Float Update (random832@fastmail.us) 3. Re: Python Float Update (Jim Witschey) 4. Re: Python Float Update (David Mertz)
----------------------------------------------------------------------
Message: 1 Date: Mon, 1 Jun 2015 12:48:12 +1000 From: Chris Angelico <rosuav@gmail.com> Cc: python-ideas <python-ideas@python.org> Subject: Re: [Python-ideas] Python Float Update Message-ID: <CAPTjJmr=LurRUoKH3KVVYpMFc= W5h6etG5TscV5uU6zWhxVbgQ@mail.gmail.com> Content-Type: text/plain; charset=UTF-8
On Mon, Jun 1, 2015 at 12:25 PM, u8y7541 The Awesome Person <surya.subbarao1@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.
ChrisA
------------------------------
Message: 2 Date: Sun, 31 May 2015 23:14:06 -0400 From: random832@fastmail.us To: python-ideas@python.org Subject: Re: [Python-ideas] Python Float Update Message-ID: <1433128446.31560.283106753.6D60F98F@webmail.messagingengine.com
Content-Type: text/plain
On Sun, May 31, 2015, at 22:25, u8y7541 The Awesome Person wrote:
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).
Even though he's mistaken about the core premise, I do think there's a kernel of a good idea here - it would be nice to have a method (maybe as_integer_ratio, maybe with some parameter added, maybe a different method) to return with the smallest denominator that would result in exactly the original float if divided out, rather than merely the smallest power of two.
------------------------------
Message: 3 Date: Mon, 01 Jun 2015 03:21:36 +0000 From: Jim Witschey <jim.witschey@gmail.com> To: Chris Angelico <rosuav@gmail.com> Cc: python-ideas <python-ideas@python.org> Subject: Re: [Python-ideas] Python Float Update Message-ID: <CAF+a8-q6kbOwcWk3F47+9PXf2vKgM9ao1uh5=qBw10jqzTC= kg@mail.gmail.com> Content-Type: text/plain; charset="utf-8"
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@gmail.com> wrote:
On Mon, Jun 1, 2015 at 12:25 PM, u8y7541 The Awesome Person <surya.subbarao1@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.
ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
participants (1)
-
u8y7541 The Awesome Person