解决Python中的错误Overflow Encountered in Double_Scalars

Python库包Numpy下定义的双精度标量是数据类型为double的值。此数据类型用于计算大数值。

通常,这些数字的大小变得如此之大,以至于程序运行到溢出状态并显示警告overflow encountered in double_scalars。本文将解释双标量中的溢出,导致此问题的某些情况,以及如何解决。

Python中错误 overflow encountered in double_scalars 的原因

双标量具有较高和较低的范围。使用较小数字的算术计算通常会产生结果,但当这些数字的幂超过某个阈值时,就会出现overflow encountered in double_scalars的问题。

让我们看一个例子来理解它。

这个程序显示双标量的范围,在范围的边界显示计算结果,然后显示溢出错误发生的点;显示警告overflow encountered in double_scalars

程序导入Python包numpy并将错误处理设置为all='warn',这将在运行时引发错误警告。

import numpy as np
np.seterr(all='warn')

为了找到numpy数据类型的范围,我们将使用数据类型例程finfo。这个例程在被调用时,返回系统内浮点类型的限制,如双标量。

找到双标量的下限,即,它的最小值,将需要像- np.finfo(np.double).min这样的语法。在该程序中,使用minmax子程序找到最小值和最大值。

print("Range of numpy double:", np.finfo(np.double).min, np.finfo(np.double).max)

为了找到范围边界处的值,创建了数据类型为A的numpy数组double。这个数组有一个值为143的元素。

第0个索引值被复制到变量a,以将该值从该数组中提升到其自身的幂。然后使用a**a将此变量提升到其自身的幂。

A = np.array([143], dtype='double')
a = A[0]
print("At the border:", a ** a)

程序正常运行,直到上面的代码,但当一个操作在给定的双标量范围之外执行时,会出现overflow encountered in double_scalars

将创建一个新数组B,它存储的值大于前一个数组中用于重现此警告的值。

当此值提高到其自身的幂时,程序显示警告overflow encountered in double_scalars

import numpy as np
np.seterr(all='warn')
print("Range of numpy double:", np.finfo(np.double).min, np.finfo(np.double).max)
A = np.array([143], dtype='double')
a = A[0]
print("At the border:", a ** a)
B = np.array([144], dtype='double')
b = B[-1]
print("Blowing out of range:", b ** b)

输出:

C:/Users/Win 10/PycharmProjects/overflow_longscalars/2.py:11: RuntimeWarning: overflow encountered in double_scalars
  print("Blowing out of range:", b ** b)
Range of numpy double: -1.7976931348623157e+308 1.7976931348623157e+308
At the border: 1.6332525972973913e+308
Blowing out of range: inf

解决错误的方法 overflow encountered in double_scalars

如上面的示例所示,跨越数据类型的最高范围可能导致overflow encountered in double_scalars。避免这种错误的最好方法是在给定的范围内工作或增加计算能力。

但在某些情况下,数据类型会造成瓶颈。这里有一个程序,传达了同样的警告。

数据类型float32的第一个数组在值143被提升到其自身的幂时溢出。这是因为float可以携带多达8位的指数。

另一方面,数据类型double可以承受多达11个指数位的计算,这就是它不会进入溢出并产生结果的原因。

import numpy as np
np.seterr(all='warn')
A = np.array([143], dtype=np.float32)
a = A[-1]
print("Array with datatype float:", a ** a)
B = np.array([143], dtype=np.double)
b = B[-1]
print("Array with datatype double", b ** b)

输出:

当程序试图执行a**a时,程序会遇到类似于双标量的溢出,并在输出中显示inf,这意味着结果是无限的。

但是,当使用不同的数据类型时,我们会得到所需的结果。

Array with datatype float: inf
Array with datatype double 1.6332525972973913e+308
C:/Users/Win 10/PycharmProjects/overflow_longscalars/5.py:7: RuntimeWarning: overflow encountered in float_scalars
  print("Array with datatype float:", a ** a)

一些计算使用无穷大来表示超出范围的结果,这意味着结果是巨大的。

float64这样的数据类型的数字范围是从-1.79769313486e+308到1.79769313486e+308。观察到变大或变小导致溢出。

例如,如果最大范围np.double(1.79769313486e+308)乘以1.1,则接收到overflow encountered in double_scalars运行时警告。

必须记住,这只是一个警告,它将继续运行。

但是,由于该数字太大,因此无法返回1。相反,它提供了inf

虽然一些有效的计算使用无穷大,但有些计算会产生nan,它代表没有数字,如下面的程序所示。

import numpy as np
var1 = np.inf - 10 ** 6
var2 = np.inf + 10 ** 6
var3 = np.inf / 10 ** 6
var4 = np.inf * 10 ** 6
var5 = np.inf * (-10 ** 6)
var6 = 1 / np.inf
var7 = np.inf * np.inf
var8 = np.inf/np.inf
var9 = np.inf-np.inf
print(var1, var2, var3, var4, var5, var6, var7, var8, var9)

输出:

inf inf inf inf -inf 0.0 inf nan nan

上面的程序显示了所有可能遇到无穷大和nan的情况。

有时一个程序并没有进入溢出或显示无穷大或NaN的状态,但产生的结果不仅不准确,而且明显不正确。

在下面的示例中,数组A被声明为数据类型int64。此数据类型根据所使用的机器存储不同的位。

当存储在此变量中的值被提升到其自身的幂时,程序将输出无意义的值,而不是发生溢出或显示无穷大。

例如,像50这样的正整数,当其自身的幂时,应该产生一个正整数,但是当执行下面的代码时,结果是一个负值。

import numpy as np
np.seterr(all='warn')
A = np.array([50], dtype=np.int64)
a = A[-1]
print(a ** a)

输出:

-6646187150092009472

但是当相同的值存储在像doublelongdouble这样的数据类型中时,我们会得到适当的结果。

import numpy as np
np.seterr(all='warn')
A = np.array([50], dtype=np.longdouble)
a = A[-1]
print(a ** a)

输出:

8.881784197001252e+84

注意:必须记住,运行时警告overflow encountered in double_scalars只能在数字沿着数据类型的范围出现时才能避免。

虽然超出该范围不会中断程序并产生错误,但忽略警告overflow encountered in double_scalars可能会导致不稳定的结果。

Python中出现的其他溢出警告

本节将教我们捕捉溢出错误,而不是双标量。主要有两个经常出现的其他溢出。

  1. power发生溢出

    numpy子例程power用于将一个数提高到其自身的幂,并且结果超出范围时,它抛出错误overflow encountered in power

    import numpy as np
    np.seterr(all='warn')
    print(np.power(143, 144, dtype=np.double))
    

    输出:

    inf
    C:/Users/main.py:12: RuntimeWarning: overflow encountered in power
    print(np.power(143, 144, dtype=np.double))
    
  2. power发生溢出

    在使用指数的操作期间会遇到这种溢出。将一个数字提高到大指数的幂得到inf,而将其除以该数字得到零。

    import numpy as np
    print(1*(1+np.exp(1140)))
    print(1/(1+np.exp(1140)))
    

    输出:

    inf
    0.0
    C:/Users/main.py:7: RuntimeWarning: overflow encountered in exp
    print(1*(1+np.exp(1140)))
    C:/Users/main.py:8: RuntimeWarning: overflow encountered in exp
    print(1/(1+np.exp(1140)))
    

结论

这篇文章解释了如何规避运行时警告,如overflow encountered in double_scalars等。阅读完本文后,读者可以很容易地发现溢出错误。