【プログラミング】小数の比較結果が思い通りにならない。float/double型を正しく比較する方法

f:id:orchid-bell:20181210011913j:plain

float型やdouble型などの浮動小数点型は、演算結果が正しくならないことがありますので注意が必要です。

  

プログラムの世界では、0.1+0.2=0.3にならないことがある

0.1 + 0.2 = 0.3。小学生の算数レベルの知識があれば解ける問題ですね。
しかし、コンピューターの世界では実はこれが当たり前ではないんです。

ご存知の方も多いと思いますが、コンピューターは2進数で数値を表現します。実はこの2進数、小数の扱いが非常に苦手です。

例えば2進数の「0.1」は10進数の「0.5」を表します。
2進数の「0.01」は10進数の「0.25」、2進数の「0.001」は10進数の「0.0125」となります。では、10進数「0.1」を2進数で表現するとどうなるか?

10進数「0.1」は、2進数「0.0001100110011……」となり、正確に表現しきれません。(「0011」部分が永久に繰り返されます)

つまり、どこかで桁を区切って値を丸める必要が出てきますので誤差が生じます。この誤差が原因で0.1+0.2=0.3という単純な式がなりたたなくなってしまうのです。

※2進数の詳しいメカニズムは以下の記事が分かりやすいので、興味がある方はご参照ください。
http://sunny.shinshu-u.ac.jp/contents/innercomp/2sinsyou.htm

 

小数を正しく比較するには、Decimal型などの専用の型を使う

小数を正しく比較するには、プログラミング言語に用意された専用の型を使います。

.NETであればDecimal型JavaであればBigDecimalです。

また、型の概念がなかったり、あいまいな言語では、専用の関数が用意されていることがあります。例えばPHPでは任意精度数学関数を使うことで、この問題を解決することができます。

そのような型や処理がない場合は、次のようにあらかじめ値を整数型に変換しておくことで対処することもできます。

int x = 0.1 * 10
int y = 0.2 * 10
int z = 0.3 * 10
if ( x + y = z )