Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add a negative i32 number to an usize variable?

Such as:

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

The output is:

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

anyway?

like image 941
Excosy S.P. Avatar asked Jan 04 '19 08:01

Excosy S.P.


People also ask

What is the size of Usize?

Conservatively assume that usize may be as narrow as 8 bits. Liberally assume that usize is at least 32 bits wide (as it is on all current officially supported platforms).

What is Usize type?

Introduction to Rust usize. It is a primitive type of rust, which is based on pointer like C programming language. If we have a type that does not have a definite size, we call those primitive types as 'usize' in rust or dynamically sized types in rust. It is representing as the pointer sized unsigned type in rust.

What is i32 in Rust?

i32 : The 32-bit signed integer type.

How big is an i32?

i32 : a 32-bit integer type. In many programming languages this is the default size for integers like int or Integer . f32 : a 32-bit floating point type. In many programming langues this type is known as float , whereas f64 is known as double.


1 Answers

Your attempt does not work because in Rust, you can only do operations between strictly similar types. Rust does not do any implicit numeric cast because it would be a shoot in the foot as you can see below: you have a special case and several ways to have an overflow.

One way to go is to cast the absolute value of the i32 to usize and add or remove it according to whether it is negative or positive. However, you must handle the special case of the minimal value that overflows when you take its absolute value:

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);
}

You may also verify the overflows:

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);
}
like image 144
Boiethios Avatar answered Oct 06 '22 14:10

Boiethios