我有一个usize
确实击中了非常大的值。我还以isize
的形式对其应用了增量。在不损失任何精度的情况下应用增量的最佳方法是什么?
fn main() {
let mut big_indexer: usize = 4295032832; // 2^32 + 2^16
let delta: isize = -65792; // 2^16 + 2^8
let big_indexer = (big_indexer as isize) + delta // Can't do this b/c overflow
let big_indexer = big_indexer + (delta as usize) // Can't do this b/c lose negative number
// This is ugly
if delta < 0 {
let big_indexer -= delta.abs() as usize;
} else {
let big_indexer += delta.abs() as usize;
}
}
有两种方法:
isize
范围内(例如选择锈std
)usize
并亲自签署(显然是我的首选)。但是实施取决于您;例如,您可以使用bool
来告诉您偏移量是差值还是加法,或者使用枚举:
fn foo(n: usize, offset: usize, sub: bool) -> Option<usize> {
(if sub {
usize::checked_sub
} else {
usize::checked_add
})(n, offset)
}
enum OffSet {
Neg(usize),
Pos(usize),
}
fn bar(n: usize, offset: OffSet) -> Option<usize> {
match offset {
OffSet::Pos(offset) => n.checked_add(offset),
OffSet::Neg(offset) => n.checked_sub(offset),
}
}
fn main() {
let n = 4295032832; // 2^32 + 2^16
let offset = 65792; // 2^16 + 2^8
let sub = true;
assert_eq!(Some(n - offset), foo(n, offset, sub));
assert_eq!(Some(n - offset), bar(n, OffSet::Neg(offset)));
}
这一点都不难看;您只需要使用一些特征来隐藏逻辑,然后就可以使用它。
取决于您的机器,usize is either 32 bit or 64 bit与isize相同,除了第一位是符号位。因此,不知道索引器的上限,安全的方法是将两个值都转换为i128
:
let big_indexer = (big_indexer as i128) + delta as i128