将Perl脚本移植到Python使用大数字和模数得到错误的结果

时间:2015-04-14 20:11:13

标签: python python-2.7 python-3.x

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

32185864684058608501682550623 % 62

在Perl中,我得到6作为结果,使用Python我得到25L。

有某种方法可以获得数字6吗?

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

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

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

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

使用大整数,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

BTW:32185864684058608501682550623 % 62实际上是25,而不是6; - )

答案 2 :(得分:1)

如果您希望有相同的行为,我建议您使用数学模块。数学模块允许您使用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的不准确性:

Modulus of a really really long number (fmod)