Necesito poder determinar un número entero máximo del sistema en Ruby. ¿Alguien sabe cómo, o si es posible?
Respuestas:
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))
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"
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.
puts (Fixnum::MAX + 1).class
esto no regresa Bignum
como debería. Si cambia 8
a 16
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.
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