如何将浮点数转换为比率?

如何将浮点数转换为比率?

我想将浮点数转换为比率或分数。

我们是否可以选择将浮点数转换1.778为比率,16:9或者16/9在 bash 中,以类似于 Python 的方式分数模块( Fraction(1.778).limit_denominator(100))。

答案1

awk -v prec=0.001 -v max=2000 '
   function fract(n, k, kr, d){
       for(k=n;k<max;k+=n){
           kr=int(k+.5); d=kr-k; if(d<0)d=-d;
           if(d<prec){return kr"/"k/n}
       }
       return n" ??"
   }
   BEGIN{for(i=1;i<ARGC;i++)print fract(ARGV[i])}
' 3.1415926535 1.77777777 0.333333 2.71828 1.61803398
355/113
16/9
1/3
1264/465
987/610

通过乘法而不是重复加法可以使其更加精确,但这也可能会使速度变慢:

awk -v prec=0.00005 -v max=20000 '
   function fract(n, k, kr, kf, d){
       for(k=1;k<max;k++){
           kf=n*k; kr=int(kf+.5); d=kr-kf; if(d<0)d=-d;
           if(d<prec){return kr"/"k}
       }
       return n" ??"
   }
   BEGIN{for(i=1;i<ARGC;i++)print fract(ARGV[i])}
' 3.14159265358979323846 1.7777777 0.33333333 2.7182818 1.61803398
355/113
16/9
1/3
34109/12548
24476/15127

max“可调”实际上是max_numerator / orig_num在第二个版本中)。

答案2

无论迂腐与否,如果我们的人只关注小数点后 3 位的精度……

打破旧awk锤子,打造同样优秀的老式锤子最低分母,而不是高调的算法,只需找到最低的误差和分母

echo "1.778" | awk 'BEGIN{en=1; de=101; er=1}{
    for (d=100; d>=1; d--) {n=int(d*$1); e=n/d-$1; e=e*e;
    if (e<=er && d<de){er=e; de=d; en=n}}
    print en":"de, en/de}'

所以...

16:9 1.77778

bash像这样的事情同样可以用适当的分数乘数来纯粹地完成。

如果我们要参加比赛

real    0m0.004s
user    0m0.001s
sys     0m0.003s

答案3

16 / 9 不是 1.778。它是(到50个地方):

1.77777777777777777777777777777777777777777777777777

相反,16.002 / 9 实际上正好是 1.778。

因此,事实上不可能存在恰好是 16 / 9 的数字(至少不是以 10 为基数并且位数有限)。

您需要在近似值中定义可接受的准确度水平。

我的第一个强力算法是在 A 和 B 中尝试双循环,计算 A / B,并在精确到(可能)6 位数字时停止。

外壳脚本:

#! /bin/bash

function Ratio {

AWK='
function Ratio (min, max, Local, a, b, q) {
    for (a = 1; a < 1e6; a++) {
        for (b = 1; b <= a; b++) {
            q = (a / b);
            if (min < q && q < max) {
                printf ("Ratio %d / %d is %.12f\n", a, b, q);
                return;
            }
        }
    }
}
{ Ratio( $1, $2); }
'   
    awk "${AWK}"
}

    {
        echo 2.8897 2.8899
        echo 1.77777777777 1.77777777778 
        echo 3.14159292 3.14159293
    } | Ratio

这里是应用程序:

paul $ time ./Ratio
Ratio 341 / 118 is 2.889830508475
Ratio 16 / 9 is 1.777777777778
Ratio 355 / 113 is 3.141592920354

real    0m0.085s
user    0m0.072s
sys     0m0.012s

显然,如果从 1.778 (> 1) 开始,则没有必要检查 A <= B 的任何情况。这表明存在一系列基于连续分数的近似值。所以我的第二个算法是找到构造收敛到指定值的无限级数的通用方法。但前提是我必须处理大量案件。

相关内容