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