Python multiply()和prod()的错误结果

时间:2010-02-18 13:42:43

标签: python numpy

任何人都可以解释以下内容吗?我正在使用Python 2.5

考虑1 * 3 * 5 * 7 * 9 * 11 ...... * 49。如果您在IPython(x,y)交互式控制台中键入所有内容,那么您将获得58435841445947272053455474390625L,这是正确的。 (为什么奇怪的数字:就像我最初做的那样)

Python multiply.reduce()或prod()应​​该为等效范围产生相同的结果。它确实如此,直到某一点。这里已经错了:

: k = range(1, 50, 2)
: multiply.reduce(k)
: -108792223

使用prod(k)也会生成-108792223。对于长度为12的等效范围,开始出现其他不正确的结果(即,k =范围(1,24,2))。

我不确定为什么。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:6)

这是因为numpy.multiply.reduce()将范围列表转换为类型numpy.int32的数组,并且reduce操作溢出了可以在某个时刻以32位存储的内容:

>>> type(numpy.multiply.reduce(range(1, 50, 2)))
<type 'numpy.int32'>

正如Mike Graham所说,您可以使用dtype参数来使用Python整数而不是默认值:

>>> res = numpy.multiply.reduce(range(1, 50, 2), dtype=object)
>>> res
58435841445947272053455474390625L
>>> type(res)
<type 'long'>

但是在这种情况下使用numpy处理python对象是没有意义的,最好的解决方案是KennyTM:

>>> import functools, operator
>>> functools.reduce(operator.mul, range(1, 50, 2))
58435841445947272053455474390625L

答案 1 :(得分:2)

CPU不会乘以任意大数,它只执行在基数2,0-1位中表示的特定数字范围上定义的特定操作。

Python'*'通过适当的表示和超出CPU或FPU指令的特殊代码来完美地处理大整数。

这种语言实际上并不常见。

在大多数其他语言中,通常将数字表示为固定的位数组。例如,在C或SQL中,您可以选择具有可以表示0到255或-128到+127的8位整数,或者您可以选择具有可以表示最多2 ^ 16-1的16位整数,这是65535.当只有一系列数字可以表示时,通过某些操作(例如*或+)超过限制会产生不良影响,例如获得负数。使用外部库时可能遇到过这样的问题,外部库本身可能是C而不是python。