将Perl Skript移植到Python会得到大数字和模的错误结果



目前我将脚本从perl移植到python,但不知何故,通过模计算,我得到了一个非常奇怪的行为。

32185864684058608501682550623 % 62

在Perl中,我得到6,使用Python我得到25L。

有没有办法得到数字 6?

同样使用 python3,我得到了相同的结果。

Perl 对大数字的内置支持不是很好。由于溢出,您得到的答案为 6。比较

$ perl -e 'print 32185864684058608501682550623 % 62, "n"'
6
$ perl -Mbignum -e 'print 32185864684058608501682550623 % 62, "n"'
25

默认情况下,Perl 将大整数转换为浮点数,而不是使用任意精度:

$ perl -e 'print 32185864684058608501682550623 + 0'
3.21858646840586e+28

Vs Python 自动切换到具有大整数的任意精度长:

>>> 32185864684058608501682550623 + 0
32185864684058608501682550623L

您可以看到这是有关 Perl 中长整数的信息丢失(不使用 bignum):

$ perl -e 'print 32185864684058608501682550623-32185864684058608501682550620'
0

与 Python 的默认值:

>>> 32185864684058608501682550623-32185864684058608501682550620
3L

要在 Python 上获得相同(不正确)的结果,只需先将大数字转换为浮点数:

>>> float(32185864684058608501682550623) % 62
6.0

然后,如果你想要一个int,则转换回一个int:

>>> int(float(32185864684058608501682550623) % 62)
6

顺便说一句:32185864684058608501682550623 % 62实际上是 25,而不是 6 ;-)

如果您希望具有相同的行为,我建议您使用数学模块。数学模块允许你使用 fmod,它将模仿预期的 Perl 行为。在此之后,如果您真的愿意,您可以随时投射回 int...

在 Python 2.7 中:

>> import math
>> print math.fmod(32185864684058608501682550623, 62)
6.0
>> print int(math.fmod(32185864684058608501682550623, 62))
6

在 Python 3 中:

>> import math
>> print(math.fmod(32185864684058608501682550623, 62))
6.0
>> print(int(math.fmod(32185864684058608501682550623, 62)))
6

但是,fmod 用于浮点数,在这里是不准确的。Perl 似乎很可能正在使用 fmod(我对 Perl 知之甚少)。使用 Wolfram Alpha,我们可以验证 Python 2 和 3 的默认行为是否正确,答案是 25。

因此,如果我们希望将答案投给 int,这就足够了:

>> print 32185864684058608501682550623 % 62
25L
>> print int(32185864684058608501682550623 % 62)
25

这个SO答案可能会帮助你理解fmod的不准确性:

非常长的数的模数 (fmod)

最新更新