【问题标题】:Wrong results with Python multiply() and prod()Python multiply() 和 prod() 的错误结果
【发布时间】:2016-11-07 02:44:52
【问题描述】:

谁能解释以下内容?我正在使用 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 = range(1,24,2)),开始出现其他不正确的结果。

我不知道为什么。有人可以帮忙吗?

【问题讨论】:

  • 呃,mutiply.reduce 是什么?它是在哪里定义的?
  • @SilentGhost: 好像是个麻木的东西
  • functools.reduce(operator.mul, range(1, 50, 2)) 给出58435841445947272053455474390625L

标签: python numpy


【解决方案1】:

这是因为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

【讨论】:

  • 要使用不同的数据类型,您还可以为一些 NumPy 函数添加 dtype 参数,例如np.prod([1,2], dtype=np.int64);但是,int64 仍然不足以计算这里提出的问题!不幸的是,我认为 NumPy 没有无限精度整数。
  • 是的,numpy 不是处理任意精度整数的好工具,正确的方法是使用 KennyTM 所说的纯 Python。
  • 如果您需要 bignums 数组(通常不需要!),您可以使用 dtype=object 将 Python 对象与 numpy 一起使用。
【解决方案2】:

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

Python '*' 通过适当的表示形式和 CPU 或 FPU 指令之外的特殊代码完美地处理大整数以进行乘法运算。

随着语言的发展,这实际上是不寻常的。

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

【讨论】:

  • 虽然您所说的某些内容可能被认为对某些人有用且有帮助,但声称“CPU 并不能真正将数字相乘”的说法是非常虚假的。事实上,很少有 CPU 没有适用于其原生整数大小的乘法指令(对于运行 Python 的台式机,通常是 32 位或 64 位)。我想你可能是想说 CPU 不直接处理 large 整数乘法,但你不是这么说的。
  • @Peter 我说的是数字。采用维基百科对数字的定义,而不是我们个人对这个词可能含义的看法——en.wikipedia.org/wiki/Number——我将支持我的推理,即 CPU 的 MUL 指令只尝试处理适合于行业定义的规范,即使那样也不会提供符合规范的任何两个数字的产品。
  • modular arithmetic 中的数字仍然是数字,它们的行为已定义。在 CPU 级别上,乘法运算符在其整个输入域上执行全乘法也很常见,但产生的输出比处理器字宽(即 32 位乘法产生 64 位乘积)。
猜你喜欢
  • 2017-09-06
  • 1970-01-01
  • 2022-10-21
  • 2013-06-20
  • 1970-01-01
  • 2018-02-09
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多