7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Math.sqrt(2**1024) < 2**1024はfalse?

Last updated at Posted at 2015-07-21

大きな数値の平方根を求めようとしたときにつまづいたことをメモ.
数学的には次の不等式は成り立つ(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関数を独自にコーディングするしかなさそうです(他の回避方法をご存知の方はコメントをお願いいたします).

参考文献

  1. Module: Math (Ruby 2.0.0),Ruby Doc
  2. Rubyのソース,The Ruby Cross Reference
  3. 浮動小数点数,MathWorks
  4. まつもと直伝 プログラミングのオキテ 第15回 浮動小数点数の謎に満ちた世界,ITpro
7
7
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?