开发者

Wrong results with Python multiply() and prod()

Can anyone explain the following? I'm using Python 2.5

Consider 1*开发者_开发问答3*5*7*9*11 ... *49. If you type all that from within IPython(x,y) interactive console, you'll get 58435841445947272053455474390625L, which is correct. (why odd numbers: just the way I did it originally)

Python multiply.reduce() or prod() should yield the same result for the equivalent range. And it does, up to a certain point. Here, it is already wrong:

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

Using prod(k) will also generate -108792223 as the result. Other incorrect results start to appear for equivalent ranges of length 12 (that is, k = range(1,24,2)).

I'm not sure why. Can anyone help?


This is because numpy.multiply.reduce() converts the range list to an array of type numpy.int32, and the reduce operation overflows what can be stored in 32 bits at some point:

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

As Mike Graham says, you can use the dtype parameter to use Python integers instead of the default:

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

But using numpy to work with python objects is pointless in this case, the best solution is KennyTM's:

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


The CPU doesn't multiply arbitrarily large numbers, it only performs specific operations defined on particular ranges of numbers represented in base 2, 0-1 bits.

Python '*' handles large integers perfectly through a proper representation and special code beyond the CPU or FPU instructions for multiply.

This is actually unusual as languages go.

In most other languages, usually a number is represented as a fixed array of bits. For example in C or SQL you could choose to have an 8 bit integer that can represent 0 to 255, or -128 to +127 or you could choose to have a 16 bit integer that can represent up to 2^16-1 which is 65535. When there is only a range of numbers that can be represented, going past the limit with some operation like * or + can have an undesirable effect, like getting a negative number. You may have encountered such a problem when using the external library which is probably natively C and not python.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜