Posted at

Python3のfloat型の誤差について

(Project Eulerについてのネタバレを含みます)

  

    

    

  

    

  

  

  

  

  

   

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

   

  

  

  

  

  

  

  

  

  

  

Project Eulerの16を解いていた。

https://projecteuler.net/problem=16

やってること自体は単純で2^1000をひたすら0になるまで10で割った余りを出してそれを足して元の数を10で割ることを繰り返すだけ、なのだけど...

  

  

  

最初に作ったのがこれ


16.py

a = 2**1000

print(a)
sum = 0
while a>0:
b = a % 10
sum += b
a = int(a / 10)
print(sum)

これだと出力が

1189

となる。しかしこれは正しい答えではなくて困惑してしまった。そこで調べてみてこんなものを見つけた。

  

  

https://paiza.hatenablog.com/entry/2017/08/01/Python3%E3%81%A7%E5%B7%A8%E5%A4%A7%E3%81%AA%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E8%A8%88%E7%AE%97%E3%81%AE%E7%B5%90%E6%9E%9C%E3%81%8C%E5%A4%89%E3%81%A0%E3%81%A3%E3%81%9F%E3%81%AE%E3%81%A7%E7%90%86

これによるとfloat型だと大分計算の誤差が発生してしまうらしい。int(a / b)という書き方を結構使っていた(つまりfloat型で計算→int型に変換)自分としては衝撃的な記事だった。これからは//を使っていこうと反省。

  

    

  

コードを以下のように書き換えた。


16.py

a = 2**1000

print(a)
sum = 0
while a!=0:
b = a % 10
sum += b
a = a // 10
print(sum)

すると以下の通り、計算結果がだいぶ違うことが分かる。

1366

こちらは正解だったのでやはりintで通すべきだったのだろう。誤差って怖いと改めて感じた。