最近、AWKを使用したフィルタリングが非常に小さい値に対して誤動作するように見えることがわかりました。次の文書に示すようにtest_loc.txt
:
10:10000018 10 0.4505
X:99997421 X 0.95508
X:99997626 X 0.016206
X:99998439 X 0.5043
10:100001724 10 0.69838
10:100001867 10 0.48936
2:137078930 2 2.8245e-05
10:100001868 10 0.11326
10:100002378 10 0.6674
19:45431453 19 3.952525e-323
10:100002464 10 0.87964
特定のしきい値の下の3番目の列に基づいてフィルタリングしたいと思います。たとえば、
awk '($3 < 0.5) {print $0}' test_loc.txt
生産する
10:10000018 10 0.4505
X:99997626 X 0.016206
10:100001867 10 0.48936
2:137078930 2 2.8245e-05
10:100001868 10 0.11326
特に、19:45431453
3列の値が非常に小さい2番目の項目は省略されました3.952525e-323
。
ただし、しきい値が下がる場合は次のとおりです5e-5
。
awk '($3 < 5e-5) {print $0}' test_loc.txt
すぐに拾いました。
2:137078930 2 2.8245e-05
19:45431453 19 3.952525e-323
この問題を解決する理由と方法のアイデアはありますか?
答え1
awk
この問題は、MPFR を持たない、または複数の精度をサポートする MP を持たないインスタンスで再現できます。非常に大きいまたは非常に小さい数字e-308
には制限があります。e+308
ここでは表16.1を参照してください。https://www.gnu.org/software/gawk/manual/gawk.html#コンピュータ操作
また見なさい:https://www.gnu.org/software/gawk/manual/html_node/MPFR-features.html
(上記のリンクを参照)の出力で複数の精度をサポートしているかどうかを確認できますawk
。倍精度のみがサポートされていても、awk --version
このオプションは効果がありません-M
。
たとえば、GNU Awk 4.2.1, API: 2.0
MPFRがない場合、この例を実行しました(awk 5を使用して再現できません)。
$ cat file
1e-305
1e-306
1e-307
1e-308
1e-309
1e-310
$ awk '$0+0 > 0' file
1e-305
1e-306
1e-307
文字列が有効数字を示していない場合は、$0+0
ゼロと評価されます。この場合、$0
比較は$0>0
数値比較ではなく文字列比較になります。