kazu22002の技術覚書

PHPer, Golang, AWS エンジニアの日々

PHPの数値について考える(2)

PHPの浮動小数点数で気になったことが。

floatの比較について「等しいかどうかを比較するのには問題があります」って。

あぁ、そうなのか。どういう場合だろ。

 

まず浮動小数点数 (あるいは "float", "double", "実数") の指定から。

 <?php
$a = 1.234; 
$b = 1.2e3; 
$c = 7E-10;
?>

 規約として

LNUM          [0-9]+
DNUM          ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})

 

ここで初めて知りましたが、指数が使えたんですね。。。

 

比較の話に戻ります。

比較については浮動小数点数の精度の話が影響しています。

書いてある内容としては

・少数点数の桁数が多くなると丸め誤差が発生する

有理数のいくつか(0.1や0.7)は正確に表現できない

 

少数点の計算は気をつけてね!

って話なのか。これは。

 

回避方法も書いてあります。

浮動小数点数値が等しいかどうかを調べるには、比較時の丸め誤差の上界を用います。

この値は計算機イプシロンあるいは丸め単位と呼ばれ、 計算時に扱える最小の差分を表します。

言っている事はなんとなくわかりますが、計算時に毎回これは考えてプログラムは組めない。。。

 

とりあえずサンプルコードを見てみます。

$a と $b は、精度 5 桁では等しくなります。

<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;

if(abs($a-$b) < $epsilon) {
    echo "true";
}
?>

ある指定した桁数以下かどうかをみてるのかな。

丸められててもOKって計算だと推測。

(精度7桁まで等しいけど、5桁?深くかんがえちゃだめだ。)

 

金融とかだとすごく影響があるらしい。

知っておいても損はないかと。