<div>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.<br><br>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.<br><br>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.</div><br><br><div class="gmail_quote">On Sun, May 31, 2015 at 22:49 Chris Angelico <<a href="mailto:rosuav@gmail.com" target="_blank">rosuav@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Mon, Jun 1, 2015 at 12:25 PM, u8y7541 The Awesome Person<br>
<<a href="mailto:surya.subbarao1@gmail.com" target="_blank">surya.subbarao1@gmail.com</a>> wrote:<br>
><br>
> 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.<br>
><br>
> 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).<br>
><br>
<br>
I think you're misunderstanding the as_integer_ratio method. That<br>
isn't how Python works internally; that's a service provided for<br>
parsing out float internals into something more readable. What you<br>
_actually_ are working with is IEEE 754 binary64. (Caveat: I have no<br>
idea what Python-the-language stipulates, nor what other Python<br>
implementations use, but that's what CPython uses, and you did your<br>
initial experiments with CPython. None of this discussion applies *at<br>
all* if a Python implementation doesn't use IEEE 754.) So internally,<br>
1/3 is stored as:<br>
<br>
0 <-- sign bit (positive)<br>
01111111101 <-- exponent (1021)<br>
0101010101010101010101010101010101010101010101010101 <-- mantissa (52<br>
bits, repeating)<br>
<br>
The exponent is offset by 1023, so this means 1.010101.... divided by<br>
2²; the original repeating value is exactly equal to 4/3, so this is<br>
correct, but as soon as it's squeezed into a finite-sized mantissa, it<br>
gets rounded - in this case, rounded down.<br>
<br>
That's where your result comes from. It's been rounded such that it<br>
fits inside IEEE 754, and then converted back to a fraction<br>
afterwards. You're never going to get an exact result for anything<br>
with a denominator that isn't a power of two. Fortunately, Python does<br>
offer a solution: store your number as a pair of integers, rather than<br>
as a packed floating point value, and all calculations truly will be<br>
exact (at the cost of performance):<br>
<br>
>>> one_third = fractions.Fraction(1, 3)<br>
>>> one_eighth = fractions.Fraction(1, 8)<br>
>>> one_third + one_eighth<br>
Fraction(11, 24)<br>
<br>
This is possibly more what you want to work with.<br>
<br>
ChrisA<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a></blockquote></div>