PHP
PHPの浮動小数点数演算
えだ
更新日:2021/08/04
突然ですがPHPの浮動小数点演算について紹介です。
PHPで正確な小数点計算はできない!
PHPでの正確な小数点計算方法を求めてでググって来られた方には申し訳ありませんが、結論から申しますと電卓のような小数点計算はできません。
論より証拠、まずはコチラを見て下さい。
1 |
var_dump(0.1 + 0.2 === 0.3); |
実行結果:boolean false
あれれ、おかしいな。なぜtrueじゃないんだろう?
理屈は次のとおりです。
数値はハードウェア的に2進数で表現されており、浮動小数点数は正確に表現できません。
たとえば0.1(10分の1)は循環小数(repeating fraction)となります。
ここで曲者有り難いのがPHPの表示仕様です。
小数値に対して2進数近似値である10進小数での近似値を表示するので、var_dumpしても勝手に丸まって見えているという事に気づかないのです。
他の言語でも浮動小数点数問題はありますが、ここまでフワッとしている仕様はPHPならではではないでしょうか。
これらの値はnumber_formatで文字列表記してみるとよくわかります。
1 |
var_dump(0.1); |
実行結果:float 0.1
1 |
var_dump(number_format(0.1,100)); |
実行結果:string ‘0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000’ (length=102)
1 |
var_dump(number_format(0.2,100)); |
実行結果:string ‘0.2000000000000000111022302462515654042363166809082031250000000000000000000000000000000000000000000000’ (length=102)
1 |
var_dump(number_format(0.3,100)); |
実行結果:string ‘0.2999999999999999888977697537484345957636833190917968750000000000000000000000000000000000000000000000’ (length=102)
そりゃズレますよね。
ちなみに差分を出すとこんなカンジです。
1 |
var_dump(0.1 + 0.2 - 0.3); |
実行結果:float 5.55111512313E-17
またひとつ勉強になりました。
何故出来ないのかという問い合わせにはこう答えましょう。
「浮動小数点数はハードウェア的に2進数で保有されており、循環小数となるため近似値でしか表せません!」と。
詳しくはマニュアルを確認して下さい。
http://php.net/manual/ja/language.types.float.php