我最近发现,对于一些非常小的值,使用 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
我想按低于某个阈值的第三列进行过滤。例如:
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 列值非常小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
将是字符串比较,而不是数字比较。