Necesito poder determinar un número entero máximo del sistema en Ruby. ¿Alguien sabe cómo, o si es posible?
87
Ruby convierte automáticamente los enteros en una clase de entero grande cuando se desbordan, por lo que (prácticamente) no hay límite para su tamaño.
Si está buscando el tamaño de la máquina, es decir, 64 o 32 bits, encontré este truco en 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
Si está buscando el tamaño de los objetos Fixnum (números enteros lo suficientemente pequeños como para almacenarlos en una sola palabra de máquina), puede llamar 0.size
para obtener el número de bytes. Supongo que debería ser 4 en compilaciones de 32 bits, pero no puedo probar eso en este momento. Además, el Fixnum más grande es aparentemente 2**30 - 1
(o 2**62 - 1
), porque se usa un bit para marcarlo como un número entero en lugar de una referencia de objeto.
FIXNUM_MAX = (2**(0.size * 8 -2) -1) FIXNUM_MIN = -(2**(0.size * 8 -2))
fuente
Fixnum
siempre es de 64 bits (no de 63 o 31 bits como en YARV) independientemente del tamaño de la palabra de la máquina, y no hay bit de etiqueta.¿Leyendo el manual amigable? ¿Quién querría hacer eso?
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"
fuente
En ruby, los Fixnums se convierten automáticamente en Bignums.
Para encontrar el Fixnum más alto posible, puede hacer algo como esto:
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)
Desvergonzadamente arrancado de una discusión de rubí . Busque allí más detalles.
fuente
puts (Fixnum::MAX + 1).class
esto no regresaBignum
como debería. Si cambia8
a16
lo hará.No hay un máximo desde Ruby 2.4, ya que Bignum y Fixnum se unificaron en Integer. ver Característica # 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
No habrá ningún desbordamiento, lo que pasaría es una falta de memoria.
fuente
como señaló @ Jörg W Mittag: en jruby, el tamaño del número fijo es siempre de 8 bytes de longitud. Este fragmento de código muestra la verdad:
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
fuente