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?
87
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))
la source
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"
la source
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.
la source
puts (Fixnum::MAX + 1).class
cela ne revient pasBignum
comme il semble que ce soit le cas. Si vous changez8
à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.
la source
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
la source