2009-02-11 7 views
71

Je dois être capable de déterminer un nombre entier maximum de systèmes dans Ruby. Quelqu'un sait comment, ou si c'est possible?Ruby max entier

Répondre

42

Ruby convertit automatiquement les entiers en une classe entière lorsqu'ils débordent, il n'y a (pratiquement) aucune limite à leur taille.

Si vous recherchez la taille de la machine, à savoir 64- ou 32 bits, j'ai trouvé this trick at 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 vous êtes à la recherche de la taille des objets FIXNUM (entiers assez petit pour stocker dans un seul mot machine), vous pouvez appeler 0.size pour obtenir le nombre d'octets. Je suppose que cela devrait être 4 sur les versions 32 bits, mais je ne peux pas le tester maintenant. En outre, le plus grand Fixnum est apparemment 2**30 - 1 (ou 2**62 - 1), car un bit est utilisé pour le marquer comme un entier au lieu d'une référence d'objet.

+1

Assez sûr que vous voulez 2 ** (machine_size * 8) -1; 2 ** 4-1 = 15 ce qui n'est pas un très grand chose. – Cebjyre

+0

Oups, je suppose que j'ai commencé à trop penser aux octets plutôt qu'aux bits. –

+10

AVERTISSEMENT: le code est inutile. Lisez l'édition, ignorez le code. Il ne trouve rien de maximum pour Ruby. Il le trouve pour du code qui n'utilise pas de pointeurs étiquetés. –

11

En ruby ​​Fixnums sont automatiquement convertis en Bignums.

Pour trouver le plus haut possible Fixnum que vous pourriez faire quelque chose comme ceci:

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) 

Shamelessly d'un ruby-talk discussion arraché. Regardez là pour plus de détails.

+5

Si vous faites 'puts (Fixnum :: MAX + 1) .class' cela ne retourne pas' Bignum' comme il se doit. Si vous changez «8» à «16», il le fera. –

+0

ce n'est pas disponible maintenant – allenhwkim

12

Vous lisez le manuel convivial? Qui voudrait faire ça?

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" 
+0

Cela semble être la seule réponse qui renvoie des nombres à la transition de Fixnum à Bignum, qui, pour moi, signifie que c'est le plus grand Fixnum en Ruby. –

78
FIXNUM_MAX = (2**(0.size * 8 -2) -1) 
FIXNUM_MIN = -(2**(0.size * 8 -2)) 
+5

Pourquoi avez-vous soustrait 2 bits au lieu de 1 pour le signe? J'ai testé cela et cela semble correct, mais pourquoi Ruby utilise-t-il 2 bits pour le signe? – Matthias

+27

@Matthias Un bit supplémentaire est utilisé pour marquer la valeur comme un entier (par opposition à un pointeur sur un objet). –

+0

Intéressant, merci! – Matthias

0

que @ Jörg W Mittag a souligné: dans JRuby, fixer la taille numérique est toujours 8 octets. Cet extrait de code montre la vérité:

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