【问题标题】:How do I multiply each element in an array with a large number without getting OverflowError: Python int too large to convert to C long?如何将数组中的每个元素与大数相乘而不会出现 OverflowError: Python int too large to convert to C long?
【发布时间】:2025-12-11 19:20:08
【问题描述】:

我正在编写一个程序,我想将数组(来自 numpy)中的每个数字与一个大数字(1.692287392646066e+41)相乘,我这样做是这样的:

x = array([ 16,  18,  19,  15,  27,  26,  13,  34,  38,  36,  43,  42,  48,
    50,  55,  57,  70,  67,  65,  85,  99,  94,  90, 112, 126, 130,
   142, 120])
weight = 1.692287392646066e+41

x[:] = [i*weight for i in x]

但随后我收到错误“OverflowError: Python int too large to convert to C long”。奇怪的是,将 for 循环外的数字相乘似乎有效:

In [1]: x[0]*weight
Out[1]: 2.7076598282337055e+42

我的问题是,我有什么办法可以在 for 循环中执行此操作,因为我事先不知道我的数组有多长? (我知道它有 1 行。)

【问题讨论】:

    标签: python arrays for-loop numpy


    【解决方案1】:

    python 中而不是在numpy 中进行乘法是没有意义的。 numpy 不仅速度更快,而且效果更好。

    您尝试执行的操作会创建一个 python list,然后它会尝试将其复制到 numpy array 元素中。

    而只是使用

    x = x * weight
    

    你很好。

    EOL 怀疑这行不通,所以这是我刚刚在我的计算机上所做的:

    $ python
    Python 2.7.3 (default, Dec 18 2014, 19:03:52)
    [GCC 4.6.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from numpy import array
    >>> x = array([ 16,  18,  19,  15,  27,  26,  13,  34,  38,  36,  43,  42,  48,
    ...     50,  55,  57,  70,  67,  65,  85,  99,  94,  90, 112, 126, 130,
    ...    142, 120])
    >>> weight = 1.692287392646066e+41
    >>> x = x * weight
    >>> x
    array([  2.70765983e+42,   3.04611731e+42,   3.21534605e+42,
             2.53843109e+42,   4.56917596e+42,   4.39994722e+42,
             2.19997361e+42,   5.75377713e+42,   6.43069209e+42,
             6.09223461e+42,   7.27683579e+42,   7.10760705e+42,
             8.12297948e+42,   8.46143696e+42,   9.30758066e+42,
             9.64603814e+42,   1.18460117e+43,   1.13383255e+43,
             1.09998681e+43,   1.43844428e+43,   1.67536452e+43,
             1.59075015e+43,   1.52305865e+43,   1.89536188e+43,
             2.13228211e+43,   2.19997361e+43,   2.40304810e+43,
             2.03074487e+43])
    >>>
    

    【讨论】:

    • 它确实对我有用。请告诉我们您认为错误的地方。
    • 谢谢,我的错。我先完成了x *= weight,导致出现错误。然后我做了x = x*weight,结果是错误的,在这种情况下(因为x.dtypeint64而不是float64)。
    【解决方案2】:

    以下带有浅拷贝 (s[:]) 的命令将为您创建s 的视图,它的元素类型为int,因此在分配后它会尝试将[i*weight for i in s] 创建的元素分配给@987654325 @ 容器,但由于您的结果是 C 长,因此会引发以下错误:

    OverflowError: Python int too large to convert to C long
    

    如果您只使用[i*weight for i in s],您也会看到结果:

    >>> [i*weight for i in s]
    [-1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60, -1.5608596215653603e+60]
    

    相反,您可以直接多个:

    >>> s = s*weight
    >>> s
    array([  2.70765983e+42,   3.04611731e+42,   3.21534605e+42,
             2.53843109e+42,   4.56917596e+42,   4.39994722e+42,
             2.19997361e+42,   5.75377713e+42,   6.43069209e+42,
             6.09223461e+42,   7.27683579e+42,   7.10760705e+42,
             8.12297948e+42,   8.46143696e+42,   9.30758066e+42,
             9.64603814e+42,   1.18460117e+43,   1.13383255e+43,
             1.09998681e+43,   1.43844428e+43,   1.67536452e+43,
             1.59075015e+43,   1.52305865e+43,   1.89536188e+43,
             2.13228211e+43,   2.19997361e+43,   2.40304810e+43,
             2.03074487e+43])
    

    【讨论】:

    • 您引用的 NumPy 结果不正确(所有数字都相同!)。我本来希望得到正确的结果(就像在 chw21 的回答中一样)。
    • @EOL 是的,这是一个错误的副本!谢谢提醒!
    • s[:] 不会“创建 Python 列表对象”(您可以尝试一下)。相反,它返回s 数组的视图(其中确实包含一些整数类型)。
    • 谢谢。现在几乎是正确的;以下问题也应该修复:s[:] 不会“创建”一个 NumPy 数组对象:正如我所写,它返回一个 view。不执行内存复制(这就是为什么分配给它会修改s)。
    【解决方案3】:

    请注意,numpy.ndarray 实例 x 在创建后将被分配一个唯一类型用于存储的基础数据。这与 Python 原生列表完全不同,后者类似于包含对任意鸭子类型 Python 对象的引用的数组。

    对底层数组数据的后续就地修改(在本例中为切片分配,即实际调用__setitem__ 方法的语法糖)将尝试将值转换为存储类型。在这种情况下,数组x 有整数,但是在赋值的 RHS 计算的浮点值太大而无法转换为整数,导致整数溢出。

    如果您使用合适的浮点类型创建数组,它可能会起作用。在伪 Python 中:

    # Type for the storage of x explicitly set when creating it.
    x = numpy.array([ whatever integer literals ... ], dtype=numpy.float64)
    # Assignment succeeds.
    x[:] = [ some list of floats ... ]
    

    【讨论】:

      【解决方案4】:

      您可以在一次操作中将整个数组与因子相乘,无需将单个元素相乘(这就是numpy 的重点):

      >>> x = array([ 16,  18,  19,  15,  27,  26,  13,  34,  38,  36,  43,  42,  48,
      ...     50,  55,  57,  70,  67,  65,  85,  99,  94,  90, 112, 126, 130,
      ...    142, 120])
      >>> weight = 1.692287392646066e+41
      >>> x * weight
      array([  2.70765983e+42,   3.04611731e+42,   3.21534605e+42,
               2.53843109e+42,   4.56917596e+42,   4.39994722e+42,
               2.19997361e+42,   5.75377713e+42,   6.43069209e+42,
               6.09223461e+42,   7.27683579e+42,   7.10760705e+42,
               8.12297948e+42,   8.46143696e+42,   9.30758066e+42,
               9.64603814e+42,   1.18460117e+43,   1.13383255e+43,
               1.09998681e+43,   1.43844428e+43,   1.67536452e+43,
               1.59075015e+43,   1.52305865e+43,   1.89536188e+43,
               2.13228211e+43,   2.19997361e+43,   2.40304810e+43,
               2.03074487e+43])
      

      【讨论】:

      • 这是一个想法,但它并没有完全回答这个问题:x 应该被修改。警告:有一个陷阱。
      • 你为什么不写你自己的答案,一切都是正确的,没有陷阱,我很乐意学到一些东西。
      • 答案不是评论,这就是为什么:它们服务于不同的目的(此外,已经有一个很好的答案)。问题是更新x,就像问题一样,不能用x *= weight来完成。