I need to be able to determine a systems maximum integer in Ruby. Anybody know how, or if it's possible?
Ruby automatically converts integers to a large integer class when they overflow, so there's (practically) no limit to how big they can be.
If you are looking for the machine's size, i.e. 64- or 32-bit, I found this trick at 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
If you are looking for the size of Fixnum objects (integers small enough to store in a single machine word), you can call 0.size
to get the number of bytes. I would guess it should be 4 on 32-bit builds, but I can't test that right now. Also, the largest Fixnum is apparently 2**30 - 1
(or 2**62 - 1
), because one bit is used to mark it as an integer instead of an object reference.
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
is always 64 Bit (not 63 or 31 bit like in YARV) regardless of machine word size, and there is no tag bit. –
Megasporophyll Ruby automatically converts integers to a large integer class when they overflow, so there's (practically) no limit to how big they can be.
If you are looking for the machine's size, i.e. 64- or 32-bit, I found this trick at 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
If you are looking for the size of Fixnum objects (integers small enough to store in a single machine word), you can call 0.size
to get the number of bytes. I would guess it should be 4 on 32-bit builds, but I can't test that right now. Also, the largest Fixnum is apparently 2**30 - 1
(or 2**62 - 1
), because one bit is used to mark it as an integer instead of an object reference.
Reading the friendly manual? Who'd want to do that?
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 Fixnums are automatically converted to Bignums.
To find the highest possible Fixnum you could do something like this:
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)
Shamelessly ripped from a ruby-talk discussion. Look there for more details.
puts (Fixnum::MAX + 1).class
this doesn't return Bignum
like it seems like it should. If you change 8
to 16
it will. –
Tomy There is no maximum since Ruby 2.4, as Bignum and Fixnum got unified into Integer. see 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
There won't be any overflow, what would happen is an out of memory.
as @Jörg W Mittag pointed out: in jruby, fix num size is always 8 bytes long. This code snippet shows the truth:
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
© 2022 - 2024 — McMap. All rights reserved.