I was looking at the Python documentation of fractions
and trying this code:
from fractions import Fraction
>>> print("Fraction (0.5):", Fraction(0.5))
Fraction (0.5): 1/2
>>> print("Fraction (0.1):", Fraction(0.1))
Fraction (0.1): 3602879701896397/36028797018963968
>>> print(1/10)
0.1
Looking at the Fraction(0.1)
result I thought it was my computer problem, but when I tried it on several computers the results were same.
My question
3602879701896397/36028797018963968
instead of 1/10
just like 1/2
as it chosen for Fraction(0.5)
.Yes, that's because that's the integer ration for the float 0.1
(which can't be represented exactly with floats):
>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)
>>> '{:.30f}'.format(0.1) # just to show that it can't be represented exactly I print 30 digits of 0.1
'0.100000000000000005551115123126'
If you want correct Fraction
s you need to use both arguments or pass in a string:
>>> Fraction(1, 10)
Fraction(1, 10)
>>> Fraction('0.1')
Fraction(1, 10)
Or limit the denominator after creating it from a float (not guaranteed to work in all cases):
>>> Fraction(0.1).limit_denominator()
Fraction(1, 10)
As for your second question: There are infinitely many rational numbers (decimal numbers that could be represented exactly as Fraction) in math but a computer uses 64bits for double
s (the Python float
type). That means only a few real numbers can have an exact representation as double
. So there are a lot of other numbers with the same problem, just to name a few:
>>> Fraction(0.2)
Fraction(3602879701896397, 18014398509481984)
>>> Fraction(0.3)
Fraction(5404319552844595, 18014398509481984)
>>> Fraction(1/3)
Fraction(6004799503160661, 18014398509481984)