Ruby max intero


89

Devo essere in grado di determinare un numero intero massimo di sistemi in Ruby. Qualcuno sa come o se è possibile?

Risposte:


50

Ruby converte automaticamente gli interi in una grande classe di interi quando superano, quindi non c'è (praticamente) alcun limite a quanto possono essere grandi.

Se stai cercando la dimensione della macchina, cioè 64 o 32 bit, ho trovato questo trucco su 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 stai cercando la dimensione degli oggetti Fixnum (numeri interi abbastanza piccoli da poter essere memorizzati in una singola parola macchina), puoi chiamare 0.sizeper ottenere il numero di byte. Immagino che dovrebbe essere 4 su build a 32 bit, ma non posso testarlo in questo momento. Inoltre, il Fixnum più grande è apparentemente 2**30 - 1(o 2**62 - 1), perché un bit viene utilizzato per contrassegnarlo come numero intero anziché come riferimento a un oggetto.


1
Abbastanza sicuro che tu voglia 2 ** (machine_size * 8) -1; 2 ** 4-1 = 15 che non è nulla di molto grande.
Cebjyre,

Ops, immagino di aver iniziato a pensare troppo ai byte anziché ai bit.
Matthew Crumley,

10
ATTENZIONE: il codice è inutile. Leggi la modifica, ignora il codice. Non trova il massimo per Ruby. Lo trova per il codice che non utilizza puntatori con tag.
CJ.

ora (2018-01-21) è a 32 bit anche in rubino a 64 bit su Windows (cygwin ha 64 bit adeguati d'altra parte)
graywolf

81
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))

5
Perché hai sottratto 2 bit invece di 1 per il segno? Ho provato questo e sembra essere corretto, ma perché Ruby usa 2 bit per il segno?
Matthias

29
@ Matthias Un bit extra viene utilizzato per contrassegnare il valore come un numero intero (al contrario di un puntatore a un oggetto).
Matthew Crumley

2
Questo non è vero per JRuby, almeno. In JRuby, Fixnumè sempre a 64 bit (non 63 o 31 bit come in YARV) indipendentemente dalla dimensione della parola macchina e non è presente alcun bit di tag.
Jörg W Mittag

13

Leggere il manuale amichevole? Chi vorrebbe farlo?

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"

Questa sembra essere l'unica risposta che restituisce numeri alla transizione da Fixnum a Bignum, che, per me, significa che è il più grande Fixnum in Ruby.
Tin Man

11

In ruby ​​Fixnum vengono convertiti automaticamente in Bignum.

Per trovare il Fixnum più alto possibile potresti fare qualcosa del genere:

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)

Spudoratamente strappato da una discussione sui discorsi rubini . Guarda lì per maggiori dettagli.


5
Se lo fai puts (Fixnum::MAX + 1).classnon ritorna Bignumcome sembra che dovrebbe. Se si modifica 8per 16lo farà.
Tin Man

1

Non c'è un massimo da Ruby 2.4, poiché Bignum e Fixnum sono stati unificati in Integer. vedere la caratteristica # 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

Non ci sarà alcun trabocco, quello che succederebbe è un esaurimento della memoria.


0

come ha sottolineato @ Jörg W Mittag: in jruby, la dimensione del numero fisso è sempre lunga 8 byte. Questo frammento di codice mostra la verità:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.