2016-12-11 19 views
2

私はprintfを使用してフロートを小数点以下の桁数に丸める問題があります。私は以下のように矛盾した結果を得ています。awkとprintfを使用して正しく丸めない

echo 104.45 | awk '{printf "%.1f\n",$1}' 
104.5        <-- seem to be correct behaviour 

echo 104.445 | awk '{printf "%.2f\n",$1}' 
104.44  (should be 104.45)  <-- seems to be INCORRECT behaviour 

echo 104.4445 | awk '{printf "%.3f\n",$1}' 
104.445        <-- seems to be correct behaviour 

浮動小数点数の計算では問題が発生する可能性がありますが、書式設定ではこれを想定していない例があります。

+0

あなたは 'GNU'バージョンのawkを使用していますか? – sjsam

+0

さらに詳しい質問は、[Python float round error 117.285 to 117.28 not 117.29](http://stackoverflow.com/questions/9301690/python-float-round-error-117-285-round-to-117)を参照してください。 -28-not-117-29)。 –

+0

おかしい、私が間違っていると思う正しいと思うもの、またはその逆。書式設定のコンテキストでは、文字列の短縮やパディングだけで何の表現も問題にならないと思います。 2番目のケースだけが私にとって期待される動作をしています。 – bli

答えて

3

数字104.4445は、正確に2進数で表すことはできません。言い換えれば、あなたのコンピュータはそのような番号を知らない。

# echo 104.4445 | awk '{printf "%.20f\n",$1}' 
104.44450000000000500222 

# echo 104.445 | awk '{printf "%.20f\n",$1}' 
104.44499999999999317879 

これは前者が104.445に丸められ、後者が104.44に四捨五入されているためです。

sjsamの回答は、正確に2進数で表すことができる数字にのみ関連しています。 e。 m/2**nであり、mnは整数であまり大きくありません。私はPythonで類似の何かを試してみましたが、あなたに同様の結果を得た

# echo 104.4445 | awk -v ROUNDMODE="A" '{printf "%.3f\n",$1}' 
104.445 
# echo 104.4445 | awk '{printf "%.3f\n",$1}' 
104.445 
# echo 104.445 | awk -v ROUNDMODE="A" '{printf "%.2f\n",$1}' 
104.44 
# echo 104.445 | awk '{printf "%.2f\n",$1}' 
104.44 
1

>>> round(104.445, 2) 
104.44 
>>> round(104.4445, 3) 
104.445 

これがあると思われるROUNDINGMODEを変更すると、「A」は104.45、104.445、または104.4445を印刷するには全く影響を与えないように実行の - ミルグラグラ浮動小数点wonkiness、特に104.445の浮動小数点表現は104.445の実際の数学値未満であることを考慮:

>>> 104.445 - 104.44 
0.0049999999999954525 
>>> 104.445 - 104.44 + 104.44 
104.445 
0

Iこの動作の理由は、コンピュータが数字を格納する方法と比べて、awkとあまり関係がないことを強く疑う。 user31264は次のように述べています。「あなたのコンピュータはこのような番号を知らない[​​104.4445]。ここで

は、私はちょうどペールムーンWebブラウザでJavaScriptスクラッチパッドで行った実験の結果をされています、あなたのawkのインタプリタは、など小数104.45、とすべての確率で

(104.45).toFixed(55) 
/* 
104.4500000000000028421709430404007434844970703125000000000 
*/ 

(104.445).toFixed(55) 
/* 
104.4449999999999931787897367030382156372070312500000000000 
*/ 

(104.4445).toFixed(55) 
/* 
104.4445000000000050022208597511053085327148437500000000000 
*/ 

扱っていませんむしろここに表示されている "うわー"の値があります。これらの "うわー"値の1,2,3の小数点以下1桁目、2桁目、3桁目を1桁目、2桁目、3桁目に丸めれば、awkインタプリタがあなたに与えているのと同じ結果になります。

関連する問題