为什么我的锤子重量功能在C中起作用,而在RUST中不起作用



我已经在Rust中有以下锤子重量代码,并且它返回了0xffff0xffffffff的垃圾,但是C中的相同代码可行,因此我必须误解有关Rust的情况的误解位级操作。它是完全括号的,所以我认为这不是操作员的问题。

在C中:

#include <stdio.h>
int hamming_weight(int val) {
    int v1 = val - ((val >> 1) & 0x55555555);
    int v2 = (v1 & 0x33333333) + ((v1 >> 2) & 0x33333333);
    return (((v2 + (v2 >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
}
int main() {
    printf("%x -> %dn", 7, hamming_weight(7));
    printf("%x -> %dn", 0xff, hamming_weight(0xff));
    printf("%x -> %dn", 0xffff, hamming_weight(0xffff));
    printf("%x -> %dn", 0xffffffff, hamming_weight(0xffffffff));
    return 0;
}

结果:

7 -> 3
ff -> 8
ffff -> 16
ffffffff -> 32

在Rust(我必须使用U64来防止0xffff上的溢出恐慌(:

fn hamming_weight(val: u64) -> u64 {
    let v1 = val - ((val >> 1) & 0x55555555);
    let v2 = (v1 & 0x33333333) + ((v1 >> 2) & 0x33333333);
    (((v2 + (v2 >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24
}
fn main() {
    println!("{:x} {}", 7, hamming_weight(7));
    println!("{:x} {}", 0xff, hamming_weight(0xff));
    println!("{:x} {}", 0xffff, hamming_weight(0xffff));
    println!("{:x} {}", 0xffffffffu32, hamming_weight(0xffffffffu64));
}

结果:

7 3
ff 8
ffff 2064
ffffffff 135272480

我正在使用Rust 1.16。我知道Rust有count_ones()-编译器在编写此代码时告诉我,这真是太神奇了,但是我选择不使用它。

我必须使用u64来防止0xffff

上的溢出恐慌

那是您的问题。原始C代码依赖于溢出的操作。增加类型的大小无法修复它,但是允许溢出包裹确实:

fn hamming_weight(val: u32) -> u32 {
    let v1 = val - ((val >> 1) & 0x55555555);
    let v2 = (v1 & 0x33333333) + ((v1 >> 2) & 0x33333333);
    (((v2 + (v2 >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24
}

最新更新