在awk中打​​印长整数

时间:2012-01-13 22:04:44

标签: printing awk printf gawk

我有一个管道分隔的Feed文件,其中包含多个字段。由于我只需要一些,我想到使用awk来捕获它们以用于我的测试目的。但是,我注意到,如果我使用 printf "%d" 会更改该值。如果我使用 "%s" ,它可以正常工作。

Feed文件示例:

  

[jaypal:~/Temp] cat temp

     

302610004125074|19769904399993903|30|15|2012-01-13 17:20:02.346000|2012-01-13 17:20:03.307000|E072AE4B|587244|316|13|GSM|1|SUCC|0|1|255|2|2|0|213|2|0|6|0|0|0|0|0|10|16473840051|30|302610|235|250|0|7|0|0|0|0|0|10|54320058002|906|722310|2|0||0|BELL MOBILITY CELLULAR, INC|BELL MOBILITY CELLULAR, INC|Bell Mobility|AMX ARGENTINA SA.|Claro aka CTI Movil|CAN|ARG|

我有兴趣捕获 second column 19769904399993903

以下是我的测试:

[jaypal:~/Temp] awk -F"|" '{printf ("%d\n",$2)}' temp
19769904399993904   # Value is changed

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

[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

版本信息:

[jaypal:~/Temp] gawk --version
GNU Awk 4.0.0
Copyright (C) 1989, 1991-2011 Free Software Foundation.

[jaypal:~/Temp] awk --version
awk version 20070501

6 个答案:

答案 0 :(得分:8)

GNU awk 4.1开始,您可以使用--bignum-M

$ awk 'BEGIN {print 19769904399993903}'
19769904399993904

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

§ Command-Line Options

答案 1 :(得分:5)

我认为这种情况下的基础数字格式是IEEE双精度格式。因此,更改的值是浮点精度错误的结果。如果实际上有必要将大值视为数值并保持准确的精度,那么使用Perl,Ruby或Python等具有功能(可能通过扩展)来处理任意精度算术的东西可能更好。

答案 2 :(得分:4)

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

原始帖子内容: 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

答案 3 :(得分:2)

@Mark Wilkins和@Dennis Williamson已经部分回答了这个问题,但我发现最大的64位整数可以处理而不会丢失精度是2 ^ 53。 例如awk的参考页面 http://www.gnu.org/software/gawk/manual/gawk.html#Integer-Programming

(对不起,如果我的回答太旧了。想想我还是会为下一个人分享,就像他们花了太多时间一样)

答案 4 :(得分:1)

你遇到了Awk's Floating Point Representation Issues。我认为你不能在awk框架中找到解决方法来准确地对大数字进行算术运算。

我能想到的只有可能(和原始)的方法是将巨大的数字分解成更小的块,执行数学并再次加入它们或更好地使用比其更强大的Perl / PHP / TCL / bsh等脚本语言AWK。

答案 5 :(得分:0)

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

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