Printing 在awk中打印长整数

Printing 在awk中打印长整数,printing,awk,printf,gawk,Printing,Awk,Printf,Gawk,我有一个管道分隔的提要文件,它有几个字段。因为我只需要一些,所以我考虑使用awk来捕获它们以用于测试目的。但是,我注意到如果我使用%d”,printf会更改值。如果我使用“%s”,它可以正常工作 提要文件示例: [jaypal:~/Temp]cat Temp 《强

我有一个管道分隔的提要文件,它有几个字段。因为我只需要一些,所以我考虑使用
awk
来捕获它们以用于测试目的。但是,我注意到如果我使用
%d”
,printf会更改值。如果我使用
“%s”
,它可以正常工作

提要文件示例:
[jaypal:~/Temp]cat Temp

《强<<<强<<强<<强<<强<<强<<强<<强<<强<<强<<强<<强<<<强<<<强<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<2012-1-13-13 17:17:20:20:20:20:20:20:02.2006.2006-2007 2007-2007 2007 2007 2007-2007 2007-2007-2007-2007 2007-2007 2007-2007 2007 2007-10-10-17 17:17 17:17:17:17:17:17:17:17:17:17:17:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:20:30| 16473840051 | 30 | 302610 | 235 | 250 | 0 | 7 | 0 | 0 | 0 | 0 | 10 | 54320058058002 | 906 | 722310 | 2 | 0 |贝尔移动蜂窝电话公司,公司|贝尔移动| AMX阿根廷公司| Claro aka CTI Movil | CAN | ARG |

我感兴趣的是捕获第二列,即1976990439999903

以下是我的测试: 但是,以下两个测试工作正常-

[jaypal:~/Temp] awk -F"|" '{printf ("%s\n",$2)}' temp
19769904399993903   # Value remains same

[jaypal:~/Temp] awk -F"|" '{print $2}' temp
19769904399993903   # Value remains same
因此,这是不能处理长整数的
“%d”的限制。如果是这样的话,为什么它会在数字上加一而不是截断它呢

我已经用
BSD
GNU
版本的
awk
尝试过这一点

版本信息:
我相信本例中的基本数字格式是IEEE double。因此,更改的值是浮点精度错误的结果。如果确实需要将大值视为数字并保持精确的精度,那么最好使用Perl、Ruby或Python之类的工具,它们具有处理任意精度算术的功能(可能通过扩展)。我认为在awk框架内找不到一种方法可以精确地对大量数字执行算术运算


我能想到的唯一可能的(也是粗糙的)方法是将庞大的数字分成更小的部分,执行您的数学运算并再次加入它们,或者更好地使用比awk更强大的Perl/PHP/TCL/bsh等脚本语言。

更新:GNU awk的最新版本支持任意精度的算术。有关更多信息,请参阅

原创帖子内容: XMLgawk支持浮点数的任意精度算术。 因此,如果可以选择安装xgawk:

zsh-4.3.11[drado]% awk --version |head -1; xgawk --version | head -1
GNU Awk 4.0.0
Extensible GNU Awk 3.1.6 (build 20080101) with dynamic loading, and with statically-linked extensions

zsh-4.3.11[drado]% awk 'BEGIN {
  x=665857
  y=470832
  print x^4 - 4 * y^4 - 4 * y^2
  }'
11885568

zsh-4.3.11[drado]% xgawk -lmpfr 'BEGIN {
  MPFR_PRECISION = 80
  x=665857
  y=470832
  print mpfr_sub(mpfr_sub(mpfr_pow(x, 4), mpfr_mul(4, mpfr_pow(y, 4))), 4 * y^2)
  }'
1.0000000000000000000000000

Mark Wilkins和Dennis Williamson已经部分回答了这个问题,但我发现可以在不损失精度的情况下处理的最大64位整数是2^53。 例如awk的参考页

(如果我的答案太旧,很抱歉。我想在下一个人像我一样花太多时间在这上面之前,我还是会和他们分享的)

从开始你可以使用
--bignum
-M

$ awk 'BEGIN {print 19769904399993903}'
19769904399993904

$ awk --bignum 'BEGIN {print 19769904399993903}'
19769904399993903

在Solaris 11上使用nawk,我将数字转换为字符串,方法是在末尾添加(连接)一个null,然后使用
%15s
作为格式字符串:

printf("%15s\n", bignum "")   

谢谢Mark,那么我们如何使用
printf
处理这些数字呢?对我来说,这不是一个表演的障碍,但我只是想知道,为了学习的目的,我不认为在AWK中准确地表示一个数字是可能的。我的理解(可能不正确)是awk总是使用双精度来存储数值。只要您不需要执行数学运算,那么最好的办法就是将它们打印/用作字符串(您已经找到了)。正确。根据
info gawk
:“包括整数在内的所有数字的内部表示都使用双精度浮点数。在大多数现代系统上,这些数字都是IEEE 754标准格式。”感谢Anubhava。这听起来不错,因为当我在命令行执行此操作时,它会很好地打印它
[jaypal:~/Temp]printf“%d”1976990439993903 197699043999993903
如果使用awk的
printf“%17.0f\n”
会发生什么?根据我在awk的经验,我想在comp.lang.awk上发布这个问题。祝你好运谢谢@Sheller。我得到了同样的结果。令人惊讶的是,它只发生在
awk
内部。如果我执行了
printf%d
并在命令行上输入了我的值,则它将正确打印。如果我在awk的BEGIN语句中执行相同的操作,它会把事情搞砸它使用作为UWIN系统一部分的awk版本打印正确的编号。我认为这可以归结为与您的awk版本相关联的C-lib函数版本的“质量”。您还可以访问64位机器和64位awk/gawk吗?祝你好运。嗯,不幸的是没有。。因此,基本上我们可以将其称为bug,就像我在CLI上所做的
printf%d
一样,它可以正常工作。奇怪的是,即使是GNU4.0.0版本的
awk
也复制了这一点。在一些linux(Unbuntu等)和UWIN中发现的新(ish)ksh中的内部printf命令也将是正确的(就像bash一样)。你在谈论处理多少数据?17位数字上的一个关对你的问题真的很重要吗?。(哦,这看起来不像是财务数据,所以可能很重要;-))。祝你好运表示GNUAWK4.1将
xgawk
作为单独的二进制文件淘汰。它建议使用
gawkextlib
进行
gawk
。你的xgawk链接已经失效。我不确定哪个链接最好,所以我没有亲自编辑你的帖子。
$ awk 'BEGIN {print 19769904399993903}'
19769904399993904

$ awk --bignum 'BEGIN {print 19769904399993903}'
19769904399993903
printf("%15s\n", bignum "")