【问题标题】:Unexpected value counts using awk使用 awk 计算意外值
【发布时间】:2017-11-28 03:07:49
【问题描述】:

我有一个名为“test.txt”的文本文件,其中包含多行,字段用分号分隔。我正在尝试获取 field3 的值 > 去掉除字段中的数字之外的所有内容 > 将其与上一行中字段 3 的值进行比较 > 如果该值是唯一的,则重定向字段 3 的值及其之间的差异和最后一个值到一个名为“differences.txt”的文件中。

到目前为止,我有以下代码:

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

任何人都可以看到我哪里出错了,因为我显然遗漏了一些东西......这让我精神崩溃!

非常感谢! :)

【问题讨论】:

    标签: unix awk qsub


    【解决方案1】:

    第二个示例输入中的数字太大。 虽然程序的逻辑是正确的, 使用非常大的整数进行计算时会损失精度,例如 2222222222222222222 - 1111111111111111111 导致 1111111111111111168 而不是预期的 1111111111111111111

    详细解释见The GNU Awk User’s Guide

    正如已经提到的,awk 在大多数系统上使用硬件双精度和 64 位 IEEE 二进制浮点表示来表示数字。像 9,007,199,254,740,997 这样的大整数具有二进制表示,虽然是有限的,但长度超过 53 位;它还必须四舍五入到 53 位。可以存储在 C double 中的最大整数通常与 double 的最大可能值相同。如果您的系统双精度是 IEEE 64 位双精度,则这个最大可能值是一个整数,可以精确表示。关于整数还应该知道什么?

    如果您想知道什么是最大整数,以便它和所有较小的整数可以存储在 64 位双精度中而不会丢失精度,那么答案是 2^53。下一个可表示的数字是偶数 2^53 + 2,这意味着您不太可能让 gawk 以整数格式打印 2^53 + 1。可以用 64 位双精度精确表示的整数范围是 [-2^53, 2^53]。如果您在 awk 中使用 64 位双精度数看到超出此范围的整数,那么您有理由对输出的准确性非常怀疑。

    正如@EdMorton 在评论中指出的那样, 如果您的 Awk 是使用 MPFR 支持编译的并且您指定了 -M 标志,那么您可以使用任意精度的算术。 详情请见15.3 Arbitrary-Precision Arithmetic Features

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-30
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多