LoginSignup
7
3

More than 3 years have passed since last update.

[Python] 浮動小数点数floatの比較は要注意!!

Last updated at Posted at 2019-07-16

はじめに

最近Pyhonを勉強し始めた新人です。
今回は浮動小数点数floatの比較について書きたいと思います。

float型の比較

皆さん、以下のコードの出力は何だと思いますか?

test.py
def main():
    x = 0
    for i in range(10):
        x += 0.1

    if x == 1.0:
        print("OK")
    else:
        print("NG")


if __name__ == "__main__":
    main()

0.1を10回足すので、xは1.0になるはずです。
そのため、"OK"が出力されるはず・・・

実際に動かしてみると・・・

実際に動かしてみましょう。

実行
$python test.py
NG

"NG"が表示されます。
数学的には0.1を10回足すと、1.0になるはずですが・・・

xには一体いくつになっているのか?

以下のコードを実行して、型とxの値を確認します。

test.py
def main():
    x = 0
    for i in range(10):
        x += 0.1

    print(type(x))
    print(x)

    if x == 1.0:
        print("OK")
    else:
        print("NG")


if __name__ == "__main__":
    main()

実行結果が以下になります。

実行
$ python test.py
<class 'float'>
0.9999999999999999
NG

型はfloat型、そしてxの値は0.9999999999999999となっています。
一体なぜでしょうか?

float型は小数を正しく表示できない!?

実はfloat型は10進数の小数を正しく表示することが出来ません。

以下のコード結果を見れば分かりますが、format()で表示桁数を増やすと誤差が存在するのが分かります。

test.py
print(0.1)
print(format(0.1, '.20f'))
実行
$ python test.py 
0.1
0.10000000000000000555

float型は2進数で管理されている

表示こそ10進数ですが、内部的には2進数で管理されています。そして、多くの10進数の小数は2進数で表現できません。

例えば十進数の「0.1」を2進数に変換すると「0.0001100110011…」となり、「0011」の部分が永遠に循環します。このような値はどこかの桁数で丸めを行う必要があるため、上記のように誤差が生じます。

また、この話はpythonに限った話ではなく、IEEE 754の2進浮動小数点形式を採用して計算していれば、同じことが起こります。

  • 追記
    float型だけではなく、int型も2進数管理されているみたいです。

対策 math.isclose()を使う

mathモジュールの関数isclose()を使うことによって、近似的な比較を行えます。
これを用いることによってfloat型の比較ができますね。
実際に使ってみましょう。

test.py
import math


def main():
    x = 0
    for i in range(10):
        x += 0.1

    if math.isclose(x, 1.0):
        print("OK")
    else:
        print("NG")


if __name__ == "__main__":
    main()

実行
$ python test.py 
OK

"OK"と表示されました!

まとめ

10進数の小数を比較するときは、誤差が生じることがあることを意識しておく必要がありそうです。
頭の片隅に置いておきましょう。

7
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3