Rubyの最大整数


87

Rubyでシステムの最大整数を決定できる必要があります。誰かがその方法を知っていますか、それが可能かどうか?

回答:


49

Rubyは、整数がオーバーフローすると自動的に大きな整数クラスに変換するため、(実際には)大きさに制限はありません。

マシンのサイズ、つまり64ビットまたは32ビットを探している場合は、ruby-forum.comでこのトリックを見つけました。

machine_bytes = ['foo'].pack('p').size
machine_bits = machine_bytes * 8
machine_max_signed = 2**(machine_bits-1) - 1
machine_max_unsigned = 2**machine_bits - 1

Fixnumオブジェクトのサイズ(単一のマシンワードに格納するのに十分小さい整数)を探している場合は、を呼び出し0.sizeてバイト数を取得できます。32ビットビルドでは4になるはずですが、現時点ではテストできません。また、最大のFixnumは明らかに2**30 - 1(または2**62 - 1)です。これは、オブジェクト参照ではなく整数としてマークするために1ビットが使用されるためです。


1
2 **(machine_size * 8)-1が必要なことは間違いありません。2 ** 4-1 = 15これはそれほど大きくはありません。
Cebjyre 2009

おっと、私はビットではなくバイトについて考えすぎたと思います。
Matthew Crumley

10
警告:コードは役に立ちません。編集を読み、コードを無視します。Rubyの最大値は何も見つかりません。タグ付きポインタを使用しないコードでそれを見つけます。
CJ。

現在(2018-01-21)Windowsの64ビットRubyでも32ビットです(一方、cygwinには適切な64ビットがあります)
greywolf 2018年

81
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))

5
符号に1ビットではなく2ビットを減算したのはなぜですか?これをテストしたところ、正しいようですが、Rubyが符号に2ビットを使用するのはなぜですか?
マティアス

29
@Matthias(オブジェクトへのポインタではなく)値を整数としてマークするために、追加のビットが使用されます。
Matthew Crumley 2012年

2
これは、少なくともJRubyには当てはまりません。JRubyでは、Fixnumマシンのワードサイズに関係なく、常に64ビット(YARVのように63ビットや31ビットではありません)であり、タグビットはありません。
イェルクWミッターク

13

フレンドリーなマニュアルを読んでいますか?誰がそれをしたいですか?

start = Time.now
largest_known_fixnum = 1
smallest_known_bignum = nil

until smallest_known_bignum == largest_known_fixnum + 1
  if smallest_known_bignum.nil?
    next_number_to_try = largest_known_fixnum * 1000
  else
    next_number_to_try = (smallest_known_bignum + largest_known_fixnum) / 2 # Geometric mean would be more efficient, but more risky
  end

  if next_number_to_try <= largest_known_fixnum ||
       smallest_known_bignum && next_number_to_try >= smallest_known_bignum
    raise "Can't happen case" 
  end

  case next_number_to_try
    when Bignum then smallest_known_bignum = next_number_to_try
    when Fixnum then largest_known_fixnum = next_number_to_try
    else raise "Can't happen case"
  end
end

finish = Time.now
puts "The largest fixnum is #{largest_known_fixnum}"
puts "The smallest bignum is #{smallest_known_bignum}"
puts "Calculation took #{finish - start} seconds"

これは、FixnumからBignumへの移行時に数値を返す唯一の答えのようです。これは、私にとって、Rubyで最大のFixnumであることを意味します。
ブリキの

11

Rubyでは、Fixnumは自動的にBignumに変換されます。

可能な限り最高のFixnumを見つけるには、次のようにします。

class Fixnum
 N_BYTES = [42].pack('i').size
 N_BITS = N_BYTES * 8
 MAX = 2 ** (N_BITS - 2) - 1
 MIN = -MAX - 1
end
p(Fixnum::MAX)

ルビートークの議論から恥知らずに引き裂かれました。詳細については、こちらをご覧ください。


5
これを行うと、本来のようにputs (Fixnum::MAX + 1).class戻らないBignumようになります。あなた816それに変更するならば、そうするでしょう。
ブリキの

これは現在利用できません
allenhwkim 2013

1

BignumとFixnumが整数に統合されたため、Ruby2.4以降の上限はありません。機能#12005を参照してください

> (2 << 1000).is_a? Fixnum
(irb):322: warning: constant ::Fixnum is deprecated
=> true

> 1.is_a? Bignum
(irb):314: warning: constant ::Bignum is deprecated
=> true

> (2 << 1000).class
=> Integer

オーバーフローは発生しません。発生するのはメモリ不足です。


0

@JörgWMittagが指摘したように、jrubyでは、修正numサイズは常に8バイト長です。このコードスニペットは真実を示しています。

fmax = ->{
  if RUBY_PLATFORM == 'java'
    2**63 - 1
  else
    2**(0.size * 8 - 2) - 1
  end
}.call

p fmax.class     # Fixnum

fmax = fmax + 1  

p fmax.class     #Bignum
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.