98 votes

Ruby max entier

Je dois être capable de déterminer un entier maximum d'un système en Ruby. Est-ce que quelqu'un sait comment, ou si c'est possible ?

84voto

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

55voto

Matthew Crumley Points 47284

Ruby convertit automatiquement les entiers en une classe d'entiers plus grands en cas de dépassement, il n'y a donc (pratiquement) pas de limite à leur taille.

Si vous cherchez la taille de la machine, c'est-à-dire 64- ou 32-bits, j'ai trouvé ce truc sur 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 cherchez la taille des objets Fixnum (entiers assez petits pour être stockés dans un seul mot machine), vous pouvez appeler 0.size pour obtenir le nombre d'octets. Je suppose que cela devrait être de 4 sur les compilations 32-bits, mais je ne peux pas le tester en ce moment. De plus, 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 votes

Je suis sûr que vous voulez 2**(machine_size * 8) -1; 2**4-1=15 ce qui n'est pas très large quoi que ce soit.

0 votes

Désolé, je suppose que j'ai commencé à trop penser aux octets au lieu des bits.

11 votes

AVERTISSEMENT: Le code est inutile. Lisez l'édition, ignorez le code. Il ne trouve pas le maximum de quoi que ce soit pour Ruby. Il le trouve pour le code qui n'utilise pas de pointeurs tagués.

13voto

Andrew Grimm Points 22996

La lecture du manuel convivial ? Qui voudrait faire ça ?

début = Time.now
plus_grand_fixnum_connu = 1
plus_petit_bignum_connu = nil

jusqu'à ce que plus_petit_bignum_connu == plus_grand_fixnum_connu + 1
  if plus_petit_bignum_connu.nil?
    nombre_suivant_à_essayer = plus_grand_fixnum_connu * 1000
  else
    nombre_suivant_à_essayer = (plus_petit_bignum_connu + plus_grand_fixnum_connu) / 2 # La moyenne géométrique serait plus efficace, mais plus risquée
  end

  if nombre_suivant_à_essayer <= plus_grand_fixnum_connu ||
       plus_petit_bignum_connu && nombre_suivant_à_essayer >= plus_petit_bignum_connu
    raise "Cas impossible" 
  end

  case nombre_suivant_à_essayer
    when Bignum then plus_petit_bignum_connu = nombre_suivant_à_essayer
    when Fixnum then plus_grand_fixnum_connu = nombre_suivant_à_essayer
    else raise "Cas impossible"
  end
end

fin = Time.now
puts "Le plus grand fixnum est #{plus_grand_fixnum_connu}"
puts "Le plus petit bignum est #{plus_petit_bignum_connu}"
puts "Le calcul a pris #{fin - début} secondes"

0 votes

Il semble que cela soit la seule réponse qui renvoie des nombres lors de la transition de Fixnum à Bignum, ce qui signifie pour moi que c'est le plus grand Fixnum en Ruby.

11voto

tommym Points 1802

En ruby, les Fixnums sont automatiquement convertis en Bignums.

Pour trouver le plus grand Fixnum possible, 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)

Honteusement repris d'une discussion ruby-talk. Regardez là pour plus de détails.

5 votes

Si vous exécutez puts (Fixnum::MAX + 1).class, cela ne renverra pas Bignum comme cela pourrait sembler. Si vous changez 8 en 16, alors ça le fera.

4voto

estani Points 1167

Il n'y a pas de maximum depuis Ruby 2.4, car Bignum et Fixnum ont été unifiés en Integer. voir Fonctionnalité #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

Il n'y aura pas de débordement, ce qui se produira est une rupture de mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X