hnwの日記

Rubyのround関数の実装が変わってた

今週は国際浮動小数点数ウイークですので、週の最後もやはり浮動小数点数ネタです。


Rubyのround関数の実装に関して、1.8.6 patchlevel 114と1.8.6 patchlevel 230の間に変更が入っています。1.8.6-p230のリリース時期は2008/06/20のようですから、1.8.7(2008/06/01リリース)から変更されたと言っていいかもしれません。


これらは、僅かながら挙動が違っています。MacOSX環境で実験しました。(再現できるのはFreeBSDMacOSXだけのような気がします)

$ /usr/bin/ruby --version
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
$ /usr/bin/ruby -e 'p 9007199254740991.0.round;'
9007199254740992
$ /opt/local/bin/ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9]
$ /opt/local/bin/ruby -e 'p 9007199254740991.0.round;'
9007199254740991


なんと、同じ数字の丸め結果が違う数字になりました。中身を簡単に説明すると、前者は自前実装していたのが、後者はlibmのroundに丸投げしています。roundが無い環境のために自前のroundも用意してありますが、これも1.8.6-p114以前とは異なる実装です。


1.8.6-p114の方が不思議な挙動に見えますので、修正自体は良いと思います。とはいえ、PHP以外の言語でも、マイナーバージョンアップで基本的な関数の実装をいじることがあるんですね。その点は少しビックリしました。

続きを読む