こんにちは、高木です。
前回は任意精度の整数を扱うためのGMP関数を紹介しました。GMP関数はすごく便利なのですが、整数しか扱うことができません。PHPでC言語やC++の前処理を行うときには、浮動小数点数で初期値を自動生成することも当然ありますので整数型だけでは不十分です。
C言語やC++では、実数の浮動小数点数を扱う型が3種類あります。float型、double型、long double型がそうです。一方でPHPの浮動小数点型は1種類です。型名としてはfloatもdoubleも使われますが、どちらも同じ意味です。そして、PHPのfloat型はint型と同じで環境依存です。多くはIEC 559の倍精度浮動小数点数になっていると思います。
C言語やC++のdouble型も、多くの処理系ではIEC 559の倍精度浮動小数点数を扱っているはずです。ところがlong double型はいろいろで、double型と同じ表現範囲と精度の場合もあれば、80ビットの拡張倍精度浮動小数点数のこともあります。また、GCCなどでは__float128型をサポートしています。このように、PHPのfloat型の表現範囲や精度を超える浮動小数点数を扱うには、任意精度の関数が必要になってきます。
PHPには、任意精度の小数を扱うことができるBCMath関数というものがあります。残念ながらGMP関数のように演算子はオーバーロードされていませんが、そんなに大きな問題はないでしょう。GMP関数ほどたくさんの機能はないものの、算術演算と平方根ぐらいはサポートされています。
BCMath関数には、scaleという省略可能な引数を渡すことができます。これは何かというと、演算結果の小数点以下の桁数です。3を指定すれば、小数点以下第3位までの文字列を返してくれます。毎回scaleを指定するのは面倒なので、bcscale関数を使えば事前にデフォルトのscaleを設定することができます。本当はphp.iniでも指定できるのですが、明示的にbcscale関数を読んだ方がいいでしょうね。
では、実際の使用例と演算結果のコメントを掲載します。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php bcscale(6); echo bcadd('1.23', '4.56') . PHP_EOL; // 5.790000 echo bcsub('1.23', '4.56') . PHP_EOL; // -3.330000 echo bcmul('1.23', '4.56') . PHP_EOL; // 5.608800 echo bcdiv('1.23', '4.56') . PHP_EOL; // 0.269736 echo bcmod('1.23', '4.56') . PHP_EOL; // 1.230000 echo bcpow('1.23', '4') . PHP_EOL; // 2.288866 echo bcpowmod('4', '5', '6') . PHP_EOL; // 4.000000 echo bccomp('1.23', '4.56') . PHP_EOL; // -1 echo bcsqrt('1.23') . PHP_EOL; // 1.109053 ?> |
大体は直感的なのですが、累乗を求めるbcpowの第2引数(指数)は整数でなければなりません。bcpowmod関数は第1~3引数ともに整数でなければなりません。ほかは大丈夫だと思います。
BCMath関数を使う場合は、拡張モジュールをインストールしておく必要があるようです。なお、Windows版では最初からインストールされています。Ubunttuでは、 sudo apt install php8.1-bcmathでインストールすることができました。PHPのバージョンは適宜読み替えてください。