如何将负i32数字添加到usize变量?

时间:2019-01-04 08:56:29

标签: rust integer integer-overflow unsigned-integer

例如:

let mut a : usize = 0xFF;
a += -1;  // -1 may be from other variable, so there can't be a -= 1;
println!("{}", a);

输出为:

error[E0277]: the trait bound `usize: std::ops::Neg` is not satisfied

反正?

1 个答案:

答案 0 :(得分:3)

您的尝试不起作用,因为在Rust中,您只能在严格相似的类型之间进行操作。 Rust不会进行任何隐式数值转换,因为这将是一个脚步,如下所示:您有一个特例,有几种溢出方法。

一种可行的方法是将i32的绝对值转换为usize并根据它是负数还是正数来添加或删除它。但是,您必须处理在取其绝对值时溢出的最小值的特殊情况:

fn add(u: usize, i: i32) -> usize {
    if i.is_negative() {
        u - i.wrapping_abs() as u32 as usize
    } else {
        u + i as usize
    }
}

fn main() {
    let u = 7;
    let i1 = -1;
    let i2 = 1;
    let min = -2_147_483_648;

    assert_eq!(add(u, i1), 6);
    assert_eq!(add(u, i2), 8);
    assert_eq!(add(3_000_000_000, min), 852_516_352);
}

您还可以验证溢出:

fn add(u: usize, i: i32) -> Option<usize> {
    if i.is_negative() {
        u.checked_sub(i.wrapping_abs() as u32 as usize)
    } else {
        u.checked_add(i as usize)
    }
}

fn main() {
    let u = 7;
    let i1 = -1;
    let i2 = 1;

    assert_eq!(add(u, i1), Some(6));
    assert_eq!(add(u, i2), Some(8));
    assert_eq!(add(0, -1), None);
}