2017-03-08 58 views
1

我使用可以正常工作的awk(减去Time_res-Time_req来查找滞后)减去大数字,但无法在python中执行相同操作。在python中使用非常大的数字

ID    Time_req    Time_res  lag 
0 3000002 1455594303468741117 1455594303469326836 585728 

为什么在下面的输出是这样的?

>>> 1455594303469326836 - 1455594303468741117 
585719 
and not 585728 

我甚至尝试

>>> long(1455594303469326836) - long(1455594303468741117) 
585719L #still wrong 
+7

585719是正确答案。 awk是错的,python是对的。 –

+0

像@ juanpa.arrivillaga说的是正确的操作:S – Tzomas

+0

有关使用大数字的更多信息:http://stackoverflow.com/questions/538551/handling-very-large-numbers-in-python –

回答

1

要做到在awk中大量(任意精度)数学需要gawk -M

$ awk 'BEGIN{print 1455594303469326836 - 1455594303468741117}' 
585728 

$ awk -M 'BEGIN{print 1455594303469326836 - 1455594303468741117}' 
585719 

$ awk --version | head -2 
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5, GNU MP 6.1.2) 
Copyright (C) 1989, 1991-2016 Free Software Foundation. 

详情请参阅https://www.gnu.org/software/gawk/manual/gawk.html#MPFR-features

1

gawk你需要指定要使用的BIGNUM包(如果gawk与链接到该包编译):

$ gawk -M 'BEGIN{print 1455594303469326836 - 1455594303468741117}' 
585719 

(您也可以为相同的功能,gawk -Mgawk --bignum 'prog'

如果没有-M开关,您可以通过将字符串添加0将输入转换为整数来查看溢出。注意第2栏是不一样的,第一:

$ echo "1455594303469326836 1455594303468741117" | awk '{print $1 " => " $1+0,ORS $2 " => " $2+0}' 
1455594303469326836 => 1455594303469326848 
1455594303468741117 => 1455594303468741120 

VS

$ echo "1455594303469326836 1455594303468741117" | awk -M '{print $1 " => " $1+0,ORS $2 " => " $2+0}' 
1455594303469326836 => 1455594303469326836 
1455594303468741117 => 1455594303468741117 

由于IEEE 754双打具有精度53位的尾数(可用于精确的整数表示到那个尺寸)便开始解除与尺寸大于53个比特的整数精确表示能力:

$ awk 'BEGIN{print 2**53, 2**53+1}' 
9007199254740992 9007199254740992 
      ^   ^  not +1 in least significant digit 

$ awk -M 'BEGIN{print 2**53, 2**53+1}' 
9007199254740992 9007199254740993  
      ^   ^  fixed... 

你的输入需要61位来表示准确(或62个比特用符号位),所以你失去了表示输入的最低有效位数的能力。


选项

如果没有gawk与BIGNUM选项,则可以使用perl与BIGNUM:

$ perl -Mbignum -E 'say 1455594303469326836 - 1455594303468741117' 
585719 

蟒蛇:

$ python -c 'print 1455594303469326836 - 1455594303468741117' 
585719 

bc

$ echo "1455594303469326836 - 1455594303468741117" | bc 
585719 

红宝石:

$ ruby -e "puts 1455594303469326836 - 1455594303468741117" 
585719 

但基本POSIX awk中 - 没有布埃诺为arbitrarily precision integer或非IEEE 754浮点运算。所有的POSIX awk算法(或没有bignum的gawk)都是用IEEE双精度完成的,这个精度会随着您输入的大小而溢出。

+1

除此之外,OP的整数需要62位,而IEEE 754只提供53位的精度。它写在哪里,但awk使用双精度?我用于OS X和NetBSD的awk手册页没有提到这一点。 –

+0

我主要依靠GNU文档:[POSIX awk使用双精度浮点数](https://www.gnu.org/software/gawk/manual/html_node/Computer-Arithmetic.html)和[默认,gawk使用它运行的系统硬件提供的双精度浮点值。](https://www.gnu.org/software/gawk/manual/gawk.html#MPFR-features) – dawg

+0

但是OpenGroup的[数值完全等于整数的值(请参阅从ISO C标准派生的概念)应该通过等同于对sprintf函数的调用(参见字符串函数)将字符串转换为字符串“%d”](http://pubs.opengroup.org/onlinepubs/9699919799/) – dawg