hnwの日記

roundとprintfの丸めに関する不整合

さて、先日の記事「PHP5.3.0alpha3のround関数の実装がPHP5.2.6と変わった」でも紹介したPHPのround関数を改善する提案には、printfとの整合性についても書かれています。というのも、printfで"%.2f"などと精度を指定した場合、round関数と同様に丸めが発生するからです。


提案文書によれば提案者は「以前はprintfもroundに合わせるべきだと思っていたが、やはりprintfは他の言語でもよく使われているから変更すべきではない。ドキュメントに違いが書いてあれば十分だ。」という結論に至ったようで、PHP5.3.0のprintfは変更されていません。


不整合が存在しても実際に困ることは無いのでしょうが、「不整合があるよ」と聞くのは気分の良いものではありません。さすがPHPだなあ、という気分になりましたが、他の言語でどうなっているのか気になったので、念のためPythonでも実験してみました。例によってMacOSX環境です。

$ python -c 'x=0.235; print "%.2f\n%f" % (x, round(x,2))'
0.23
0.240000
$ python -c 'x=0.236; print "%.2f\n%f" % (x, round(x,2))'
0.24
0.240000


0.235をprintfモドキ(Pythonのこれは何と言うんでしょう?)とround関数とを使って小数点以下第2位までに丸めてみたところ、違う結果になりました。なんだ、Pythonも整合性とれてないんだ。


さすがPHPとか言ってごめんなさい。


補足しておくと、Linux環境のPythonでは不整合を見つけられませんでした。それはそれで不思議な気がします。でも不整合が見つかりました。ソースを読まずに想像で書きますが、内部的にシステムのsprintfを呼んでいる気がします。つまり、最初から整合性を取る気がゼロなんでしょう。

$ python -c 'x=0.125; print "%.2f\n%f" % (x, round(x,2))'
0.12
0.130000


そもそもCのprintfでの丸め方式自体が未定義なんですね。それなら不整合があってもいいや。