ゼロ除算

ゼロで割ることはできません。無理に割ろうとすると

1 / 0

ZeroDivisionError というエラーになります。

しかし、コンピュータによる数値計算では、a / b のような割り算のときに、たまにしか起こらないエラーのためにいちいち b がゼロかどうか確認するのは面倒ですし、速度的にも不利です。

そこで、浮動小数点演算の IEEE 754 という規格では、1.0 / 0.0 に相当する「無限大」という数や、0.0 / 0.0 に相当する「非数」という数を導入して、割り算がエラーにならない仕組みを用意しています。

この仕組みをどう使うかは、言語によって異なります。

R では、1 / 0 と打ち込むと Inf(Infinity = 無限大)と返ってきます。0 / 0NaN(Not a Number = 非数)になります。いずれにしても、エラーで止まることはありません。

Ruby では、1 / 00 / 0 は ZeroDivisionError になって止まりますが 1.0 / 0.0Infinity0.0 / 0.0NaN になります。C言語でも同じです。

ところが Python では 0 で割っても 0.0 で割っても ZeroDivisionError になり、そこで実行が止まってしまいます。これでは不便です。もちろん

try:
    x = a / b
except ZeroDivisionError:
    if a == 0:
        x = float("nan")
    else:
        x = float("inf")

のようなことはできますが、面倒です。

Python でゼロで割って止まらないようにするには、NumPy を使います:

import numpy as np

a = np.array([1.0, 0.0, -0.0])
print(a[0] / a[1])
print(a[1] / a[1])
print(a[0] / a[2])
inf
nan
-inf

ただし、RuntimeWarning(実行時の警告)が出ます。RuntimeWarning を出したくなければ、あらかじめ

np.seterr(divide="ignore", invalid="ignore")

と打ち込んでおきます(invalid とは 0/0 のこと)。元に戻すには

np.seterr(divide="warn", invalid="warn")

とします。デフォルトは

np.seterr(divide="warn", over="warn", under="ignore", invalid="warn")

で、ゼロ除算・オーバーフロー・0/0 が警告、アンダーフローが無視です。

特定の割り算だけ warn しないようにするには

with np.errstate(divide="ignore", invalid="ignore"):
    x = a[0] / a[1]

のようにします。

似た問題に「0の0乗」があります。Wikipediaの Zero to the power of zero で解説されているように、多くの処理系で1になります。Pythonも 0 ** 0 は1、0.0 ** 0.0 は1.0です。