Ruby'de bir sistem maksimum tamsayısı belirleyebilmem gerekiyor. Nasıl ya da mümkün olup olmadığını bilen var mı?
Yanıtlar:
Ruby tam sayıları taştıklarında otomatik olarak büyük bir tamsayı sınıfa dönüştürür, bu nedenle (pratik olarak) ne kadar büyük olabileceklerine dair bir sınır yoktur.
Makinenin boyutunu, yani 64 veya 32 bit arıyorsanız, bu numarayı ruby-forum.com'da buldum :
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
Fixnum nesnelerinin boyutunu (tek bir makine kelimesinde saklanacak kadar küçük tamsayılar) arıyorsanız 0.size
, bayt sayısını öğrenmek için arayabilirsiniz . Sanırım 32 bitlik yapılarda 4 olmalı, ancak şu anda bunu test edemiyorum. Ayrıca, en büyük Fixnum görünüşe göre 2**30 - 1
(veya 2**62 - 1
) çünkü bir bit onu bir nesne referansı yerine bir tamsayı olarak işaretlemek için kullanılır.
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
her zaman 64 Bit (değil 63 veya YARV gibi 31 bit) bakılmaksızın makine kelime büyüklüğü ve hiçbir etiket bit yoktur.
Dostça kılavuzu okuyor musunuz? Bunu kim yapmak ister?
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"
Ruby'de Fixnumlar otomatik olarak Bignums'a dönüştürülür.
Mümkün olan en yüksek Fixnum'u bulmak için aşağıdaki gibi bir şey yapabilirsiniz:
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)
Yakut konuşmalarından utanmazca koparılmış . Daha fazla ayrıntı için oraya bakın.
puts (Fixnum::MAX + 1).class
, Bignum
olması gerektiği gibi görünmez . Eğer değiştirirseniz 8
için 16
bunun olacaktır.
Ruby 2.4'ten beri, Bignum ve Fixnum'un Tamsayı olarak birleşmesinden bu yana maksimum yoktur. bkz Özelliği # 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
Herhangi bir taşma olmayacak, ne olacak bir hafıza yetersizliği.
@ Jörg W Mittag'ın belirttiği gibi: jruby'de fix num size her zaman 8 bayt uzunluğundadır. Bu kod parçası gerçeği gösteriyor:
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