2011-04-09
PHP 5.3のround関数の挙動は仕様かも
PHPは4.06までしか知らないJava屋からPHPerのid:hnw氏へ。「PHPの新しいround関数にバグをみつけた」に関して、ちょっと疑問があります。
Bogus扱いにされて怒っているPHP :: Bug #54479ですが、症状は確認できました。
しかし、バグでは無さそうです。まずは以下のコードを見てください。
問題が出るケース
以下のhnw_float_01.phpを書いてみます。有効桁数は17。
ini_set("precision",17);
var_dump(12.345);
var_dump(round(12.345, 1));
実行してみます。おお、確かに問題が出ます。アニソン歌えそうです。
float(12.345000000000001)
float(12.300000000000001)
仮数をギリギリの大きさにしなくても、同じ症状が発生するところがポイントです。
問題が出ないケース
以下のhnw_float_02.phpを書いてみます。有効桁数は16。
ini_set("precision",16);
var_dump(12.345);
var_dump(round(12.345, 1));
あれ、丸め処理される? ウィンクを歌うおじさんの声が聞こえてきました。
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で確認しました。
- 2011-04-03 深林音欲 3/20 15%
- 2011-04-03 tochogi の技術メモ 3/33 9%
- 2011-04-03 seri::Diary 3/47 6%
- 2011-04-03 HHeLiBeXの日記 正道編 3/57 5%