区切りファイルに大きな値を追加したときに発生するシェルスクリプトと問題

区切りファイルに大きな値を追加したときに発生するシェルスクリプトと問題

区切りファイルを読み取り、各レコードにファイルの3番目の要素を追加するスクリプトがあります。この方法は、1つを除くほとんどのデータファイルに適しています。 193のレコードを含むデータファイルがあります。スクリプトは2028219.43を返すと期待しています。代わりに丸められたように見える指数を取得します。最初はprintfを使用すると数値を取得できると思いましたが、数値がすでに丸められている場合は、私が期待する結果は返されません。

これは、区切られたデータファイルを読み取るために使用するコードです。各レコードのデータは * で区切られます。

export clm_total=$( awk -F* '{f1+=$3} END {print f1}' datafile.dat)
export new_clm_total=$(printf "%.2f" $clm_total)

スクリプトの実行時にログに表示される内容は次のとおりです。

+ export clm_total=2.02822e+06
+ printf %.2f 2.02822e+06
+ export new_clm_total=2028220.00
+ echo 2028220.00

これはデータファイルの例です。まだ記録が多いので、193の記録をすべて表示する必要はないようです。

CLM*123456789*4820.9***13:A:1**A*Y*Y
CLM*123698547*3642.05***13:A:7**A*Y*Y
CLM*147852369*579.25***13:A:1**A*Y*Y
CLM*789654123*929.8***13:A:1**A*Y*Y

私が返すと予想したのは2028219.43でした。 2.02822e+06 を返し、2028220.00 で書式設定しました。

答え1

awkは倍精度浮動小数点数に対して算術演算を実行します。小数点以下2桁まで正確な結果が得られる正確な限界が何かはわかりませんが、範囲内にあります。しかし、これは数字が大きくなると問題が発生する可能性があります。。正確な結果を得るには、整数を使用してオーバーフローに注意するか、bc任意の精度算術を実行する関数を使用してください。

ここで問題は、awkが正しい結果を計算しますが、デフォルトの印刷形式は近似であることです。結果を印刷するときは、明示的な形式を使用してください。

export clm_total=$( awk -F'*' '{f1+=$3} END {printf "%.2f\n", f1}' datafile.dat)

あるいは、print数字を文字列に変換するために印刷形式を変更する必要があると主張することもできます。デフォルト値は、表示される%.6gコンテンツの近似値を生成します。

export clm_total=$( awk -F'*' -v CONVFMT='%.2f' '{f1+=$3} END {print f1}' datafile.dat)

答え2

コンピュータサイエンスで浮動小数点数学を扱うとき(特にawkあなたの場合)、システム内でデータを表現するために使用される基本的なメカニズムに注意を払う必要があります。

私はこれがあなたの特定の状況に直面している問題だと思います。この記事を参照してください。D.3 浮動小数点数の考慮事項、このトピックの詳細をご覧ください。この文書はまた、問題を特定するのに役立ちます。15.2 浮動小数点プログラミングの理解

私が言うことができるのは、浮動小数点数を扱うとき、数の仮数部分に使用できる数が数個しかないawkようです。正確なセックスを失います。

はい

ここでは、しきい値を超えて科学的表記法を使用して実際の数値を追跡し始める様子を見ることができます。

$ seq -f "%f" 1413 | awk '{f1+=$1+0.4} END {print f1}'
999556
$ seq -f "%f" 1414 | awk '{f1+=$1+0.4} END {print f1}'
1.00097e+06

関連情報