Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add or multiply two i16 in Rust to form an i32 without overflowing?

How to add or multiply two i16 numbers in Rust into a larger i32 without overflowing?

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i32 = a + b; // throws EO308 "Expected `u32`, found `u16`
like image 507
Petrus Theron Avatar asked Jan 27 '23 01:01

Petrus Theron


1 Answers

There are no integral promotions or implicit casts in Rust, so you must do all type conversions manually.

For casts, you can use <value> as <type>. However, if the destination type is a superset of the original one and converting it cannot lose information (such as your case), you can self-document that by using <type>::from:

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i32 = i32::from(a) + i32::from(b);
assert_eq!(c, 65534);

This particular case cannot overflow, but for other cases you can prevent overflows using {integer}::checked_*() functions:

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: Option<i16> = a.checked_add(b);
assert_eq!(c, None); //overflow!

Note that overflowing an integer operation panics by default in debug builds.

If what you want is wrapping arithmetic, just like in old C, you can use {integer}::wraping_*(), with the additional bonus that it works for signed as well as unsigned values.

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i16 = a.wrapping_add(b);
assert_eq!(c, -2);
like image 163
rodrigo Avatar answered Jan 29 '23 08:01

rodrigo