루비 최대 정수


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가되어야한다고 생각하지만 지금은 테스트 할 수 없습니다. 또한 객체 참조 대신 정수로 표시하는 데 1 비트가 사용되기 때문에 가장 큰 Fixnum은 분명히 2**30 - 1(또는 2**62 - 1)입니다.


1
2 ** (machine_size * 8) -1; 2 ** 4-1 = 15는 그다지 크지 않습니다.
Cebjyre

죄송합니다. 비트 대신 바이트에 대해 너무 많이 생각하기 시작했습니다.
Matthew Crumley

10
경고 : 코드는 쓸모가 없습니다. 편집 내용을 읽고 코드를 무시하십시오. Ruby에 대한 최대 값을 찾지 못했습니다. 태그가있는 포인터를 사용하지 않는 코드를 찾습니다.
CJ.

이제 (2018-01-21) Windows의 64 비트 루비에서도 32 비트입니다 (cygwin에는 적절한 64 비트가 있음)
graywolf

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

5
부호에 대해 1 대신 2 비트를 뺀 이유는 무엇입니까? 나는 이것을 테스트했고 그것이 옳은 것 같지만 왜 Ruby가 부호에 2 비트를 사용합니까?
Matthias 2012

29
@Matthias 추가 비트는 값을 정수로 표시하는 데 사용됩니다 (개체에 대한 포인터가 아니라).
Matthew Crumley 2012 년

2
적어도 JRuby에게는 사실이 아닙니다. JRuby에서는 Fixnum머신 워드 크기에 관계없이 항상 64 비트 (YARV에서와 같이 63 비트 또는 31 비트가 아님)이며 태그 비트가 없습니다.
Jörg W Mittag

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임을 의미합니다.
The Tin Man

11

루비에서 Fixnums는 자동으로 Bignums로 변환됩니다.

가능한 가장 높은 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이를 것입니다.
The Tin Man

이것은 지금 사용할 수 없습니다
allenhwkim 2013

1

Bignum과 Fixnum이 Integer로 통합 되었기 때문에 Ruby 2.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örg W Mittag가 지적했듯이 jruby에서 수정 번호 크기는 항상 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.