如何在 Rust 中将有符号整数添加到无符号整数,检查无符号溢出?
Posted
技术标签:
【中文标题】如何在 Rust 中将有符号整数添加到无符号整数,检查无符号溢出?【英文标题】:How do I add a signed integer to an unsigned integer in Rust, checking for unsigned overflow? 【发布时间】:2020-12-11 22:55:04 【问题描述】:我想将isize
添加到usize
并包括边界检查,以便结果不会溢出usize
的边界。如何做到这一点?
【问题讨论】:
【参考方案1】:您可以使用isize::is_negative()
、isize::wrapping_abs()
、usize::checked_add()
和usize::checked_sub()
的组合。
const fn add(lhs: usize, rhs: isize) -> Option<usize>
if rhs.is_negative()
lhs.checked_sub(rhs.wrapping_abs() as usize)
else
lhs.checked_add(rhs as usize)
为什么是 isize::is_negative()
和 rhs < 0
?在这种情况下,它不会改变任何东西,因为对文字的逻辑操作算作constant expressions。
然而,虽然它允许用于字面量,但一般情况下是不允许的,因为特征方法不能是 const
。因此,如果您有包装类型,例如Foo(isize)
则不允许在 const 上下文中说 foo < Foo(0)
。不过,可以说foo.is_negative()
因为Foo
仍然可以实现const fn is_negative()
。
是的,你仍然可以说 foo.0 < 0
,但这不是我想要说明的重点。
【讨论】:
jc,有理由更喜欢is_negative()
而不是< 0
吗?
如果rhs
是isize::MIN
,这不会溢出吗?
使用x < 0
也很好,是的,它会溢出,我已经更新了使用wrapping_abs()
的答案。
@kmdreko 我为is_negative()
vs < 0
添加了一些背景信息
@goose121 编号 isize::MIN 是 0b1000..000 而-(isize::MIN+1)
是 0b0111..1111 所以isize::MIN as usize == (isize::MIN+1) as usize + 1
。【参考方案2】:
一种方法是使用如下函数:
fn signed_unsigned_add(x: usize, y: isize) -> usize
let (n, overflow) = x.overflowing_add(y as usize);
if (y >= 0) ^ overflow
n
else
panic!(
"signed + unsigned addition overflow: + ",
x,
y,
)
这利用了这样一个事实,即当从无符号数的角度来看时,这种加法应该只在无符号数为负时“溢出”(即表现出二进制补码行为),并且如果它不这样做所以当数字为负数时,这表示下溢。
【讨论】:
以上是关于如何在 Rust 中将有符号整数添加到无符号整数,检查无符号溢出?的主要内容,如果未能解决你的问题,请参考以下文章