【问题标题】:Factorializing Medium Numpy Ints Creates Runtime Warning分解中型 Numpy Ints 会产生运行时警告
【发布时间】:2020-01-22 13:22:24
【问题描述】:

我正在检查阶乘的运行时间(必须使用用户定义的函数),但我收到一个奇怪的错误。我正在使用的代码如下:

import numpy as np
import time
np.random.seed(14)
nums = list(np.random.randint(low=100, high=500, size=10))
# nums returns as [207, 444, 368, 427, 349, 458, 334, 256, 238, 308]
def fact(x):
  if x == 1:
    return 1
  else:
    return x * fact(x-1)
recursion_times = []
recursion_factorials = []

for i in nums:
    t1 = time.perf_counter()
    factorial = fact(i)
    t2 = time.perf_counter()
    execution = t2-t1
    recursion_factorials.append(factorial)
    recursion_times.append(execution)
    print(execution)

当我运行上述内容时,我得到以下信息: RuntimeWarning: overflow encountered in long_scalars"""

但是当我如下运行它时,我没有收到任何警告。

recursion_times = []
recursion_factorials = []
for i in [207, 444, 368, 427, 349, 458, 334, 256, 238, 308]:
    t1 = time.perf_counter()
    factorial = fact(i)
    t2 = time.perf_counter()
    execution = t2-t1
    recursion_factorials.append(factorial)
    recursion_times.append(execution)
    print(execution)

我知道调用列表nums 有点额外开销,但为什么会触发运行时警告?我已经尝试过挖掘,但我只得到动态命名的变量线程和警告抑制库 - 我正在寻找为什么会发生这种情况。

不管怎样,我在 jupyter notebook 中运行 Python3。如果有帮助,很高兴回答任何其他问题。

提前感谢您的帮助!

【问题讨论】:

  • 我认为这与您的变量名没有任何关系。您最终得到的数字太大而无法存储在您选择的数据类型中。你在用 numpy 吗?
  • 以后,请发布一些我们可以实际运行的东西,在运行时重现错误。特别是,如果没有fact 的定义,我们就无法运行它。此外,除非fact 本身直接使用 NumPy,否则溢出可能是由您使用 NumPy 数组作为输入触发的,在这种情况下,传递列表(如发布的代码版本)不会触发它。跨度>
  • @user2357112supportsMonica 好点,已编辑原始帖子以定义 fact()。对此感到抱歉
  • Numpy 的默认整数大小是int32。使用int32 最多只能计算12!。请注意,即使100! 也是一个巨大 数字(它有 158 位数字)。

标签: python python-3.x numpy recursion


【解决方案1】:

如果(如在您的帖子的当前版本中)您通过在 NumPy 数组上调用 list 创建了 nums,但是为第二次测试编写了一个没有 NumPy 的显式列表文字,那么第二次测试不会给出警告因为它没有使用 NumPy。 nums 是 NumPy 固定宽度整数的列表,而另一个列表是普通 Python 整数的列表。普通的 Python 整数不会溢出。

(如果你想从一个 NumPy 数组创建一个普通 Python 标量的列表,可以使用array.tolist()。由于性能问题,这通常是不可取的,但有时需要与以下代码进行互操作阻塞 NumPy 类型。)


由于默认的 Python 警告处理,通常会产生额外的影响。默认情况下,Python 仅在每个 Python 进程的每个代码位置发出一次警告。在您问题的原始版本中,看起来这是造成差异的原因。


使用变量或不使用变量对这个警告没有影响。

【讨论】:

  • 我不这么认为,但如果我再次运行同一个单元格(或另一个具有相同代码的单元格),我会保留警告。我还尝试更改单元格并注释掉调用列表nums 的行。它仍然认为,每当我调用 nums 而不是直接调用列表时,我都会收到警告。你知道为什么会这样吗?
  • @TJ15:可能是某种排序效果或奇怪的非默认警告处理,或者您所做的一些您没有意识到的额外更改很重要。这不太可能与您是否使用变量进行输入有关。
  • 例如,如果您写的是for i in [207, 444, 368, 427, 349, 458, 334, 256, 238, 308] 而不是for i in list(np.random.randint(low=100, high=500, size=10)),那么您将使用普通的 Python 整数而不是 NumPy 固定宽度整数,并且您不会收到此警告。再加上笔记本中不同的警告处理方式,当您使用 NumPy 时会更频繁地显示警告,这可以说明问题。
  • 好点。 this question 的答案更详细地介绍了 python 内置 int 类型与 np.int64 或 np.int32。感谢您的帮助!
猜你喜欢
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
相关资源
最近更新 更多