浮動小数点数の比較

プログラミングの常識ではありますが、PHPでも浮動小数点数の比較には注意が必要です。例えば、次のプログラム。
$a = 8;
$b = (0.1 + 0.7) * 10;

if ($a == $b) {
  echo '等しい';
} else {
  echo '等しくない';
}
「(0.1 + 0.7) * 10 = 8」だから、出力は「等しい」! と思いきや、「等しくない」と出力されてしまいます(実行環境によって誤差があるようですが…)。

これは、(0.1 + 0.7)の結果が、PHPの内部では 0.79999999999999991118...のようになっているからです。ちなみに、$b = 0.8 * 10; とすると、「等しい」と出力されます。浮動小数点数について詳しくは、PHPマニュアル:浮動小数点数を参照して下さい。


では、浮動小数点数の比較をするにはどうすればよいか? これもPHPマニュアルに書いてあるやり方ですが、
$a = 8;
$b = (0.1 + 0.7) * 10;
$epsilon = 0.00001; // 小数点数の丸め誤差上限

if (abs($a - $b) < $epsilon) {
  echo '等しい';
} else {
  echo '等しくない';
}
という風に、小数点数の丸め誤差上限を定めた上で、2つの値の差分の絶対値をとって誤差を測定すればよいのです。ここでは、小数点以下5桁の精度で比較しています。実験してみたところ、上のプログラムであれば、小数点以下40桁の精度でも「等しい」という結果が出ます。