ter*_*don 5 python perl awk rounding long-integer
考虑一下(所有命令都在64位Arch Linux系统上运行):
Perl(v5.24.0)
$ perl -le 'print 10190150730169267102/1000%10'
6
Run Code Online (Sandbox Code Playgroud)awk (GNU Awk 4.1.3)
$ awk 'BEGIN{print 10190150730169267102/1000%10}'
6
Run Code Online (Sandbox Code Playgroud)R(3.3.1)
> (10190150730169267102/1000)%%10
[1] 6
Run Code Online (Sandbox Code Playgroud)bc
$ echo 10190150730169267102/1000%10 | bc
7
Run Code Online (Sandbox Code Playgroud)Python 2(2.7.12)
>>> print(10190150730169267102/1000%10)
7
Run Code Online (Sandbox Code Playgroud)Python 3(3.5.2)
>>> print(10190150730169267102/1000%10)
8.0
Run Code Online (Sandbox Code Playgroud)所以,Perl,gawk并R同意,bc和Pyhon 2.然而,在测试的6个工具之间,我得到了4个不同的结果.我知道这与整数很长的整数有关,但为什么不同的工具差别如此之大?我曾预料到这将取决于处理器处理大数字的能力,但它似乎取决于语言的内部特征(或错误).
有人可以解释幕后发生的事情吗?每种语言有哪些限制,为什么它们的表现如此不同?
您看到不同的结果有两个原因:
除法步骤是做两件事:在你尝试的一些语言中,它表示整数除法,它丢弃结果的小数部分,只保留整数部分.在其他情况下,它代表实际的数学划分(遵循Python的术语,我将在下面称为"真正的划分"),返回接近真实商的浮点结果.
在某些语言(支持任意精度的语言)中,10190150730169267102正好表示大的分子值; 在其他情况下,它被最近的可表示浮点值替换.
上面1.和2.中可能性的不同组合给出了不同的结果.
详细说明:在Perl,awk和R中,我们正在使用浮点值和真正的除法.该值10190150730169267102太大而无法存储在机器整数中,因此它以通常的IEEE 754 binary64浮点格式存储.该格式不能代表该特定值完全,所以什么都存储是最接近的值是在格式,这是表示的10190150730169266176.0.现在我们将该近似值除以1000,再次给出一个浮点结果.精确的商,10190150730169266.176再次不能完全表示为binary64格式,我们得到最接近的可表示的浮点数,恰好是10190150730169266.0.取余数模数10给出6.
在bc和Python 2中,我们使用任意精度整数和整数除法.这两种语言都可以完全代表分子.然后是除法结果10190150730169267(我们正在进行整数除法,而不是真正的除法,因此丢弃小数部分),其余模数10为7.(这有点过于简单化了:bc在内部使用的格式Decimal比Python的类型更接近于任意精度整数类型,但在这种情况下效果是相同的.)
在Python 3中,我们使用任意精度整数和真正的除法.分子的确切表示,但除法的结果是与真商最接近的浮点值.在这种情况下,精确的商是10190150730169267.102,并且最接近的可表示的浮点值是10190150730169268.0.取该值模的剩余部分10给予8.
摘要: