Take a look at the Rosetta Code Convert Decimal to Rational. Since I am not versed in C, I converted the C code there to Python (although I think Python can have some appropriate libraries) and added some functions that you could easily adapt to C. If the fraction conversion denominators are everything 1.0, we divide the largest common divisor is a list of numbers. Otherwise, we return the product of unique denominators.
import math
import operator
def f(arr):
epsilon = 4
fractions = [rat_approx(i, 16**epsilon) for i in arr]
if sum([denom for (num, denom) in fractions]) == len(fractions):
return 1.0 / gcd_of_many([num for (num, denom) in fractions])
else:
return reduce(operator.mul, set([denom for (num, denom) in fractions]), 1)
def gcd(a, b):
if a < b:
return gcd(b, a)
elif b == 0:
return a;
else:
return gcd(b, a % b)
def gcd_of_many(arr):
result = arr[0]
for i in xrange(1, len(arr)):
result = gcd(result, arr[i])
return result
def rat_approx(f, md):
h = [0, 1, 0]
k = [1, 0, 0]
n = 1
neg = 0
num = 0
denom = 0
if md <= 1:
denom = 1
num = f
return num, denom
if f < 0:
neg = 1
f = -f
while f != math.floor(f):
n <<= 1
f *= 2
d = f
for i in xrange(65):
a = d // n if n else 0
if i and not a:
break
x = d
d = n
n = x % n
x = a;
if k[1] * a + k[0] >= md:
x = (md - k[0]) // k[1]
if x * 2 >= a or k[1] >= md:
i = 65
else:
break
h[2] = x * h[1] + h[0]
h[0] = h[1]
h[1] = h[2]
k[2] = x * k[1] + k[0]
k[0] = k[1]
k[1] = k[2]
denom = k[1]
num = -h[1] if neg else h[1]
return (num, denom)
Conclusion:
f([8, 10])
=> 0.5
f([1.66667, 2.33333])
=> 3.0
source
share