将浮点小数转换为分数
2022-08-31 00:01:00
我正在尝试将具有十进制结果的用户键入的计算转换为分数。例如;66.6666666667 转换为 66 2/3。任何指针?提前感恩节
我正在尝试将具有十进制结果的用户键入的计算转换为分数。例如;66.6666666667 转换为 66 2/3。任何指针?提前感恩节
连续分数可用于查找实数的有理近似值,这些实数在严格意义上是“最佳”的。下面是一个 PHP 函数,它查找给定(正)浮点数的有理近似值,相对误差小于:$tolerance
<?php
function float2rat($n, $tolerance = 1.e-6) {
$h1=1; $h2=0;
$k1=0; $k2=1;
$b = 1/$n;
do {
$b = 1/$b;
$a = floor($b);
$aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux;
$aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux;
$b = $b-$a;
} while (abs($n-$h1/$k1) > $n*$tolerance);
return "$h1/$k1";
}
printf("%s\n", float2rat(66.66667)); # 200/3
printf("%s\n", float2rat(sqrt(2))); # 1393/985
printf("%s\n", float2rat(0.43212)); # 748/1731
我已经写了更多关于这个算法以及它为什么工作,甚至在这里写了一个JavaScript演示:https://web.archive.org/web/20180731235708/http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
在这种情况下,Farey分数可能非常有用。
它们可用于将任何小数转换为具有尽可能低分母的分数。
抱歉 - 我没有PHP的原型,所以这里有一个Python的原型:
def farey(v, lim):
"""No error checking on args. lim = maximum denominator.
Results are (numerator, denominator); (1, 0) is 'infinity'."""
if v < 0:
n, d = farey(-v, lim)
return (-n, d)
z = lim - lim # Get a "zero of the right type" for the denominator
lower, upper = (z, z+1), (z+1, z)
while True:
mediant = (lower[0] + upper[0]), (lower[1] + upper[1])
if v * mediant[1] > mediant[0]:
if lim < mediant[1]:
return upper
lower = mediant
elif v * mediant[1] == mediant[0]:
if lim >= mediant[1]:
return mediant
if lower[1] < upper[1]:
return lower
return upper
else:
if lim < mediant[1]:
return lower
upper = mediant