Re: [Pythonideas] Pythonideas Digest, Vol 103, Issue 10
Thanks Stefan for quicktions!
On Mon, Jun 1, 2015 at 1:18 PM, pythonideasrequest@python.org wrote:
Send Pythonideas mailing list submissions to pythonideas@python.org
To subscribe or unsubscribe via the World Wide Web, visit https://mail.python.org/mailman/listinfo/pythonideas or, via email, send a message with subject or body 'help' to pythonideasrequest@python.org
You can reach the person managing the list at pythonideasowner@python.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Pythonideas digest..."
Today's Topics:
 Re: Pythonideas Digest, Vol 103, Issue 3 (u8y7541 The Awesome Person)
 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: pythonideas@python.org Subject: Re: [Pythonideas] Pythonideas Digest, Vol 103, Issue 3 MessageID: <CA+o1fZMHxNybOjMWr7Uqk8= AKBncpAKXy+QO+vhF8ENtAXL6qg@mail.gmail.com> ContentType: text/plain; charset="utf8"
Maybe we could make a C implementation of the Fraction module? That would be nice.
On Sun, May 31, 2015 at 8:28 PM, pythonideasrequest@python.org wrote:
Send Pythonideas mailing list submissions to pythonideas@python.org
To subscribe or unsubscribe via the World Wide Web, visit https://mail.python.org/mailman/listinfo/pythonideas or, via email, send a message with subject or body 'help' to pythonideasrequest@python.org
You can reach the person managing the list at pythonideasowner@python.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Pythonideas digest..."
Today's Topics:
 Re: Python Float Update (Chris Angelico)
 Re: Python Float Update (random832@fastmail.us)
 Re: Python Float Update (Jim Witschey)
 Re: Python Float Update (David Mertz)
Message: 1 Date: Mon, 1 Jun 2015 12:48:12 +1000 From: Chris Angelico rosuav@gmail.com Cc: pythonideas pythonideas@python.org Subject: Re: [Pythonideas] Python Float Update MessageID: <CAPTjJmr=LurRUoKH3KVVYpMFc= W5h6etG5TscV5uU6zWhxVbgQ@mail.gmail.com> ContentType: text/plain; charset=UTF8
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 Pythonthelanguage 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 finitesized 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: pythonideas@python.org Subject: Re: [Pythonideas] Python Float Update MessageID: <1433128446.31560.283106753.6D60F98F@webmail.messagingengine.com
ContentType: 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: pythonideas pythonideas@python.org Subject: Re: [Pythonideas] Python Float Update MessageID: <CAF+a8q6kbOwcWk3F47+9PXf2vKgM9ao1uh5=qBw10jqzTC= kg@mail.gmail.com> ContentType: text/plain; charset="utf8"
Teachable moments about the implementation of floatingpoint 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 decimalnumber 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 Pythonthelanguage 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 finitesized 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 _______________________________________________ Pythonideas mailing list Pythonideas@python.org https://mail.python.org/mailman/listinfo/pythonideas Code of Conduct: http://python.org/psf/codeofconduct/
participants (1)

u8y7541 The Awesome Person