How to detect Arithmetic Overflow exceptions

Just had an instance crash and found out it was an Arthimetic Overflow exception by 64_i8 being multiplied by 2.

What are some good ways to mitigate these exceptions?

With that said, is it possible to just return the max value instead of raising an exception? I deal with these numbers all over being multiplied by scaling modifiers. I really don’t want to litter my codebase with redundant if statements checking every single formula :S

Ideally don’t use such small Int types where it’s likely the value could be more than what it can hold. Not really any benefit using Int8 over Int32 unless you have a reason. Alternatively, you can use the wrapping operators https://crystal-lang.org/api/Int128.html#&*(other:Int32):self-instance-method or rescue https://crystal-lang.org/api/OverflowError.html.

2 Likes

I agree so much, I’m really getting sick and tired with dealing all these types other than Int32 and Int64. When I was designing my database, for example, in my character database, the level column is a tinyint, because characters can’t go past level 99. So, the conservative me, is thinking this is the best idea because it seemed like the correct storage type.

Then, I have this method that calculates a player’s experience needed for their next level

START_EXP = 200
def get_next_level_amount(level)
  START_EXP + (START_EXP * level) * (level*2)
end

pp get_next_level_amount(63_i8)

Once a character reaches level 64, it’s broke. All because I decided to be conservative with my storage types, but instead, I’m punished for being frugal. This would have never happened if I set the column to int (Int32 in Crystal).

The general advice is to avoid anything but 32-bit and 64-bit integers. The only use case for smaller sizes in general code is converting to/from binary data formats. And maybe some other edge cases like math operations where you need specific wrapping behaviour.