如何按位获取数字而不是求反符号位
How to get the bitwise not of a number but do not negate the sign bits?
我有一个代表掩码的数字,我想得到负掩码(0110,即 6)。我想不按位做,但似乎它也否定了符号位,我得到了一个不需要的值......
size_t msk = 9; // that is 1001, or 000...01001 on more bits
size_t nMsk = ~msk; // this I want to be 6, that is 0110, but bitwise not
// is negating all the bits, so I get 111...10110
有没有一种快速的方法(没有循环)?
编辑更多信息:
我在其中一个答案的一些评论中添加了一些更好的案例:在我的例子中,16 是 100000000,~16 不是111011111111,而是000011111111
如果您希望您的值按照您的要求为 6,那么您需要删除它前面所有不使用的位。
size_t nMsk = (~msk) & 0xF;
用 0xF
屏蔽它,等于二进制中的 1111
将删除除最后 4 位之外的所有位,从而产生您想要的值。
OP在一条评论中表示,他事先不知道位数。解决此问题的一种方法是使用查找表。一个 8 位示例是
uint8_t lookup[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
result ^= lookup [numberofbits];
如果你假设你正在使用的最大位数,你可以得到一个"所有位等于或低于最高设定位"的掩码,而不需要太多的魔术(尽管魔术可能更快)
size_t m = msk;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16;
m |= m >> 32; // if size_t is more than 32 bits
然后只需 XOR 与它:
nMsk = msk ^ m;
这是一个不寻常的操作,我仍然怀疑你真的是别的意思。
符号
位只是颠倒的,因为~不考虑有符号/无符号。例:
uint8_t a = 54; /* 0011 0110 */
uint8_t b = ~a; /* 201 1100 1001 */
int8_t c = 54; /* 0011 0110 */
int8_t d = ~c; /* -55 1100 1001 */
如果只想反转某些位,则可以改用 xor,例如:
uint8_t a = 54; /* 0011 0110 */
uint8_t b = a ^ 15; /* 57 0011 1001 */
这是我的尝试(见输出):
#include <climits>
#include <cmath>
#include <bitset>
#include <iostream>
template <typename T>
T build_mask(T num) {
const int up_to_bit = ceil(log2(num));
for (int i = 0; i < up_to_bit; i++)
num |= 1 << i;
return num;
}
template <typename T>
std::bitset<sizeof(T) * CHAR_BIT> get_bits(T num) {
return std::bitset<sizeof(T) * CHAR_BIT>(num);
}
int main() {
int32_t msk = 9;
int32_t nMsk = ~msk & build_mask(msk);
std::cout << "value: " << msk << std::endl;
std::cout << "bits : " << get_bits(msk) << std::endl;
std::cout << "mask : " << get_bits(build_mask(msk)) << std::endl;
std::cout << "value: " << nMsk << std::endl;
std::cout << "bits : " << get_bits(nMsk) << std::endl;
return 0;
}
如何通过按位异或保留符号位:
size_t nMsk = ~msk ^ (1 << ((sizeof(size_t) * CHAR_BIT) - 1));
它将首先反转掩码,然后切换符号位。
相关文章:
- 将按位if条件转换为普通if条件
- 为什么 std::vector 需要 is_trivial 才能按位移动,而不仅仅是is_trivially_copya
- C++ 中的按位运算符和重载
- 何时使用按位运算而不是算术替代方法?
- 如何使用按位运算将随机uint64_t转换为范围 (0, 1) 的随机双精度
- GCC constexpr 允许添加,但不允许按位添加或带地址
- 为什么在C++(按位运算符)中(~10)等于-11
- C++重载|(按位OR)运算符,返回常数值
- 为什么我们不能使用整数到字符串直接转换,但可以按位到字符串?
- 位集上的按位或给出错误的答案
- 使用按位运算确定值是否包含另一个值
- 对有符号字符的按位运算
- C++14 是否定义了无符号 int 的填充位上的按位运算符的行为
- 如何按位获取数字而不是求反符号位
- 按位运算符和有符号类型
- 按位左移一个带有 16 的无符号字符是什么意思
- 了解 C++14 中有符号类型的按位左移
- 按位移位将无符号字符提升为 int
- 为什么按位否定运算符"~"转换为 int?(从"int"转换为"无符号字符"可能会改变其值)
- 无符号类型的按位移位中的 RHS 操作数的类型