简体   繁体   中英

How do I add a signed integer to an unsigned integer in Rust, checking for unsigned overflow?

I want to add an isize to a usize and include bounds checking so that the result does not overflow the bounds of a usize . How can this be done?

You could use a combination of isize::is_negative() , isize::wrapping_abs() , usize::checked_add() and usize::checked_sub() .

const fn add(lhs: usize, rhs: isize) -> Option<usize> {
    if rhs.is_negative() {
        lhs.checked_sub(rhs.wrapping_abs() as usize)
    } else {
        lhs.checked_add(rhs as usize)
    }
}

Why isize::is_negative() vs rhs < 0 ? In this case, it doesn't change anything, as logical operations on literals count as constant expressions .

However, while it is allowed for literals it is not allowed in general, as traits methods cannot be const . So if you had a wrapping type, eg Foo(isize) then it wouldn't be allowed to say foo < Foo(0) in a const context. Though, it would be possible to say foo.is_negative() as Foo could still implement a const fn is_negative() .

Yes, you'd still be able to say foo.0 < 0 , but that's besides the point I was trying to make.

One way to do this would be with a function like the following:

fn signed_unsigned_add(x: usize, y: isize) -> usize {
    let (n, overflow) = x.overflowing_add(y as usize);
    if (y >= 0) ^ overflow {
        n
    } else {
        panic!(
            "signed + unsigned addition overflow: {} + {}",
            x,
            y,
        )
    }
}

This takes advantage of the fact that such an addition, when looked at in terms of unsigned numbers, should only "overflow" (ie exhibit two's-complement behaviour) when the unsigned number is negative, and if it doesn't do so when the number is negative, this indicates underflow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM