Eu preciso ser capaz de determinar um número inteiro máximo do sistema em Ruby. Alguém sabe como, ou se é possível?
87
Ruby converte inteiros automaticamente em uma classe de inteiro grande quando eles estouram, então não há (praticamente) limite para o quão grande eles podem ser.
Se você está procurando o tamanho da máquina, ou seja, 64 ou 32 bits, encontrei este truque em 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
Se você estiver procurando pelo tamanho dos objetos Fixnum (inteiros pequenos o suficiente para armazenar em uma única palavra de máquina), você pode chamar 0.size
para obter o número de bytes. Eu acho que deveria ser 4 em compilações de 32 bits, mas não posso testar isso agora. Além disso, o maior Fixnum é aparentemente 2**30 - 1
(ou 2**62 - 1
), porque um bit é usado para marcá-lo como um inteiro em vez de uma referência de objeto.
FIXNUM_MAX = (2**(0.size * 8 -2) -1) FIXNUM_MIN = -(2**(0.size * 8 -2))
fonte
Fixnum
é sempre 64 bits (não 63 ou 31 bits como em YARV), independentemente do tamanho da palavra da máquina, e não há bit de tag.Lendo o manual amigável? Quem iria querer fazer isso?
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"
fonte
Em rubi, Fixnums são automaticamente convertidos em Bignums.
Para encontrar o Fixnum mais alto possível, você pode fazer algo assim:
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)
Desavergonhadamente arrancado de uma conversa de rubi . Procure aqui para mais detalhes.
fonte
puts (Fixnum::MAX + 1).class
isso, não retornaráBignum
como deveria. Se você mudar8
para16
isso.Não há máximo desde o Ruby 2.4, já que Bignum e Fixnum foram unificados em Integer. ver Recurso # 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
Não haverá transbordamento, o que aconteceria é uma falta de memória.
fonte
como @ Jörg W Mittag apontou: em jruby, fix num size tem sempre 8 bytes de comprimento. Este snippet de código mostra a verdade:
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
fonte