From Int to BigInt

Hi there
is it possibile to automatic convert from Int to BigInt?
Example:

puts (2**30)
puts (2**40)

the first line is ok, the second is an overflow… how can i provide a way to get an automatic conversion in situations like this? for example in a loop…

Thanks

Crystal will not automatically convert between numeric types on overflow. You should use the numeric type that will work with your values.

1 Like

If you really want to do this, you can use exceptions:

require "big"

n = 1i8
increasing_size_ints = [Int8, Int16, Int32, Int64, BigInt]

max = BigInt.new(Int128::MAX)
max * 2

while n < max
  begin
    n *= 2
  rescue
    new_type = increasing_size_ints[increasing_size_ints.index(n.class).not_nil! + 1]
    n = new_type.new(n)
    n *= 2
  end
end

p! n # => 170141183460469231731687303715884105728

… or just use a large enough data type right from the start :man_shrugging:

2 Likes

Thank you all. Obviously the question was intended to address the case of anomalous situations that should arise

Following up on this, if you need growing integers you really ought to use BigInt. On my machine, it was 3 times faster for the code above.

Full Code
require "big"
require "time"

max = BigInt.new(Int128::MAX)
max * 2
increasing_size_ints = [Int8, Int16, Int32, Int64, BigInt]

n = 1i8

# growing ints
n_time = Time.measure do
  while n < max
    begin
      n *= 2
    rescue
      new_type = increasing_size_ints[increasing_size_ints.index(n.class).not_nil! + 1]
      n = new_type.new(n)
      n *= 2
    end
  end
end

m = BigInt.new(1)

# big_int
m_time = Time.measure do
  while m < max
    m *= 2
  end
end

p! n, n_time
p! m, m_time
Output
n      # => 170141183460469231731687303715884105728
n_time # => 00:00:00.000033894
m      # => 170141183460469231731687303715884105728
m_time # => 00:00:00.000010804

I guess if the issue is that you want to keep the data types small when the values are small, maybe the exception approach works, but honestly I’m not even sure that’s true for unions like that.

1 Like