Saya harus dapat menentukan integer maksimum sistem di Ruby. Ada yang tahu caranya, atau apakah itu mungkin?
89
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))
sumber
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"
sumber
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.
sumber
puts (Fixnum::MAX + 1).class
ini tidak kembaliBignum
seperti yang seharusnya. Jika Anda mengubah8
ke16
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.
sumber
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
sumber