Ich muss in der Lage sein, eine maximale System-Ganzzahl in Ruby zu bestimmen. Weiß jemand wie oder ob es möglich ist?
Antworten:
Ruby konvertiert Ganzzahlen automatisch in eine große Ganzzahlklasse, wenn sie überlaufen, sodass ihre Größe (praktisch) unbegrenzt ist.
Wenn Sie nach der Größe des Computers suchen, dh 64- oder 32-Bit, habe ich diesen Trick bei ruby-forum.com gefunden :
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
Wenn Sie nach der Größe von Fixnum-Objekten suchen (Ganzzahlen, die klein genug sind, um in einem einzelnen Maschinenwort gespeichert zu werden), können 0.size
Sie die Anzahl der Bytes abrufen . Ich würde vermuten, dass es bei 32-Bit-Builds 4 sein sollte, aber das kann ich momentan nicht testen. Das größte Fixnum ist anscheinend 2**30 - 1
(oder 2**62 - 1
), da ein Bit verwendet wird, um es als Ganzzahl anstelle einer Objektreferenz zu markieren.
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
ist immer 64 Bit (nicht 63 oder 31 Bit wie in YARV), unabhängig von der Größe des Maschinenworts, und es gibt kein Tag-Bit.
Das freundliche Handbuch lesen? Wer würde das machen wollen?
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"
In Ruby werden Fixnums automatisch in Bignums konvertiert.
Um das höchstmögliche Fixnum zu finden, können Sie Folgendes tun:
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)
Schamlos aus einer Ruby-Talk-Diskussion herausgerissen . Suchen Sie dort nach weiteren Details.
puts (Fixnum::MAX + 1).class
kehrt dies nicht so zurück, Bignum
wie es scheint. Wenn Sie dazu wechseln 8
, 16
wird.
Seit Ruby 2.4 gibt es kein Maximum mehr, da Bignum und Fixnum zu Integer vereinigt wurden. siehe 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
Es wird keinen Überlauf geben, was passieren würde, ist ein Mangel an Speicher.
wie @ Jörg W Mittag betonte: In jruby ist die Größe der festen Nummer immer 8 Byte lang. Dieses Code-Snippet zeigt die Wahrheit:
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