回答:
「浮動小数点数の丸め」とはどういう意味ですか?
それは簡単です。明らかに...学校の数学の本はどこにありますか...
いいえ、浮動小数点数に関連するものは何も簡単ではないことがすでにわかっています。
まず、複数の丸めモードがあります。
上向きに丸めますか?
切り下げますか?
ゼロに丸めますか?
最も近い値に丸める-偶数とのつながり?
最も近い値に丸めます-ゼロから離れていますか?
コーナーケースの扱い方は?コーナーケースはどのようにして見つけるのですか?
はい、IEEE 754標準の実装を使用した方がよいようです。システムで処理してください。
標準の浮動小数点演算に基づいて、シェルで浮動小数点数を丸めるには、3つのステップが必要です。
シェルコマンド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
は、シェルの代わりにを使用するbash
かzsh
、printf
バリアントの実装における軽微な不整合を回避し、ドイツ語のロケールでLC_ALL
設定されているがエクスポートされない場合の非常にダーティな影響を防ぎます。次に、組み込みはを使用し,
、... を/usr/bin/printf
使用し.
ます。
%g
指定された有効桁数への丸めについても参照してください。
awk
。