请看Rosetta Code的
"将十进制数转换为有理数"。由于我不熟悉C语言,所以我将那里的C代码转换为Python(尽管我认为Python可能有一些相关的库),并添加了几个函数,您可以轻松地将它们适应到C中。如果分数转换中的分母全部为
1.0
,则我们将数字列表的最大公约数除以它。否则,我们返回唯一分母的乘积。
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)
输出:
f([8, 10])
=> 0.5
f([1.66667, 2.33333])
=> 3.0
5
结尾的小数分数可以被表示为某个二的幂次方的整数:您的输入数据是不精确的,但有少数例外。 - greybeard