シェルで浮動小数点数を丸める方法は?


13

コマンドラインでIEEE 754浮動小数点数を正しく丸めるにはどうすればよいですか?

出力数値の精度-小数桁数を指定したいのですが。

丸め6.66精度にして1与える必要があり6.7、たとえば、。以下の表の詳細:

Value   Precision  Rounded
6.66    0          7
6.66    1          6.7
6.66    2          6.66
6.66    3          6.660
6.666   3          6.666
6.6666  3          6.667

対話型シェルで使用できる必要がありますが、本番シェルスクリプトで使用するには十分に堅牢であることが理想的です。


私は使用しますawk
同型写像

回答:


30

浮動小数点数の丸め

「浮動小数点数の丸め」とはどういう意味ですか?
それは簡単です。明らかに...学校の数学の本はどこにありますか...

いいえ、浮動小数点数に関連するものは何も簡単ではないことがすでにわかっています。

まず、複数の丸めモードがあります。

上向きに丸めますか?
切り下げますか?
ゼロに丸めますか?
最も近い値に丸める-偶数とのつながり?
最も近い値に丸めます-ゼロから離れていますか?

コーナーケースの扱い方は?コーナーケースはどのようにして見つけるのですか?

はい、IEEE 754標準の実装を使用した方がよいようです。システムで処理してください。

標準の浮動小数点演算に基づいて、シェルで浮動小数点数を丸めるには、3つのステップが必要です。

  • 入力テキストをコマンドライン引数から標準の浮動小数点数に変換します。
  • 通常のIEEE 754実装を使用して浮動小数点数を丸めます。
  • 数値を出力用の文字列としてフォーマットします。

シェルコマンドprintfがこれをすべて実行できることがわかります。で説明されているように、フォーマット仕様に従って数値を出力するために使用できますman 3 printf。出力形式で必要な場合、数値は標準的な方法で暗黙的に丸められます。

コマンド

ラウンドxへのpコマンドライン引数として入力と桁精度:

printf "%.*f\n" "$p" "$x"

または、シェルパイプラインで、入力をx標準入力に、p引数として使用します。

echo "$x" | xargs printf "%.*f\n" "$p"

例:

$ printf '%.*f\n' 0 6.66
7
$ printf '%.*f\n' 1 6.66
6.7
$ printf '%.*f\n' 2 6.66
6.66
$ printf '%.*f\n' 3 6.66
6.660
$ printf '%.*f\n' 3 6.666
6.666
$ printf '%.*f\n' 3 6.6666
6.667

悪い罠

ロケールに注意してください!整数部と小数部の間のセパレータを指定します- .期待どおり。
しかし、ドイツ語のロケールで何が起こるかを自分で確認してください。たとえば、次のようになります。

$ LC_ALL=de_DE.UTF-8 printf '%.*f\n' 3 6.6666
6,667

はい、そうです6,667。6つのコンマ6 6つの7。それは確かにあなたのスクリプトを台無しにするでしょう。
(ただし、ドイツの2人の顧客のみ。これらの顧客のために現在デバッグしている開発者のマシンを除く。)

より堅牢

より堅牢にするには、以下を使用します。

LC_ALL=C /usr/bin/printf "%.*f\n" "$p" "$x"

または

echo "$x" | LC_ALL=C xargs /usr/bin/printf "%.*f\n" "$p"

これ/usr/bin/printfは、シェルの代わりにを使用するbashzshprintfバリアントの実装における軽微な不整合を回避し、ドイツ語のロケールでLC_ALL設定されているがエクスポートされない場合の非常にダーティな影響を防ぎます。次に、組み込みはを使用し,、... を/usr/bin/printf使用し.ます。


%g指定された有効桁数への丸めについても参照してください。


0

以下は私のために働いた。

#!/bin/bash
function float() {
bc << EOF
num = $1;
base = num / 1;
if (((num - base) * 10) > 1 )
    base += 1;
print base;
EOF
echo ""
}

float 3.2
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.