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.sizeSie 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))
Fixnumist 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).classkehrt dies nicht so zurück, Bignumwie es scheint. Wenn Sie dazu wechseln 8, 16wird.
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