エンジニア4年目のブログ

Javaエンジニア4年目のブログです。

floatのお話

どうもShZgZです。

 

本日は雪の影響(おかげ)で少し早く帰れました。諸々お気をつけ下さい。

 

今回はタイトル通り「floatのお話」です。

 

まず、下のコードをご覧下さい。

>>> 27.0 / 10.0 - 17.0 / 10.0 > 1
True

※Python3の計算結果です。

これを見て、「?、当たり前じゃん」となっちゃう方は恐らくこの読んでも面白い事はあまり無いと思いますが、できれば読んで頂いてコメント貰えるととても嬉しい。

 

Paiza解いてる時に詰まった部分なんですが、なんか浮動小数点の計算しててなんか挙動おかしいなと思って確かめてる時にこれを見つけました。

普通に計算したら、

 

27.0 / 10.0 - 17.0 / 10.0  =  2.7 - 1.7 = 1.0

 

1.0 > 1 = False

1.0 < 1 = False

 

こうなってくれるんじゃ無いかと思ってたわけです。

 

でもならない。

 

因みに、

>>> 27.0 / 10.0 - 17.0 / 10.0
1.0000000000000002

こうなりました。

 

簡単にすると、 

>>> 2.6 - 1.6
1.0
>>> 2.7 - 1.7
1.0000000000000002

※因みに、Rustでも同様であることは確認しました。他の言語は試してません。興味ある方は是非試してみて下さい。

 

この原因ですが、そもそも浮動小数点をどう扱っているかというところです。

浮動小数点数の計算はIEEE 754で定められています。←これどういうことかというとプログラミング言語における標準仕様(IEEE 754)に書かれてることだから、それに沿ってる色んな言語で上記のような状況がありえるよってことです。

 

浮動小数点の基本形式に関しては情報処理技術者の試験とかでもあった気がするので説明は割愛します(気になったらWikiとか他のサイトとかを参考にしてみて下さい。今回の話ではわかってなくても大丈夫です。)が、

浮動小数点数である"2.7"はデータとしては"2.7±誤差"となってもっている可能性があるということです。

ここでは先の例があるので2.7としましたが、モチロン他の値でもありえます。

 

要するに、浮動小数点数がデータとしてどのように保持されているかを理解していれば別ですが、よくわかんないという場合には

 

浮動小数点数(1.1, 2.9882, 10.301 ...etc)は、表示されたままではなく誤差があるものとして考えておこう。

 

・まとめ

プログラミングにおいて浮動小数点数を扱う際には、

1.1も中では1.1000000000001とかかもしれないし、2.9882も中では2.9881999999998とかかもしれないから、もしかしたらその浮動小数点数には誤差があるかもしれないと思っておきましょうということ。