[英]How do I add a signed integer to an unsigned integer in Rust?
Do I have to branch on the sign of the signed integer, like in the example below?我是否必须在已签名的 integer 的符号上分支,如下例所示? (In the real program
y
is calculated to change the index pointing into a 64K array, and wraparound is the desired behavior) (在实际程序中,计算
y
以将指向的索引更改为 64K 数组,并且回绕是所需的行为)
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);
}
i8 as u16
i8 as u16
扩展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. 这意味着您可以将
y as u16
转换y as u16
,它将转换为二进制补码值,如果y
为负数,则wrapping_add将正确处理。
In short: do as @Veedrac said. 简而言之:按照@Veedrac所说的做。
fn main() {
let mut x: u16 = 100;
let y: i8 = -1;
x = x.wrapping_add(y as u16);
println!("{}", x);
}
In the real program
y
is calculated to change the index pointing into a 64K array , and wraparound is the desired behavior)在实际程序中,计算
y
来更改指向64K数组的索引,并且回绕是所需的行为)
There is no consensus of how things should be done, but here's my advice: Provide to the user two functions: 对于应该如何做尚无共识,但是我的建议是:向用户提供两个功能:
fn add(&mut self, index: u16) -> u16 { // return previous index why not
// ..
}
fn sub(&mut self, index: u16) -> u16 {
// ..
}
You could also add a helper function that should not be used lightly: 您还可以添加一个不应轻易使用的辅助函数:
fn offset(&mut self, offset: i16) -> u16 {
// ..
}
The purpose is that the user should know whenever use sub or add, the user should manage only unsigned type. 目的是使用户在使用sub或add时应该知道,用户应仅管理无符号类型。 That question is opinion oriented so I understand if people don't agree.
这个问题是意见导向的,所以我理解人们是否同意。
Full example: 完整示例:
use std::mem;
#[derive(Debug, PartialEq, PartialOrd)]
struct MyIndex {
index: u16,
}
impl MyIndex {
fn new(index: u16) -> Self {
Self { index }
}
fn add(&mut self, index: u16) -> u16 {
let index = self.index.wrapping_add(index);
self.replace(index)
}
fn sub(&mut self, index: u16) -> u16 {
let index = self.index.wrapping_sub(index);
self.replace(index)
}
fn offset(&mut self, offset: i16) -> u16 {
if offset > 0 {
self.add(offset as u16)
} else {
self.sub(offset as u16)
}
}
fn replace(&mut self, index: u16) -> u16 {
mem::replace(&mut self.index, index)
}
}
fn main() {
let mut index = MyIndex::new(42);
let mut other_index = MyIndex::new(84);
let (x, first) = if index > other_index {
(index.index - other_index.index, true)
}
else {
(other_index.index - index.index, false)
};
// ...
if first {
index.sub(x);
}
else {
other_index.sub(x);
}
println!("{:?} {:?}", index, other_index);
index.sub(21);
println!("{:?}", index);
index.offset(-1);
println!("{:?}", index);
}
If you're on nightly, we now have the unstable feature mixed_integer_ops .如果您每晚使用,我们现在有不稳定的功能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;有
wrapping_
、 checked_
、 saturating_
和overflowing_
变体,具体取决于您希望溢出时的行为; 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);
)并且这些方法都在有符号和无符号整数上,分别命名为
_unsigned
和_signed
(所以上面也可以表示为x = y.wrapping_add_unsigned(x);
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.