如何在Rust中将有符号整数添加到无符号整数?
我是否必须在有符号整数的符号上进行分支,如下面的示例所示?(在实际程序中,如何在Rust中将有符号整数添加到无符号整数?,rust,Rust,我是否必须在有符号整数的符号上进行分支,如下面的示例所示?(在实际程序中,y的计算目的是将指向64K数组的索引更改,而wrapparound是所需的行为) fn main(){ 设mut x:u16=100; 设y:i8=-1; //x+=y; 如果y
y
的计算目的是将指向64K数组的索引更改,而wrapparound是所需的行为)
fn main(){
设mut x:u16=100;
设y:i8=-1;
//x+=y;
如果y<0{
x-=i8::abs(y)为u16;
}否则{
x+=i8::abs(y)为u16;
}
println!(“{}”,x);
}
- 有符号整数是两个补数
- 数字强制符号将
i8扩展为u16
y强制转换为u16
,如果y
为负数,它将变成一个two-s补码值
简言之:照@Veedrac说的做
fn main() {
let mut x: u16 = 100;
let y: i8 = -1;
x = x.wrapping_add(y as u16);
println!("{}", x);
}
在实际程序中,计算y
以将指向64K数组的索引更改,而wrapparound是所需的行为)
对于如何操作,目前还没有达成共识,但我的建议是:向用户提供两个功能:
fn add(&mut self, index: u16) -> u16 { // return previous index why not
// ..
}
fn sub(&mut self, index: u16) -> u16 {
// ..
}
您还可以添加一个不应轻易使用的辅助函数:
fn offset(&mut self, offset: i16) -> u16 {
// ..
}
其目的是,用户应该知道,无论何时使用sub或add,用户都应该只管理未签名类型。这个问题是以意见为导向的,所以如果人们不同意,我理解
完整示例:
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);
}
@E_Net4;可能与之重复。欢迎链接的问题更多地是关于浮点数与整数,而不是混合符号。直觉以及行动过程都是一样的。混合有符号整数之间的算术很复杂,如果编译器只是选择了一个意外的转换规则集(C和C++就是这种情况),可能会产生奇怪的结果。如果转换是无损的(例如,
i16::from(y)
),则只需使用from
关联函数,否则使用as
操作符。x=x.u添加(y为u16)
?或者更好的是,x.wrapping\u add(i16::from(y))
,以符合Clippy lint。我不建议这样做,而是使用下一个更高的有符号值(在本例中是i32
)并添加它们。谢谢,我忘记了,生锈会在无符号溢出时产生恐慌,而不仅仅是在有符号溢出时。@hellow愿意详细说明吗?首先,这看起来更复杂,更容易出错,其次,在某些情况下(u128
),您就是做不到。
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);
}