Saya harus dapat menentukan integer maksimum sistem di Ruby. Ada yang tahu caranya, atau apakah itu mungkin?
Jawaban:
Ruby secara otomatis mengonversi bilangan bulat menjadi kelas bilangan bulat besar ketika mereka melimpah, jadi (secara praktis) tidak ada batasan seberapa besar mereka bisa.
Jika Anda mencari ukuran mesin, yaitu 64- atau 32-bit, saya menemukan trik ini di 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
Jika Anda mencari ukuran objek Fixnum (bilangan bulat yang cukup kecil untuk disimpan dalam satu kata mesin), Anda dapat memanggil 0.size
untuk mendapatkan jumlah byte. Saya kira itu harus 4 pada build 32-bit, tetapi saya tidak dapat mengujinya sekarang. Juga, Fixnum terbesar ternyata 2**30 - 1
(atau 2**62 - 1
), karena satu bit digunakan untuk menandainya sebagai integer alih-alih referensi objek.
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
selalu 64 Bit (bukan 63 atau 31 bit seperti di YARV) terlepas dari ukuran kata mesin, dan tidak ada bit tag.
Membaca manual ramah? Siapa yang mau melakukan itu?
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"
Dalam ruby Fixnums secara otomatis diubah menjadi Bignum.
Untuk menemukan Fixnum setinggi mungkin, Anda dapat melakukan sesuatu seperti ini:
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)
Merobek tanpa malu-malu dari diskusi ruby-talk . Lihat di sana untuk lebih jelasnya.
puts (Fixnum::MAX + 1).class
ini tidak kembali Bignum
seperti yang seharusnya. Jika Anda mengubah 8
ke 16
itu akan.
Tidak ada jumlah maksimum sejak Ruby 2.4, karena Bignum dan Fixnum disatukan menjadi Integer. lihat Fitur # 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
Tidak akan ada luapan apapun, yang akan terjadi adalah kehabisan memori.
seperti yang ditunjukkan @ Jörg W Mittag: dalam jruby, ukuran nomor tetap selalu sepanjang 8 byte. Cuplikan kode ini menunjukkan kebenaran:
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