解決済み: Python の Double_Scalars でオーバーフローが発生する

Jay Shaw 2023年6月21日
  1. Python での double_scalars でオーバーフローが発生しました エラーの原因
  2. エラー double_scalars でオーバーフローが発生しました を回避する方法
  3. Python で発生するその他のオーバーフロー警告
  4. まとめ
解決済み: Python の Double_Scalars でオーバーフローが発生する

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

しかし、同じ値が 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 found in double_scalars は、数値がデータ型の範囲内に収まるまでしか回避できないことに注意してください。

その範囲外に出てもプログラムが中断されてエラーが発生することはありませんが、double_scalars でオーバーフローが発生しました という警告を無視すると、結果が不安定になる可能性があります。

Python で発生するその他のオーバーフロー警告

このセクションでは、double スカラー以外のオーバーフロー エラーをキャッチする方法を説明します。 他に主に 2つのオーバーフローが頻繁に発生します。

  1. 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))
    
  2. 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 で発生したオーバーフローなどの実行時の警告を回避する方法について説明します。この記事を読み終えた読者は、オーバーフロー エラーを簡単に見つけることができます。