
浮動小数点数を比率または分数に変換したいと思います。
Pythonと同様に浮動小数点を1.778
比率に変換する16:9
か、bashに変換するオプションはありますか?16/9
噴水モジュール(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番目のバージョンにあります)。
答え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.7777777777777777777777777777777777777777777777777
代わりに、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の場合を確認する必要はありません。これは、連続分数に基づく近似系列があることを示唆している。だから私の2番目のアルゴリズムは、指定された値に収束する無限系列を構築する一般的な方法を見つけることです。ただし、多くの場合を処理する必要がある場合にのみ該当します。