For most operators that might overflow, Rust provides a checked version. For example, to test if an addition overflows one could use checked_add
:
match 255u8.checked_add(1) {
Some(_) => println!("no overflow"),
None => println!("overflow!"),
}
This prints "overflow!"
. There is also a checked_shl
, but according to the documentation it only checks if the shift is larger than or equal to the number of bits in self
. That means that while this:
match 255u8.checked_shl(8) {
Some(val) => println!("{}", val),
None => println!("overflow!"),
}
is caught and prints "overflow!"
, This:
match 255u8.checked_shl(7) {
Some(val) => println!("{}", val),
None => println!("overflow!"),
}
simply prints 128
, clearly not catching the overflow.
What is the correct way to check for any kind of overflow when shifting left?
Check these out. Which one does * correspond to? Rust provides the following methods to handle overflows: checked_mul, saturating_mul, wrapping_mul, overflowing_mul. (other operations are supported as well) So your example can be rewritten as: let z = match x.checked_mul (y) { Some (val) => val, None => { ...
The “shift left” testing movement is about pushing testing toward the early stages of software development. By testing early and often, a project can reduce the number of bugs and increase the quality of the code. The goal is to not find any critical bugs during the deployment phase that require code patching.
There can be overflow only if signs of two numbers are same, and sign of sum is opposite to the signs of numbers. 1) Calculate sum 2) If both numbers are positive and sum is negative then return -1 Else If both numbers are negative and sum is positive then return -1 Else return 0
Check for Integer Overflow. Write a “C” function, int addOvf (int* result, int a, int b) If there is no overflow, the function places the resultant = sum a+b in “result” and returns 0. Otherwise it returns -1.
I'm not aware of any idiomatic way of doing this, but something like implementing your own trait would work: Playground
The algorithm is basically to check if there are not fewer leading zeros in the number than the shift size
#![feature(bool_to_option)]
trait LossCheckedShift {
fn loss_checked_shl(self, rhs: u32) -> Option<Self>
where Self: std::marker::Sized;
}
impl LossCheckedShift for u8 {
fn loss_checked_shl(self, rhs: u32) -> Option<Self> {
(rhs <= self.leading_zeros()).then_some(self << rhs)
// in stable Rust
// if rhs <= self.leading_zeros() { Some(self << rhs) }
// else { None }
}
}
fn main() {
match 255u8.loss_checked_shl(7) {
Some(val) => println!("{}", val),
None => println!("overflow!"), // <--
}
match 127u8.loss_checked_shl(1) {
Some(val) => println!("{}", val), // <--
None => println!("overflow!"),
}
match 127u8.loss_checked_shl(2) {
Some(val) => println!("{}", val),
None => println!("overflow!"), // <--
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With