将值添加到存储为字节数组的整数
Adding a value to an integer stored as a byte array
将值添加(而不是追加)到字节数组的最佳方法是什么?一个整数?
例如:
let arr = [0xFF, 0x01, 0xC3, 0x43];
假设 arr
可以是任意长度。例如,如果我将 350 添加到此,则新数组应为:[0xFF, 0x01, 0xC4, 0xA1]
。我想出的解决方案只有在我们递增 1 时才有效,因此我需要在循环中调用该方法 amount
次,这对于大型 amount
来说效率很低(此示例使用 Vec
而不是数组):
fn increment_byte_vec(vec: Vec<u8>) -> Vec<u8> {
let mut done = false;
vec.iter().rev().map(|&v| {
if done {
v
} else if v == 0xFF {
0
} else {
done = true;
v + 1
}
}).rev().collect::<Vec<_>>()
}
我将如何调整以上内容以便该函数可以采用 amount
参数?
您基本上是以 256 为基数实现求和。解决此问题的一种方法是转换为十进制,加上 350,然后将结果重新转换为以 256 为基数。
即[0xFF, 0x01, 0xC3, 0x43]
是:
255 (FF) * 256^3 +
1 * 256^2 +
195 (C3) * 256^1 +
67 (43) * 256^0 = 4,278,305,603 (base10)
4,278,305,603 + 350 = 4_278_305_953
现在您需要将其重新转换为基数 256。最后一位在 Rust 中可能如下所示:
// warning, does not handle overflows
fn base10_to_256(n: u64) -> [u8; 4] {
let mut converted_number = [0u8; 4];
let mut number_to_convert = n;
let base = 256u64;
for index in 0.. {
converted_number[3-index] = (number_to_convert % base) as u8;
number_to_convert = number_to_convert / base;
if number_to_convert == 0 { break; }
}
converted_number
}
这里不多说了;只需添加并携带矢量,从后到前。
号码可能溢出。我选择了return进位;您可能更愿意扩展向量。我的解决方案使用变异,因为它比分配新向量更有效,而且由于我没有改变长度,我认为在可变切片上通用更好。
/// Increments the bytes, assuming the most significant
/// bit is first, and returns the carry.
fn increment_bytes(b256: &mut [u8], mut amount: u64) -> u64 {
let mut i = b256.len() - 1;
while amount > 0 {
amount += b256[i] as u64;
b256[i] = amount as u8;
amount /= 256;
if i == 0 { break; }
i -= 1;
}
amount
}
fn main() {
let mut input = vec![0xFF, 0x01, 0xC3, 0x43];
println!("{}", increment_bytes(&mut input, 350));
println!("{:?}", input);
}
将值添加(而不是追加)到字节数组的最佳方法是什么?一个整数?
例如:
let arr = [0xFF, 0x01, 0xC3, 0x43];
假设 arr
可以是任意长度。例如,如果我将 350 添加到此,则新数组应为:[0xFF, 0x01, 0xC4, 0xA1]
。我想出的解决方案只有在我们递增 1 时才有效,因此我需要在循环中调用该方法 amount
次,这对于大型 amount
来说效率很低(此示例使用 Vec
而不是数组):
fn increment_byte_vec(vec: Vec<u8>) -> Vec<u8> {
let mut done = false;
vec.iter().rev().map(|&v| {
if done {
v
} else if v == 0xFF {
0
} else {
done = true;
v + 1
}
}).rev().collect::<Vec<_>>()
}
我将如何调整以上内容以便该函数可以采用 amount
参数?
您基本上是以 256 为基数实现求和。解决此问题的一种方法是转换为十进制,加上 350,然后将结果重新转换为以 256 为基数。
即[0xFF, 0x01, 0xC3, 0x43]
是:
255 (FF) * 256^3 +
1 * 256^2 +
195 (C3) * 256^1 +
67 (43) * 256^0 = 4,278,305,603 (base10)
4,278,305,603 + 350 = 4_278_305_953
现在您需要将其重新转换为基数 256。最后一位在 Rust 中可能如下所示:
// warning, does not handle overflows
fn base10_to_256(n: u64) -> [u8; 4] {
let mut converted_number = [0u8; 4];
let mut number_to_convert = n;
let base = 256u64;
for index in 0.. {
converted_number[3-index] = (number_to_convert % base) as u8;
number_to_convert = number_to_convert / base;
if number_to_convert == 0 { break; }
}
converted_number
}
这里不多说了;只需添加并携带矢量,从后到前。
号码可能溢出。我选择了return进位;您可能更愿意扩展向量。我的解决方案使用变异,因为它比分配新向量更有效,而且由于我没有改变长度,我认为在可变切片上通用更好。
/// Increments the bytes, assuming the most significant
/// bit is first, and returns the carry.
fn increment_bytes(b256: &mut [u8], mut amount: u64) -> u64 {
let mut i = b256.len() - 1;
while amount > 0 {
amount += b256[i] as u64;
b256[i] = amount as u8;
amount /= 256;
if i == 0 { break; }
i -= 1;
}
amount
}
fn main() {
let mut input = vec![0xFF, 0x01, 0xC3, 0x43];
println!("{}", increment_bytes(&mut input, 350));
println!("{:?}", input);
}