如何从usize中减去isize?

问题描述 投票:2回答:2

我有一个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;
    }
}
types rust type-conversion primitive
2个回答
2
投票

有两种方法:

  • 要么将所有值都保持在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)));
}

这一点都不难看;您只需要使用一些特征来隐藏逻辑,然后就可以使用它。


0
投票

取决于您的机器,usize is either 32 bit or 64 bitisize相同,除了第一位是符号位。因此,不知道索引器的上限,安全的方法是将两个值都转换为i128

let big_indexer = (big_indexer as i128) + delta as i128
© www.soinside.com 2019 - 2024. All rights reserved.