Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add a signed integer to an unsigned integer in Rust?

Tags:

rust

Do I have to branch on the sign of the signed integer, like in the example below? (In the real program y is calculated to change the index pointing into a 64K array, and wraparound is the desired behavior)

fn main() {
    let mut x: u16 = 100;
    let y: i8 = -1;
    //x += y;
    if y < 0 {
        x -= i8::abs(y) as u16;
    } else {
        x += i8::abs(y) as u16;
    }
    println!("{}", x);
}
like image 647
Alexey Avatar asked Nov 23 '18 22:11

Alexey


2 Answers

  • Signed integers are twos complement
  • numeric cast sign extends an i8 as u16

That means you can cast y as u16 it will turn into a twos complement value that a wrapping_add will rightfully handle if y was negative.

In short: do as @Veedrac said.

fn main() {
    let mut x: u16 = 100;
    let y: i8 = -1;
    x = x.wrapping_add(y as u16);
    println!("{}", x);
}
like image 181
kmkaplan Avatar answered Nov 15 '22 10:11

kmkaplan


If you're on nightly, we now have the unstable feature mixed_integer_ops.

With this you can do:

#[feature(mixed_integer_ops)]
fn main() {
    let mut x: u16 = 100;
    let y: i8 = -1;
    //x += y;
    x = x.wrapping_add_signed(y); // wraps on overflow
    println!("{}", x);
}

There's wrapping_, checked_, saturating_, and overflowing_ variants, depending on what behavior you want on overflow; and the methods are on both signed and unsigned integers, named _unsigned and _signed respectively (so the above could also be expressed as x = y.wrapping_add_unsigned(x);)

like image 42
Zoey Hewll Avatar answered Nov 15 '22 09:11

Zoey Hewll