Numpyでは0除算は無限大として処理される
Pythonのみで記載している場合は、例外:ZeroDivisionErrorが発生します。
しかし、NumPyを使用した際には、下記のように値が返されます。
- 0以外の値は0で除算した際は、inf(無限大)
- 0を0で除算した際はnan(定義できないため非数を返却)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Python array = [1,2,3] divide_by_zero = [val / 0 for val in array] print(divide_by_zero) >> Traceback (most recent call last): >> ZeroDivisionError: division by zero // Numpy import numpy as np np_array = np.array([0, 1, 2, 3]) divide_by_zero = np_array / 0 print(list(divide_by_zero)) >> [nan, inf, inf, inf] |
うっかり高速化だ!とか言ってPythonのコードをそのままNumPyにしたりすると、今までZeroDivisionErrorで捕まえてたものを取り逃すことになったりするので要注意。
なお、nanは非数なので計算はできなくなりますが、infは通常の計算はほぼ機能しなくなるものの、その後の計算も出来てしまうので要注意
例外を返すように設定する
Webアプリケーション等での計算はinf(無限大)では成り立たないためか、例外を返すようにする設定があります。
1 2 3 4 5 6 7 8 |
import numpy as np np.seterr(divide='raise') np_array = np.array([0, 1, 2, 3]) divide_by_zero = np_array / 0 print(list(divide_by_zero)) >> Traceback (most recent call last): >> FloatingPointError: divide by zero encountered in true_divide |
基本的にはnumpyを読み込んだ際にはこの設定を付けておいたほうが無難だと思います…
参考)https://docs.scipy.org/doc/numpy-1.16.1/reference/generated/numpy.seterr.html?highlight=seterr#numpy.seterr
おまけ)inf(無限大)は計算ができる
inf以外の数値とは計算結果は異なるものの、各種の演算子を使用することが出来ます。
しかし、通常のアプリケーションでこのような値を使用していいことはないので、対策をすることが殆となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
inf = float('inf') // inf = np.inf でも同様 type(inf) <class 'float'> inf - inf >> nan inf + inf >> inf inf * inf >> inf inf / inf >> nan inf + 1 >> inf inf - 1 >> inf inf * 2 >> inf inf / 10 >> inf inf ** inf >> inf inf ** 0 >> 1.0 inf / 0 >> Traceback (most recent call last): >> ZeroDivisionError: float division by zero |
NumPy等は便利ですが、気をつけて実装しないと思わぬバグを潜めそうで怖い。