将负符号添加到无符号的更快方法
Faster way of adding negative signed to unsigned
假设我有 a: usize
和一个负数 b:isize
我如何实现以下语义 - 以最快的方式将 a 减去 b 的绝对值?
我已经想到了a - (b.abs() as usize)
,但我想知道是否有更快的方法。也许是位操作的东西?
为什么你认为这很慢?如果将该代码放入函数中并编译,在 x86-64 linux 上,它会生成以下内容:
_ZN6simple20h0f921f89f1d823aeeaaE:
mov rax, rsi
neg rax
cmovl rax, rsi
sub rdi, rax
mov rax, rdi
ret
这是假设它没有被内联......我不得不工作几分钟以阻止优化器为了获得上述内容而做的事情。
这并不是说它绝对不能做得更快,但我不相信它可以做得更快 much。
如果b
保证为负数,那么就可以a + b
.
在 Rust 中,我们必须首先将一个操作数转换为与另一个操作数相同的类型,然后我们必须使用 wrapping_add
而不是简单地使用运算符 +
,因为调试会在溢出时产生恐慌(在 usize
上使用 +
时会发生溢出,因为负数在转换后会变成非常大的正数)。
fn main() {
let a: usize = 5;
let b: isize = -2;
let c: usize = a.wrapping_add(b as usize);
println!("{}", c); // prints 3
}
通过优化,wrapping_add
编译为单个 add
指令。
假设我有 a: usize
和一个负数 b:isize
我如何实现以下语义 - 以最快的方式将 a 减去 b 的绝对值?
我已经想到了a - (b.abs() as usize)
,但我想知道是否有更快的方法。也许是位操作的东西?
为什么你认为这很慢?如果将该代码放入函数中并编译,在 x86-64 linux 上,它会生成以下内容:
_ZN6simple20h0f921f89f1d823aeeaaE:
mov rax, rsi
neg rax
cmovl rax, rsi
sub rdi, rax
mov rax, rdi
ret
这是假设它没有被内联......我不得不工作几分钟以阻止优化器为了获得上述内容而做的事情。
这并不是说它绝对不能做得更快,但我不相信它可以做得更快 much。
如果b
保证为负数,那么就可以a + b
.
在 Rust 中,我们必须首先将一个操作数转换为与另一个操作数相同的类型,然后我们必须使用 wrapping_add
而不是简单地使用运算符 +
,因为调试会在溢出时产生恐慌(在 usize
上使用 +
时会发生溢出,因为负数在转换后会变成非常大的正数)。
fn main() {
let a: usize = 5;
let b: isize = -2;
let c: usize = a.wrapping_add(b as usize);
println!("{}", c); // prints 3
}
通过优化,wrapping_add
编译为单个 add
指令。