我有一个5位的u8
,我们说0b10101
。我想在位置1、2和4中插入全部为3的位,以便获得:ii1i0101
,即11110101
。我想通过三个函数调用来完成此操作,这意味着该函数应将索引作为参数之一,并在该位置插入一个位。
我遇到过this question,但是该页面上的答案对我不起作用。例如,实现时具有最小支持的 panic 的答案,而其他答案则无法给出正确的结果。
fn insert_at(x: u8, index: u8, bit: u8) -> u8 {
let mask = (1 << (8 - index + 1)) - 1;
(x & !mask) | (bit << (8 - index)) | ((x & mask) >> 1)
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::*;
#[rstest(
input, index, expected,
case(0b10101, 1, 0b110101),
)]
fn test_bla(input: u8, index: u8, expected: u8) {
let result = insert_at(input, index, 1);
assert_eq!(result, expected);
}
}
thread 'tests::test_bla::case_1' panicked at 'attempt to shift left with overflow'
最佳答案
我做了一些假设(和修改),以使您的问题的语义更加具体:
index
0(而不是index
1)是指最高有效设置位左侧的位置。 index > 0
中插入的一位将所有更高有效位的位向左移动1。一个有效的实现(playground link):
fn insert_at(x: u8, index: u8, bit: u8) -> Option<u8> {
if bit != 0 && bit != 1 {
return None;
}
// most significant set bit, from right
// 0b00010101
// 87654321
let msb = 8 - x.leading_zeros() as u8;
if index >= msb {
// the new bit is past the LSB
return None;
}
// an index of 0 means insert as the new MSB (if it fits).
// insert is the absolute index of the inserted bit.
let insert = msb - index;
if insert == 8 {
// the new bit is out of u8 range.
// 0b_11111111
// ^ trying to insert here
return None;
}
let mask = (1 << insert) - 1;
Some((x & !mask) << 1 | (bit << insert) | (x & mask))
}
您的实现 panic 的原因是检查了Rust的左移操作:如果将任何一位从整数的左侧移出,则检查将失败。这样做的主要原因是,在这种情况下,不同的平台具有不同的行为。在这些情况下,Rust还提供具有指定行为的算术运算,例如
overflowing_shl()
和wrapping_shl()
。
关于rust - 在8位整数中插入一位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65755600/