1

QUESTION:

I would like to convert floats into a ratio of integers in simplest form. (Not a duplicate of this question, see "EDIT" below). For example, 0.1 = 1, 10, 0.66666... = 2, 3, etc. In the code snippet below, I try doing this for x = 0.1, 0.2, ..., 1.0 using this default function; the method only works successfully for x = 0.5 and x = 1.0. Why does this algorithm fail for other values of x and what is a better method to do this? In case it is relevant, my use-case will be for dx ~ 0.0005 = x[1] - x[0] for 0.0005 < x 10.0.

CODE:

import numpy as np

f = np.vectorize(lambda x : x.as_integer_ratio())

x = np.arange(0.1, 1.1, 0.1)
nums, dens = f(x)
for xi, numerator, denominator in zip(x, nums, dens):
    print("\n .. {} = {} / {}\n".format(xi, numerator, denominator))

OUTPUT:

 .. 0.1 = 3602879701896397 / 36028797018963968


 .. 0.2 = 3602879701896397 / 18014398509481984


 .. 0.30000000000000004 = 1351079888211149 / 4503599627370496


 .. 0.4 = 3602879701896397 / 9007199254740992


 .. 0.5 = 1 / 2


 .. 0.6 = 5404319552844595 / 9007199254740992


 .. 0.7000000000000001 = 6305039478318695 / 9007199254740992


 .. 0.8 = 3602879701896397 / 4503599627370496


 .. 0.9 = 8106479329266893 / 9007199254740992


 .. 1.0 = 1 / 1

EDIT:

This is not really a duplicate. Both methods of the accepted answer in the original question fail a basic use-case from my MWE. To show that the Fraction module gives the same error:

import numpy as np
from fractions import Fraction

f = np.vectorize(lambda x : Fraction(x))

x = np.arange(0.1, 1.1, 0.1)
y = f(x)
print(y)

## OUTPUT
[Fraction(3602879701896397, 36028797018963968)
 Fraction(3602879701896397, 18014398509481984)
 Fraction(1351079888211149, 4503599627370496)
 Fraction(3602879701896397, 9007199254740992) Fraction(1, 2)
 Fraction(5404319552844595, 9007199254740992)
 Fraction(6305039478318695, 9007199254740992)
 Fraction(3602879701896397, 4503599627370496)
 Fraction(8106479329266893, 9007199254740992) Fraction(1, 1)]
zeebeel
  • 15
  • 1
  • 4
  • 1
    I guess this is what you want: [Convert a float to a rational number that is guaranteed to convert back to the original float](https://stackoverflow.com/q/66980340/995714) – phuclv Jun 09 '21 at 11:28
  • `Why does this algorithm fail for other values of x` because only 0.5 and 1 are exactly representable in binary floating-point in your range. There's no way to store 0.1 in float and `3602879701896397/36028797018963968` is the closest rerepsentable float. You need a much more complex algorithm to get 1/10 – phuclv Jun 09 '21 at 11:30

0 Answers0