Je dois être en mesure de déterminer un nombre entier maximal de systèmes dans Ruby. Quelqu'un sait comment, ou si c'est possible?
Réponses:
Ruby convertit automatiquement les entiers en une grande classe d'entiers lorsqu'ils débordent, il n'y a donc (pratiquement) aucune limite à leur taille.
Si vous recherchez la taille de la machine, c'est-à-dire 64 ou 32 bits, j'ai trouvé cette astuce 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 recherchez la taille des objets Fixnum (nombres entiers suffisamment petits pour être stockés dans un seul mot machine), vous pouvez appeler 0.size
pour obtenir le nombre d'octets. Je suppose que ce devrait être 4 sur les versions 32 bits, mais je ne peux pas le tester pour le moment. 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.
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
c'est toujours 64 bits (pas 63 ou 31 bits comme dans YARV) quelle que soit la taille du mot machine, et il n'y a pas de bit d'étiquette.
Lire 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"
Dans ruby, les Fixnums sont automatiquement convertis en Bignums.
Pour trouver le Fixnum le plus élevé possible, vous pouvez 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)
Sans vergogne arraché à une discussion rubis . Regardez là pour plus de détails.
puts (Fixnum::MAX + 1).class
cela ne revient pas Bignum
comme il semble que ce soit le cas. Si vous changez 8
à 16
ce sera.
Il n'y a pas de maximum depuis Ruby 2.4, car Bignum et Fixnum se sont unifiés en Integer. voir Feature # 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 passerait est un manque de mémoire.
comme @ Jörg W Mittag l'a souligné: dans jruby, la taille du numéro fixe est toujours de 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