BLOGスタッフブログ

インソースマーケティングデザイン

2014.12.12 システム

[PHP]PHPで小数計算する?

こんにちは。エンジニアの高田です。
先日はまったPHPでの小数計算…。
PHPで小数点は扱わないほうがいいらしいですよ。
まぁ扱わざるを得ない場合もあるので、注意点や方法をご紹介します。

まずは、PHPマニュアルの「浮動小数点」についての記述の確認。特に「警告」部分。
http://php.net/manual/ja/language.types.float.php

echo floor((0.1+0.7)*10);

※floor→端数の切り捨て

この結果はどうなると思います?
括弧の中を先に計算するからぁ・・・
おそらく「8」が出力されるでしょう!と予想されます。
しかしたいてい「7」が出力されるそうです。
これは、(この計算結果の) 内部的な値が 7.9999999999999991118… のようになっているからだそうです。
そしてその端数を切り捨てるから「7」が出力される。

これは、浮動小数点型(floatもしくはdouble)で扱える値の限界値も整数型と同じく、
プラットフォームに依存するとマニュアルに記載されています。
ただし、通常は10進数で14桁の精度があるそうです。

浮動小数点は2進数のため、2進数変換する際、小数に若干の狂いが生じる場合がある、という事です。

それでは、小数値を扱うためにはどうしたらよいでしょう?

PHPマニュアルには
「より高い精度が必要な場合には、 任意精度数学関数(BC Math 関数)または gmp 関数を代わりに使用してください。 」
と書いてあります。

ということで、今回はPHPに用意されている任意精度計算用の関数を使用してこの誤差問題を回避することができました。
BC Math 関数」ですね。

但し、BC Math関数を使用する場合、別途インストールが必要ですので注意が必要です!

このBC Math関数を使用して、上記計算をすると。。。

echo floor(bcmul(bcadd(0.1, 0.7, 1), 10, 1)); // 精度は小数点以下1桁で

※bcadd→2つの任意精度の数値を「加算」する
※bcmul→2つの任意精度数値の「乗算」を行う
※floor→端数の切り捨て

この計算の場合、小数点以下は1桁で十分なので、精度は「1」を指定しています。
結果は、ちゃんと「8」が出力されます。

PHPに限らず、多くの言語で発生する有名な問題だそうなので、
小数点を扱う計算は注意が必要ですね。
以上です。ではまた。

インソースマーケティングデザインが書いた他の記事

見積もり・ご依頼など、
お気軽にご相談ください

本サイトはユーザーエクスペリエンスの向上などを目的に、Cookieを使用しています。
右記のバナーで「同意する」をクリックする、または本サイトを利用することにより、
お客様は弊社のCookieポリシーに同意したことになります。

同意します