大きな数値の平方根を求めようとしたときにつまづいたことをメモ.
数学的には次の不等式は成り立つ(trueである)はずです.
\sqrt{2^{1024}} < 2^{1024} \ ・・・ \ (1)
しかし,Rubyでこの式を実行すると,結果はfalseになります.
sample1.rb
Math.sqrt(2**1024) < 2**1024
# => false
これはどういうことでしょうか.
実は,RubyのDocを読んでみると,Math::sqrt内部でRFLOAT_VALUEという数値をdouble型に変換するマクロが使われていることが分かります.
そして,double型はIEEE754方式で$2^{1013}$までしか表現できないわけですから(詳しくは参考文献3,4を参照のこと),それ以上の数値は+∞に丸め込まれるわけです.
よって Math::sqrt内部では,2**1024はFloat::INFINYと等価となり,sample1.rbは次のように書き換えることができます.
sample2.rb
Math.sqrt(Float::INFINITY) < 2**1024
# => false
これで,Ruby上では不等式(1)が成り立たない謎が解けました.
この問題を回避するには,sqrt関数を独自にコーディングするしかなさそうです(他の回避方法をご存知の方はコメントをお願いいたします).