Рубин Макс целое - PullRequest
       20

Рубин Макс целое

76 голосов
/ 11 февраля 2009

Мне нужно иметь возможность определить максимальное целое число систем в Ruby. Кто-нибудь знает, как, или если это возможно?

Ответы [ 5 ]

79 голосов
/ 10 апреля 2009
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
44 голосов
/ 11 февраля 2009

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, чтобы получить количество байтов. Я предполагаю, что это должно быть 4 на 32-битных сборках, но я не могу проверить это сейчас. Кроме того, наибольшее значение Fixnum, по-видимому, 2**30 - 1 (или 2**62 - 1), поскольку один бит используется для обозначения его как целого числа вместо ссылки на объект.

12 голосов
/ 12 февраля 2009

Читаете дружественное руководство? Кто бы хотел это сделать?

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"
11 голосов
/ 11 февраля 2009

В рубине 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)

Бесстыдно оторванный от разговора о рубине . Смотрите там для более подробной информации.

0 голосов
/ 27 марта 2017

как указал @ 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
...