Abdul Haseeb - 1 year ago 108

Python Question

While doing exercise on the topic of float type to Fraction type conversion in Python 3.52, I found the difference between the two different ways of conversion.

The first method is:

`>>> from fractions import Fraction`

>>> x = 1232.23

>>> f = Fraction(*x.as_integer_ratio())

>>> print(f)

2709702426188841/2199023255552 #Answer

The second method is:

`>>> from fractions import Fraction`

>>> x = 1232.23

>>> f = Fraction(str(x))

>>> print(f)

123223/100 #Answer

I want to know the reason behind these two different answers? Sorry if this is a stupid question , I am new to programming and Python.

Edited: I found a way to convert inaccurate fraction obtained by first method to accurate by

`limit_denominator`

`>>> from fractions import Fraction`

>>> x = 1232.23

>>> f = Fraction(*x.as_integer_ratio())

>>> f = f.limit_denominator(100)

>>> print(f)

123223/100

Answer Source

Yet again it's because floating point numbers aren't stored in base-10 (decimal), but in base-2 (binary).

A number that is finite length in base-10 might be a repeating decimal in base-2. And because floats are a fixed size, that repeating decimal gets truncated, resulting in inaccuracies.

When you use `as_integer_ratio`

for a number that's a repeating decimal in base-2, you will get you a somewhat silly fraction as a result of the slight inaccuracies in the base-10 to base-2 conversion. If you divide those two numbers, the value will be very close to to your original number.

For instance, while 1/10 = 0.1 in base-10 and is not a repeating decimal, it is in fact a repeating decimal in base-2. Just like 1/3 = 0.333... in base-10.

```
>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)
```

If Python's output was exact, you would see this even when you enter just `0.1`

in the prompt, by getting something like 1.00000...01 as the output. But Python *hides* this inaccuracy from you in the general case, leading to confusion.