Мне нужно уметь определять максимальное целое число системы в Ruby. Кто-нибудь знает, как или возможно ли это?
87
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
), потому что один бит используется для обозначения его как целого числа вместо ссылки на объект.
FIXNUM_MAX = (2**(0.size * 8 -2) -1) FIXNUM_MIN = -(2**(0.size * 8 -2))
источник
Fixnum
всегда 64 бит (а не 63 или 31 бит, как в YARV) независимо от размера машинного слова, и бит тега отсутствует.Читаете дружелюбное руководство? Кто бы хотел это сделать?
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"
источник
В 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)
Беззастенчиво вырванный из разговора о рубиновых разговорах . Смотрите там подробности.
источник
puts (Fixnum::MAX + 1).class
это сделаете, это не вернется,Bignum
как кажется, как должно. Если поменять8
на16
это будет.Начиная с Ruby 2.4 максимума нет, поскольку Bignum и Fixnum объединились в Integer. см. Feature # 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
Переполнения не будет, произойдет нехватка памяти.
источник
как отметил @ 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
источник