餡子付゛録゛

ソフトウェア開発ツールの便利な使い方を紹介。

PHP 5.3のround関数の挙動は仕様かも

PHPは4.06までしか知らないJava屋からPHPerのid:hnw氏へ。「PHPの新しいround関数にバグをみつけた」に関して、ちょっと疑問があります。
Bogus扱いにされて怒っているPHP :: Bug #54479ですが、症状は確認できました。
しかし、バグでは無さそうです。まずは以下のコードを見てください。

問題が出るケース

以下のhnw_float_01.phpを書いてみます。有効桁数は17。

実行してみます。おお、確かに問題が出ます。アニソン歌えそうです。

$ php hnw_float_01.php
float(12.345000000000001)
float(12.300000000000001)

仮数をギリギリの大きさにしなくても、同じ症状が発生するところがポイントです。
単にIEEE754形式では、12.3も12.300000000000001も同じ値になるためです。つまり、有効桁数17桁を指定しても、PHPが17桁を扱えないためです。

問題が出ないケース

以下のhnw_float_02.phpを書いてみます。有効桁数は16。

あれ、丸め処理される? ウィンクを歌うおじさんの声が聞こえてきました。

$ php hnw_float_02.php
float(12.345)
float(12.3)

理由はたぶん単純、倍精度の桁数は10進数で16桁だから

英語版のwikipediaに、仮数は53 bits(sをつけるか-BITにしてね)で、10進数に直すとだいたい16桁って書いてある。

its significand has a precision of 53 bits (about 16 decimal digits).

デフォルトはini_set("precision",14);なので、仕様の問題は17以上を指定したときの挙動だと思います。
PHPの挙動を変更するとすれば、値が17以上は警告を出して、かつ自動的に16に再設定するのが適切かと。
間違っていたらごめんなさい。PHPは4.06までしか良く分からないんです。

PHP 5.2.17で問題が出ない理由

PHP 5.2.xまでは、80bitsで計算していたら、19桁でもいけたのでしょうね。
浮動小数点演算はPHPでしちゃいけないと、ばーちゃんの友達の隣人の他人が言っていたのを夢で見たので、詳しい事は分かりません。後はPHPerの皆様、よろしくお願いします。

その他

PHP 5.3.2-1ubuntu4.7で確認しました。
浮動小数点演算を使うなら、こういうモノに使いたいです。