Another issue is the numerical range. Consider the input "1.5e-318". It causes overflow in the float, decimal, and fraction implementations I gave:
% python frac.py 1.5e-318 --method float
Using float64 for '1.5e-318'
Traceback (most recent call last):
File "frac.py", line 40, in <module>
print("solution:", to_frac(Q))
File "tmp.py", line 31, in to_frac
Dc = Db * int(Zb) + Da
OverflowError: cannot convert float infinity to integer
% python frac.py 1.5e-318 --method fraction
Using fractions for '1.5e-318'
1/666666666... many 6s removed ...6666 = 1/666666666... many 6s removed ...6666
(diff: -1/666 .. more 6s removed ... 6600.. even more zeros removed ...00)
Traceback (most recent call last):
File "frac.py", line 40, in <module>
print("solution:", to_frac(Q))
File "frac.py", line 35, in to_frac
if float(N) / float(Dc) == float(X):
OverflowError: int too large to convert to float
while with the mediant solution I don't need to worry about the input range beyond infinity and NaN:
>>> from fractions import Fraction
>>> Fraction(1.5e-318).limit_denominator(1000000)
Fraction(0, 1)
(I used the float() calls to ensure the fraction and decimal methods stop at the limits of float64. If I remove them I still end up with numbers like 3/2E319 which would not be representable as a Turbo Pascal integer, while the Turbo Pascal mediant implementation would not have a problem.)
Finally, the mediant solution is easier to implement.
Yes, you can stop the algorithm at a certain accuracy, but that doesn't mean you can't get better for that given accuracy.
Consider the pi = 3.14159265359 case, and you want it precise to 1/1,000,000. The float64 algorithm gives 1146408/364913 or 5419351/1725033 because:
The mediant method, on the other hand, gives an intermediate solution: That's a difference of -1.3495871087343403e-12 which is more accurate than 1146408/364913, and is not a solution found by the other algorithm.Or, if you want a denominator of 364913 or 1725033 you can do that with mediants:
Another issue is the numerical range. Consider the input "1.5e-318". It causes overflow in the float, decimal, and fraction implementations I gave: while with the mediant solution I don't need to worry about the input range beyond infinity and NaN: (I used the float() calls to ensure the fraction and decimal methods stop at the limits of float64. If I remove them I still end up with numbers like 3/2E319 which would not be representable as a Turbo Pascal integer, while the Turbo Pascal mediant implementation would not have a problem.)Finally, the mediant solution is easier to implement.