解決済み: Python の Double_Scalars でオーバーフローが発生する
-
Python での
double_scalars でオーバーフローが発生しました
エラーの原因 -
エラー
double_scalars でオーバーフローが発生しました
を回避する方法 - Python で発生するその他のオーバーフロー警告
- まとめ
Python ライブラリ パッケージ Numpy
で定義されている double スカラーは、データ型 double の値です。 このデータ型は、大きな数の計算に使用されます。
多くの場合、これらの数値の大きさが大きくなりすぎて、プログラムがオーバーフロー状態になり、double_scalars でオーバーフローが発生しました
という警告が表示されます。 この記事では、double スカラーのオーバーフロー、この問題を引き起こす特定の状況、およびその解決方法について説明します。
Python での double_scalars でオーバーフローが発生しました
エラーの原因
ダブルスカラーには、より高い範囲とより低い範囲があります。 より小さい数の算術計算は通常結果を生成しますが、これらの数が特定のしきい値を超えて累乗されると、double_scalars でオーバーフローが発生する
という問題が発生します。
それを理解するために例を見てみましょう。
このプログラムは double スカラーの範囲を表示し、範囲の境界で計算を表示し、次にオーバーフロー エラーが発生したポイントを表示します。 double_scalars でオーバーフローが発生しました
という警告が表示されます。
プログラムは Python パッケージ numpy
をインポートし、エラー処理を all='warn'
に設定します。これにより、実行時にエラーの警告が発生します。
import numpy as np
np.seterr(all="warn")
numpy
データ型の範囲を見つけるには、データ型ルーチン finfo
を使用します。 このルーチンは、呼び出されると、システム内の double scalar のような浮動小数点型の制限を返します。
double スカラーの下限、つまりその最小値を見つけるには、np.finfo(np.double).min
のような構文が必要です。 このプログラムでは、min
および max
サブルーチンを使用して最小値と最大値を見つけます。
print("Range of numpy double:", np.finfo(np.double).min, np.finfo(np.double).max)
範囲の境界で値を見つけるために、データ型 double
の numpy 配列 A
が作成されます。 この配列には、値 143
を持つ単一の要素があります。
0 番目のインデックス値を変数 a
にコピーして、この値をこの配列から自分自身で累乗します。 次に、この変数は、a**a
を使用してそれ自身の累乗になります。
A = np.array([143], dtype="double")
a = A[0]
print("At the border:", a ** a)
プログラムは上記のコードまでは正常に実行されますが、演算が double_scalars の指定された範囲外で実行されると、double_scalars でオーバーフローが発生しました
が発生します。
この警告を再現するために、前の配列で使用された値よりも大きな値を格納する新しい配列 B
が作成されます。
この値を自分自身で累乗すると、プログラムは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
エラー double_scalars でオーバーフローが発生しました
を回避する方法
上記の例に見られるように、データ型の最高範囲を超えると、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
を掛けると、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
しかし、同じ値が double
や longdouble
のようなデータ型に格納されている場合、適切な結果が得られます。
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 found in double_scalars
は、数値がデータ型の範囲内に収まるまでしか回避できないことに注意してください。
その範囲外に出てもプログラムが中断されてエラーが発生することはありませんが、double_scalars でオーバーフローが発生しました
という警告を無視すると、結果が不安定になる可能性があります。
Python で発生するその他のオーバーフロー警告
このセクションでは、double スカラー以外のオーバーフロー エラーをキャッチする方法を説明します。 他に主に 2つのオーバーフローが頻繁に発生します。
-
power
で発生したオーバーフローnumpy
サブルーチンpower
を使用して数値をそれ自体の累乗に累乗し、その結果が範囲外になると、overflow found 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))
-
exp
で発生したオーバーフローこの種のオーバーフローは、指数の操作中に発生します。 数値を巨大な指数で累乗すると
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)))
まとめ
この記事では、double_scalars で発生したオーバーフロー
などの実行時の警告を回避する方法について説明します。この記事を読み終えた読者は、オーバーフロー エラーを簡単に見つけることができます。