如何使用 BitSlices 进行算术运算?
How to do arithmetic operations with BitSlices?
使用 bitvec crate,假设我有两个 BitSlice
:
let num1: &BitSlice = 10.view_bits::<Lsb0>();
let num2: &BitSlice = 9.view_bits::<Lsb0>();
有没有办法用这些 运行 位算术运算,例如 num1 - num2
?
我在 no-std
环境中工作受到限制,而且位片可能很大,所以我无法将它们转换为数字,进行运算并转换回位表示。
bitvec
曾经包含 addition and subtraction, but they were removed in version 0.18. Also, there was never subtraction on BitSlice
, only addition. Although it was mentioned they should be moved into a separate crate,我找不到这样的 crate。所以,你需要自己去实现。
最简单(虽然绝对不是最有效)的方法是步行 bit-by-bit 并执行操作。
例如加法(改编自0.17.4版本的代码):
/// May overflow.
pub fn add_assign(lhs: &mut BitSlice, rhs: &BitSlice) {
fn add_with_carry(a: bool, b: bool, carry: bool) -> (bool, bool) {
let result = u8::from(a) + u8::from(b) + u8::from(carry);
((result & 0b01) != 0, (result & 0b10) != 0)
}
let mut carry = false;
let extended_rhs = rhs.iter().by_vals().rev().chain(core::iter::repeat(false));
for (mut lhs_bit, rhs_bit) in lhs.iter_mut().rev().zip(extended_rhs) {
(*lhs_bit, carry) = add_with_carry(*lhs_bit, rhs_bit, carry);
}
}
请注意,除非可以扩展切片,否则无法防止溢出,这需要 BitVec
和分配支持。
为了完整起见,我还将添加自己的减法函数:
pub fn subtract(lhs: &mut BitSlice, rhs: &BitSlice) {
let mut borrow = false;
for (mut l, r) in lhs
.iter_mut()
.rev()
.zip(rhs.iter().by_vals().rev().chain(core::iter::repeat(false)))
{
if borrow {
*l = !(*l);
borrow = *l;
}
*l = match (*l, r) {
(true, false) => true,
(false, true) => {
borrow = true;
true
}
(_, _) => false,
};
}
}
我可以为我的用例做出某些假设,例如位顺序和 lhs >= rhs
,因此如果您要复制粘贴此代码,请也考虑这些情况。
使用 bitvec crate,假设我有两个 BitSlice
:
let num1: &BitSlice = 10.view_bits::<Lsb0>();
let num2: &BitSlice = 9.view_bits::<Lsb0>();
有没有办法用这些 运行 位算术运算,例如 num1 - num2
?
我在 no-std
环境中工作受到限制,而且位片可能很大,所以我无法将它们转换为数字,进行运算并转换回位表示。
bitvec
曾经包含 addition and subtraction, but they were removed in version 0.18. Also, there was never subtraction on BitSlice
, only addition. Although it was mentioned they should be moved into a separate crate,我找不到这样的 crate。所以,你需要自己去实现。
最简单(虽然绝对不是最有效)的方法是步行 bit-by-bit 并执行操作。
例如加法(改编自0.17.4版本的代码):
/// May overflow.
pub fn add_assign(lhs: &mut BitSlice, rhs: &BitSlice) {
fn add_with_carry(a: bool, b: bool, carry: bool) -> (bool, bool) {
let result = u8::from(a) + u8::from(b) + u8::from(carry);
((result & 0b01) != 0, (result & 0b10) != 0)
}
let mut carry = false;
let extended_rhs = rhs.iter().by_vals().rev().chain(core::iter::repeat(false));
for (mut lhs_bit, rhs_bit) in lhs.iter_mut().rev().zip(extended_rhs) {
(*lhs_bit, carry) = add_with_carry(*lhs_bit, rhs_bit, carry);
}
}
请注意,除非可以扩展切片,否则无法防止溢出,这需要 BitVec
和分配支持。
为了完整起见,我还将添加自己的减法函数:
pub fn subtract(lhs: &mut BitSlice, rhs: &BitSlice) {
let mut borrow = false;
for (mut l, r) in lhs
.iter_mut()
.rev()
.zip(rhs.iter().by_vals().rev().chain(core::iter::repeat(false)))
{
if borrow {
*l = !(*l);
borrow = *l;
}
*l = match (*l, r) {
(true, false) => true,
(false, true) => {
borrow = true;
true
}
(_, _) => false,
};
}
}
我可以为我的用例做出某些假设,例如位顺序和 lhs >= rhs
,因此如果您要复制粘贴此代码,请也考虑这些情况。