首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在i64域中表示u64?

如何在i64域中表示u64?
EN

Stack Overflow用户
提问于 2022-11-18 14:30:32
回答 2查看 55关注 0票数 0

如何将i64 -9223372036854775808,9223372036854775807表示为u64域0,18446744073709551615。例如,i64中的0在u64中是9223372036854775808。

这就是我所做的。

代码语言:javascript
复制
    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真

是否有一个内置的方式来做到这一点,因为它看起来过于冗长,而且容易出错?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-18 14:59:33

从性能角度看,如何编写它并不重要,对神机器人的快速检查显示了编译到同一机器代码的包装版本和比特版本。但我认为带有包装的变体可以更好地理解和传达意图。

代码语言:javascript
复制
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
}
代码语言:javascript
复制
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

要吸取的教训是,除非您有非常具体的优化,否则编译器的性能可能会优于您。

票数 2
EN

Stack Overflow用户

发布于 2022-11-18 14:42:58

最简单的解决方案是只翻译两者的补码表示,而不是使用偏移-二进制:

代码语言:javascript
复制
let x_transform = u64::from_ne_bytes(x.to_ne_bytes());
let x_original = i64::from_ne_bytes(x_transform.to_ne_bytes());

但是,根据对wiki的说明:

偏移二进制可以通过反转最重要的位来转换成两个的补码。

因此,您可以这样做,并使用不太容易出错的二的补充,用于实际翻译:

代码语言:javascript
复制
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())
}

64码

代码语言:javascript
复制
        movabs  rax, -9223372036854775808
        xor     rax, rdi
        ret
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74491204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档