2017-06-24 9 views
4

フィールドがセミコロンで区切られた複数の行を含む "test.txt"というテキストファイルがあります。フィールド3の値を取ろうとしていますが、フィールド内の数値以外のすべてを除外します>前の行のフィールド3の値と比較します>値が一意の場合は、フィールド3の値とその差をリダイレクトします最後の値は "differences.txt"というファイルに保存されます。awkを使用すると予期しない値がカウントされる

はこれまでのところ、私は次のコードを持っている:

awk -F';' ' 
BEGIN{d=0} {gsub(/^.*=/,"",$3); 
if(d>0 && $3-d>0){print $3,$3-d} d=$3} 
' test.txt > differences.txt 

私は次のテキストで実行しようとすると、これは絶対に正常に動作します:予想通り、

field1=xxx;field2=xxx;field3=111222222;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222222;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222333;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222444;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222555;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222555;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222777;field4=xxx;field5=xxx 
field1=xxx;field2=xxx;field3=111222888;field4=xxx;field5=xxx 

出力を:

111222333 111 
111222444 111 
111222555 111 
111222777 222 
111222888 111 

しかし、次のテキストを試してみると、まったく違った予期しない数字が出ます - 私はそうではありませんそれはフィールドや何かの長さの増加によるものかどうか?

テスト:予期しない値を持つ

test=none;test=20170606;test=1111111111111111111; 
test=none;test=20170606;test=2222222222222222222; 
test=none;test=20170606;test=3333333333333333333; 
test=none;test=20170606;test=4444444444444444444; 
test=none;test=20170606;test=5555555555555555555; 
test=none;test=20170606;test=5555555555555555555; 
test=none;test=20170606;test=6666666666666666666; 
test=none;test=20170606;test=7777777777777777777; 
test=none;test=20170606;test=8888888888888888888; 
test=none;test=20170606;test=9999999999999999999; 
test=none;test=20170606;test=100000000000000000000; 
test=none;test=20170606;test=11111111111111111111; 

出力、:

2222222222222222222 1111111111111111168 
3333333333333333333 1111111111111111168 
4444444444444444444 1111111111111111168 
5555555555555555555 1111111111111110656 
6666666666666666666 1111111111111111680 
7777777777777777777 1111111111111110656 
8888888888888888888 1111111111111111680 
9999999999999999999 1111111111111110656 
100000000000000000000 90000000000000000000 

誰もが、私は明らかに何かが欠けているように私は、間違っているつもりだ...そしてそれは私を運転だ場所を確認できます精神的な!!

多くの感謝! :)

答えて

3

2番目の入力例の数値が大きすぎます。 プログラムのロジックは正しいですが、のような非常に大きな整数を使って計算すると精度が失われ、結果として1111111111111111111の代わりに1111111111111111168が得られます。

The GNU Awk User’s Guideで詳細な説明を参照してください。既に述べたように

を、AWKは、ほとんどのシステム上の番号の64ビットIEEEバイナリ浮動小数点表現とハードウェア倍精度を使用します。 9,007,199,254,740,997のような大きな整数は、有限ではあるが53ビット以上の2進表現を持つ。 53ビットに丸めなければなりません。 C doubleに格納できる最大の整数は通常、doubleの可能な最大値と同じです。システムdoubleがIEEE 64ビットのdouble型の場合、この最大値は整数であり、正確に表現できます。整数に関してもっと知っているべきことは何ですか?

最大の整数が何であるかを知りたい場合は、精度を失うことなく64ビットの倍精度整数とそれより小さな整数を格納できるようにするには、答えは2^53です。次の表現可能な数は偶数2^53 + 2です。つまり、整数形式のgawk print 2^53 + 1を作成することはできません。 64ビットの倍精度で正確に表現できる整数の範囲は[-2^53、2^53]です。 awkで64ビットdoubleを使ってこの範囲外の整数を見ると、出力の正確さについて非常に疑わしい理由があります。 @EdMortonとして

あなたのAwkのがMPFRサポート付きでコンパイルされた場合は、任意精度演算を持つことができ、あなたが-Mフラグを指定 、コメントで指摘しました。 詳細については、15.3 Arbitrary-Precision Arithmetic Featuresをご覧ください。

関連する問題