NaN - 無限を求めて -
世の中には浮動小数点数というものがあるのだけれど、こいつは便利なような不便なようなやつだ。まぁ、その辺は「まつもと直伝 プログラミングのオキテ 第15回 浮動小数点数の謎に満ちた世界」や「IEEE754 倍精度浮動小数点数のフォーマット」をはじめとして方々で解説されているので略そう。
さて、最近は浮動小数点数といえば IEEE 754 の事を意味する事が多い。IEEE 754 ではいくつか数でない「数」が規定されている。具体的には Infinity と NaN だ。IEEE 754 準拠な処理系ならば、これらも浮動小数点数として扱う事が出来る。
Rubyist としては当然これらを Ruby でも扱いたくなるのだが、ここで問題が発生する。Ruby の組み込み浮動小数点クラスである Float は C 言語の double の上に構築されている。つまり、C 言語のレベルでポータブルならば Ruby でも自然とポータブルになるし、C 言語でポータブルでないものを Ruby レベルでポータブルにしようと思うならば、実装でがんばる必要が出てくる。Ruby はそれなりに移植性を重視しているので、C90 までしか仮定していない。言い換えると、Ruby の実装をする際には、C レベルで IEEE 754 に準拠しているとは限らないのだ。極論すれば、Ruby の Float では必ずしも Infinity や NaN が存在するとは限らないと言う事になる。
この事は Float::INFINITY や Float::NAN といった定数を作れないという問題に影響し、今まで幾度も議論されてきた。(ruby-dev:1657 ruby-dev:4760 ruby-list:7023 ruby-list:46690 ruby-core:26632 ruby-talk:41352 ruby-talk:203333)
とは言っても、最初の IEEE 754-1985 ができてからもう 25 年、世のほとんどの処理系は IEEE 754 準拠になっており、C レベルでマクロが定義されていないなどといった違いはあれど、中身は基本的に変わらないように見える。(x86 系がその他のプロセッサと挙動が違ったりといった話はある。「strictfpの実装」ruby-math:802)
結局の所、簡単に得る方法がないだけで、そこに Infinity はあるのだ。コンパイラが Infinity を扱えないのならば手も足も出ないが、対応しているならば話は簡単、創ってやればよい。C 言語において任意のバイト列を作る方法はいくつかある。1 つは ruby-list:46710 にもある通り、共用体を使う方法。BSD 系で Infinity を作る際にもこの方法が使われている。もう1つがBinary Hacks の HACK #97 に載っているポインタを使った方法。どちらもエンディアンを考慮する必要がある。
以上の話は、Infinity が存在することが前提にあるので、存在しない場合は使えない。既に VAX にはない事が指摘されているが……まぁ、知ったこっちゃないよね。
というわけで、r26197 にて入りました。妖しい環境を持っている方は試してみてください。