説明する:

説明する:

Unixの長い列に1行に1つの値を掛け、0.01秒間隔で増加する大きなファイルがあります。 1日分のデータの場合、これは864万行に相当します。

135699840000
135699840001
135699840002
135699840003
135699840004

このファイルの各行から各行のシリアル日付番号(参照年01/01/0000のmatlabの日付カウンタ)を計算するコマンドを実行したいと思います。

735235.0000000000
735235.0000001157
735235.0000002314
735235.0000003472
735235.0000004629

私はコーディングが初めてですが、whileループを使用して動作するようにしました。しかし、これは非常に非効率的で、実行には数時間かかります。

while read epochtimerange; do
echo "scale=10; (($epochtimerange/(100*86400))+719529)" |bc
done < epochtimerangetmp.txt > serialdaterangetmp.txt

私はawkを使って実行する方法があるはずですが、うまくいきません。重要なことは、出力で小数点以下10桁の精度を維持できることです。

誰でも私を助けることができますか?ありがとうございます。

ベストアンサー1

私たち全員が知っているように、シェルは非常に遅いです。
あなたが要求することは次のようにシェルで達成することができます:

#!/bin/bash
while read line; do
    bc <<<"scale=10;($line/(100*86400))+719529"
done <datafile

1000行を処理するのに約1.1秒かかります。
864万枚の写真はすべて約2時間41分かかります。

また、bc の数値結果は正しく丸められません。
例の5行は次の値を生成します。

735235.0000000000
735235.0000001157
735235.0000002314
735235.0000003472
735235.0000004629

より多くの数字を表示するには、精度を20に変更してみましょう。

735235.00000000000000000000
735235.00000011574074074074
735235.00000023148148148148
735235.00000034722222222222
735235.00000046296296296296

たとえば、で終わる3番目の数字2314は誤って丸められ、次の数字はに丸められなければならないこと4が示されます。85

AWK

awkを使用すると、より高速なソリューションを得ることができます。 awkが要求したものを実装すると、次のようになります。

$ awk '{printf ("%.10f\n",($0/(100*86400))+719529)}' datafile

735235.0000000000
735235.0000001157
735235.0000002314
735235.0000003473
735235.0000004630

1000行を処理するには0.006(6ミリ秒)しかかかりません。 864万行すべてを約50秒で処理する必要があります。
しかし、awkは精度範囲を超えました。デフォルトでは、64ビット浮動小数点値を使用して表されます。これは精度は小数点以下15桁程度です。。データ結果の整数部分は6桁で、分数部分は8桁目まで正確に推定できます。
実際にビット数を拡張しようとすると、次のようになります。

awk '{printf ("%.20f\n",($0/(100*86400))+719529)}' datafile

私たちが得るのは騒音だけです。

735235.00000000000000000000
735235.00000011571682989597
735235.00000023143365979195
735235.00000034726690500975
735235.00000046298373490572

より正確なbc結果と比較:

735235.00000000000000000000
735235.00000000000000000000

735235.00000011571682989597
735235.00000011574074074074

735235.00000023143365979195
735235.00000023148148148148

735235.00000034726690500975
735235.00000034722222222222

735235.00000046298373490572
735235.00000046296296296296

この問題を実際に解決するには、より正確なawkが必要です。

多精度AWK

GNU awk(ここではgawkと呼びます)を使用してMPFR(Multiple Precision Floating Point Library)でコンパイルすると、はるかに高い精度が得られます。

あなたのawkにこのライブラリがあることを確認してください(バージョンにお問い合わせください):

$ awk --version
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.1)
Copyright (C) 1989, 1991-2015 Free Software Foundation.

そして、使用可能な精度を使用するようにawkコマンドを変更します。

gawk -M -v PREC=100 '{printf ("%.20f\n",($0/(100*86400))+719529)}' datafile

735235.00000000000000000000
735235.00000011574074074074
735235.00000023148148148148
735235.00000034722222222222
735235.00000046296296296296

結果は高精度bcと同じです。
この場合、awkの速度とbcの精度が得られます。

10進数10桁で要求された最終コマンドは次のとおりです。

gawk -M -v PREC=100 '{printf ("%.10f\n",($0/(100*86400))+719529)}' datafile

735235.0000000000
735235.0000001157
735235.0000002315
735235.0000003472
735235.0000004630

すべての値は正しく丸められます。

おすすめ記事