awk: 负指数的解释不正确

问题描述 投票:0回答:1

我有这个表格。

a   0
b   0
c   1.6149e-315
d   5.2587e-265
e   8.2045e-227
f   8.2045e-227

如果我输入

$awk '($2<1){print}' my_file.txt

它返回

a   0
b   0
d   5.2587e-265
e   8.2045e-227
f   8.2045e-227

但它认为第三行的值1.6149e-315大于1。

$awk '($2>1){print}' my_file.txt 
c   1.6149e-315

这种行为的原因是什么?是不是负指数<1e-300太小了,所以它去掉了 "e-"部分?看起来是这样,因为

$awk '($2>1.6149){print}' my_file.txt 
c   1.6149e-315

但如果我跑

$ awk '($2>1.615){print}' my_file.txt

什么都没有输出。

我如何克服这个问题?

shell if-statement unix awk exponential
1个回答
2
投票

像这样运行你的awk。

awk '($2+0) < 1' file

这将输出:

a   0
b   0
c   1.6149e-315
d   5.2587e-265
e   8.2045e-227
f   8.2045e-227

$2+0 转换 $2 变成一个数字值。

另外在 GNU Awk 5.0.1即使没有这个技巧,我也能得到正确的输出。


-1
投票

转载OP的问题与 GNU Awk 4.2.1.


首先是: $NF+0 似乎不能解决这个问题,正如我们在这个例子中看到的那样。
> cat file
a   0
b   0
c   1.6149e-315
d   5.2587e-265
e   8.2045e-227
f   8.2045e-227

> awk '$2+0>0' file
d   5.2587e-265
e   8.2045e-227
f   8.2045e-227

样本输入的第三个数字没有再被打印出来,而它应该大于零。

而这里我们看到第三个数字只有零。

awk '{printf "%.320f\n",$2+0}' file

以上都说明 e^-315 没有以预期的方式表示。


看起来你已经超过了极限,那就是...。-308 为双精度浮点。左右 e^-308 是要表示的最小正非零值。

https:/www.gnu.orgsoftwaregawkmanualgawk.html#Computer-Arithmetic


此外,如果你的gnu awk编译时支持MPFR,你可以使用-M选项拥有多个精度的数字,这似乎是表示一个正数的唯一方式,小于 10^-308

https:/www.gnu.orgsoftwaregawkmanualhtml_nodeMPFR-features.html


最后一个论点,一个简单的测试。

> cat file
a   1.1e-312
b   1.1e-311
c   1.1e-310
d   1.1e-309
e   1.1e-308
f   1.1e-307
g   1.1e-306
h   1.1e-305
> awk '$2+0>0' file
f   1.1e-307
g   1.1e-306
h   1.1e-305

指数小于 -308 是不按预期处理的。

> awk '{print($2+0)}' file
0
0
0
0
0
1.1e-307
1.1e-306
1.1e-305

这就是证明,即 $NF+0 力为零,而不是指数数,任何超出的数字都是 ^-308 不能表示,因为该限制存在于双精度的awk实例中,不支持多精度。

© www.soinside.com 2019 - 2024. All rights reserved.