如何将i64 -9223372036854775808,9223372036854775807表示为u64域0,18446744073709551615。例如,i64中的0在u64中是9223372036854775808。
这就是我所做的。
let x: i64 = -10;
let x_transform = ((x as u64) ^ (1 << 63)) & (1 << 63) | (x as u64 & (u64::MAX >> 1));
let x_original = ((x_transform as i64) ^ (1 << 63)) & (1 << 63) | (x_transform & (u64::MAX >> 1)) as i64;
println!("x_transform {}", x_transform);
println!("x_original {} {}", x_original, x_original == x);屈服
x_transform 9223372036854775798 x_original -10真
是否有一个内置的方式来做到这一点,因为它看起来过于冗长,而且容易出错?
发布于 2022-11-18 14:59:33
从性能角度看,如何编写它并不重要,对神机器人的快速检查显示了编译到同一机器代码的包装版本和比特版本。但我认为带有包装的变体可以更好地理解和传达意图。
pub fn wrap_to_u64(x: i64) -> u64 {
(x as u64).wrapping_add(u64::MAX/2 + 1)
}
pub fn wrap_to_i64(x: u64) -> i64 {
x.wrapping_sub(u64::MAX/2 + 1) as i64
}
pub fn to_u64(x: i64) -> u64 {
((x as u64) ^ (1 << 63)) & (1 << 63) | (x as u64 & (u64::MAX >> 1))
}
pub fn to_i64(x: u64) -> i64 {
((x as i64) ^ (1 << 63)) & (1 << 63) | (x & (u64::MAX >> 1)) as i64
}example::wrap_to_u64:
movabs rax, -9223372036854775808
xor rax, rdi
ret
example::wrap_to_i64:
movabs rax, -9223372036854775808
xor rax, rdi
ret
example::to_u64:
movabs rax, -9223372036854775808
xor rax, rdi
ret
example::to_i64:
movabs rax, -9223372036854775808
xor rax, rdi
ret要吸取的教训是,除非您有非常具体的优化,否则编译器的性能可能会优于您。
发布于 2022-11-18 14:42:58
最简单的解决方案是只翻译两者的补码表示,而不是使用偏移-二进制:
let x_transform = u64::from_ne_bytes(x.to_ne_bytes());
let x_original = i64::from_ne_bytes(x_transform.to_ne_bytes());但是,根据对wiki的说明:
偏移二进制可以通过反转最重要的位来转换成两个的补码。
因此,您可以这样做,并使用不太容易出错的二的补充,用于实际翻译:
pub fn convert1(x: i64) -> u64 {
((x as u64) ^ (1 << 63)) & (1 << 63) | (x as u64 & (u64::MAX >> 1))
}
pub fn convert3(x: i64) -> u64 {
// manipulating the bytes in transit requires
// knowing the MSB, use LE as that's the most
// commmon by far
let mut bytes = x.to_le_bytes();
bytes[7] ^= 0x80;
u64::from_le_bytes(bytes)
}
pub fn convert4(x: i64) -> u64 {
u64::from_ne_bytes((x ^ i64::MIN).to_ne_bytes())
} movabs rax, -9223372036854775808
xor rax, rdi
rethttps://stackoverflow.com/questions/74491204
复制相似问题