64bit環境のRubyで現在のDripの変換規則を使っとき、Fixnumで表現できるのはどれくらいか、計算してみましょう。
まずFixnumの最大の整数を探してみましょう。64bitですから、そこから順に小さくしてみます。
>> (2 ** 64).class => Bignum >> (2 ** 63).class => Bignum >> (2 ** 62).class => Bignum >> (2 ** 61).class => Fixnum
2 ** 62 と 2 ** 61 の間にBignumとFixnumの境界がありそうです。2 ** 62 - 1で試します。
>> (2 ** 62 - 1).class => Fixnum
見つけました。Fixnumです。2 ** 62 - 1が最大ですね。これをDripのキーの規則でTimeにしてみましょう。
>> Time.at(* (2 ** 62 - 1).divmod(1000000)) => 148108-07-06 23:00:27 +0900
だいたい14万年ころです。私の生きている間はFixnumで表現できそうです。
最小のFixnumはいくつでしょう。なんとなく気付いた人もいると思いますが、最小のFixnumは-(2 ** 62)です。Fixnumになるのは-(2 ** 62)から(2 ** 62 - 1)。つまり64bitマシンのRubyのFixnumは、63bitの符号つき整数です。64bitの符号つき整数ではありません。RubyのFixnumはオブジェクトの表現に密接な関係があります。整数のobject_idを調べてみましょう。
>> 0.object_id => 1 >> 1.object_id => 3 >> 2.object_id => 5 >> (-1).object_id => -1 >> (-2).object_id => -3
Fixnum nのobject_idは 2 * n + 1 と決まっています。Ruby内部ではオブジェクトはポインタ幅の整数で識別されています。多くのオブジェクトはアロケートされた空間を示しますが、Fixnumのためにメモリを確保するのは効率が悪いので、下位1bitが1の時は番地ではなく、整数そのものとして扱うことにしています。Fixnumであることを示すフラグに1bit使ってしまったので、Fixnumは63bit符号つき整数の範囲となりました。なお、32bitマシンでは31bit符号つき整数となります。
他にも特別なobject_idを持つオブジェクトがあります。
>> [false, true, nil].collect {|x| x.object_id} => [0, 2, 4]
Rubyの内部を少しだけ覗いてみました。