MS Excelのようなbashで小数点以下の2桁に丸める方法は?

MS Excelのようなbashで小数点以下の2桁に丸める方法は?

BASHで「浮動数値」を丸める方法を検索するために数時間を費やしましたが、正しいものが見つかりません!回避策:(この数字をExcelに入力すると、小数点以下の2桁まで丸めた後に正しい結果が得られます。

3.314 -> 3.31
3.315 -> 3.32
8.124 -> 8.12
8.125 -> 8.13

BASHで正確な結果を得るには?printf試してみましたが、awk同じ結果が得られませんでした。

prompt> printf '%.*f\n' 2 8.125
8.12
prompt> echo '8.125' | awk '{printf("%.2f\n", $1)}'
8.12

ベストアンサー1

printf '%.2f\n' 8.125

8.125strtod()10進数のテキスト表現は、標準またはC関数などのstrtold()方法を使用して内部バイナリ表現に変換され、結果としてバイナリ浮動小数点数になり、内部表現はCコンパイラとdoubleコンピュータlong doubleアーキテクチャによって異なります。

その後、数値はコマンドを介して標準関数(または結果を文字列として返すバリアント)printfに渡され、それをリテラル10進表現に変換して丸めます。printf()最も近い偶数に丸め、偶数に丸め(とも呼ばれる)銀行家の丸め)。

学校で学んだ方法は、平均的に(正の場合)過大評価する傾向があるという点で偏っています。半分が偶数の場合、8.125合計8.1158.122でも)、1ビットは丸められ、1ビットは丸められる。大きな数字の場合、数字の半分を四捨五入し、残りの半分を四捨五入しても体系的な偏りは発生しません。

これは、2進数で正確に表現できる数値にのみ適用されます。

偶然にも、8.125は2進数で表すことができます。それは2 3 + 2 -3です。 8.135 最も近い IEEE 754 倍精度 2 進数は 8.134999999999999997868371792719699442386627197265625(10 進数に再変換するとき) なので偶数 (8.4 偶数 (8.1)

したがって、必要なものを実行するには(適切な銀行丸めも実行する)、2進数では機能しませんが、10進数では機能する必要があります。したがって、ユーティリティをprintf()含む、以下で使用されるか、またはより一般的にバイナリを処理するプロセッサの浮動小数点算術関数と連携することは不可能です。printfawkprintf()numfmt

python3たとえば、次decimalのモジュールを使用できます。@marcelmが表示)perlまたはMath::BigFloat基準寸法そしてそれはbfround()機能です。基本的に彼らはそうです銀行家の丸め:

$ printf '%s\n' 1.1{0..5}5 | perl -MMath::BigFloat -lne 'print "$_ -> " . Math::BigFloat->new($_)->bfround(-2)'
1.105 -> 1.10
1.115 -> 1.12
1.125 -> 1.12
1.135 -> 1.14
1.145 -> 1.14
1.155 -> 1.16

ただし、次のように切り替えることができます。common モデルこれは学校で学んだ内容と一致します。

$ printf '%s\n' {-,}1.1{0..5}5 +825e-3 0xAAp-6 0x1p100 nan Infinity | 
   perl -MMath::BigFloat -lne '
     print "$_ -> " . Math::BigFloat->new($_)->bfround(-2,common)'
-1.105 -> -1.11
-1.115 -> -1.12
-1.125 -> -1.13
-1.135 -> -1.14
-1.145 -> -1.15
-1.155 -> -1.16
1.105 -> 1.11
1.115 -> 1.12
1.125 -> 1.13
1.135 -> 1.14
1.145 -> 1.15
1.155 -> 1.16
+825e-3 -> 0.83
0xAAp-6 -> 2.66
0x1p100 -> 1267650600228229401496703205376.00
nan -> NaN
Infinity -> inf

(他の記号を使用する追加の数字が表示されます)。

likepython3のメソッドは、numfmt一部のprintfユーティリティ実装とは異なり、ロケールを区別しません。特に、10進数の基数文字は、ロケール.でも入出力に使用されます。,٫

おすすめ記事