将存储在u32数组中的大数转换为字节并返回

tin*_*ker 2 rust

我在Rust中做了一些计算数学,并且我有一些大数字,我存储在24个值的数组中.我有将它们转换为字节并返回的函数,但它对u32值不起作用,而它可以正常工作u64.代码示例可以在下面找到:

fn main() {
    let mut bytes = [0u8; 96]; // since u32 is 4 bytes in my system, 4*24 = 96
    let mut j;
    let mut k: u32;

    let mut num: [u32; 24] = [1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981, 2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433, 4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229, 4185060747, 1883946895, 4146];
    println!("original_num: {:?}", num);

    for i in 0..96 {
        j = i / 4;
        k = (i % 4) as u32;
        bytes[i as usize] = (num[j as usize] >> (4 * k)) as u8;
    }

    println!("num_to_ytes: {:?}", &bytes[..]);
    num = [0u32; 24];

    for i in 0..96 {
        j = i / 4;
        k = (i % 4) as u32;
        num[j as usize] |= (bytes[i as usize] as u32) << (4 * k);
    }

    println!("recovered_num: {:?}", num);
}
Run Code Online (Sandbox Code Playgroud)

铁锈操场

上面的代码没有从字节数组中检索正确的数字.但是,如果我改变这一切u32u64,所有4s到8s,且尺寸减少num24个值12,它工作一切正常.我假设我的u32版本有一些逻辑问题.正确工作的u64版本可以在这个Rust游乐场找到.

She*_*ter 7

学习如何创建MCVE是编程时的一项重要技能.例如,为什么你有一个阵列?为什么要重用变量?

您的原始第一个数字是0x4F9B1BD6,输出的第一个数字是0x000B1BD6.

比较中间字节表明你有垃圾:

let num = 0x4F9B1BD6_u32;
println!("{:08X}", num);

let mut bytes = [0u8; BYTES_PER_U32];
for i in 0..bytes.len() {
    let k = (i % BYTES_PER_U32) as u32;
    bytes[i] = (num >> (4 * k)) as u8;
}

for b in &bytes {
    print!("{:X}", b);
}
println!();
Run Code Online (Sandbox Code Playgroud)
4F9B1BD6
D6BD1BB1
Run Code Online (Sandbox Code Playgroud)

打印出以下值k:

for i in 0..bytes.len() {
    let k = (i % BYTES_PER_U32) as u32;
    println!("{} / {}", k, 4 * k);
    bytes[i] = (num >> (4 * k)) as u8;
}
Run Code Online (Sandbox Code Playgroud)

显示您试图以4位的倍数移位:

0 / 0
1 / 4
2 / 8
3 / 12
Run Code Online (Sandbox Code Playgroud)

我很确定今天的每个通用平台都使用8位作为一个字节,而不是4位.

就是魔术数字不好的原因.如果你已经使用常量来表示值,那么你会更快地注意到这个问题.

因为u32在我的系统中是4个字节

一个u32 更好的是4个字节的每个系统 -这就是为什么它是一个u32.


总的来说,不要重新发明轮子.使用byteorder crate或等价物:

extern crate byteorder;

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

const LENGTH: usize = 24;
const BYTES_PER_U32: usize = 4;

fn main() {
    let num: [u32; LENGTH] = [
        1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981,
        2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433,
        4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229,
        4185060747, 1883946895, 4146,
    ];
    println!("original_num: {:?}", num);

    let mut bytes = [0u8; LENGTH * BYTES_PER_U32];
    {
        let mut bytes = &mut bytes[..];
        for &n in &num {
            bytes.write_u32::<BigEndian>(n).unwrap();
        }
    }

    let mut num = [0u32; LENGTH];
    {
        let mut bytes = &bytes[..];
        for n in &mut num {
            *n = bytes.read_u32::<BigEndian>().unwrap();
        }
    }

    println!("recovered_num: {:?}", num);
}
Run Code Online (Sandbox Code Playgroud)