我有一个根据某些特定算法计算哈希值的方法。
uint8_t cal_hash(uint64_t _in_data) {
uint8_t hash;
// algorithm
// bit at hash[0] = XOR of some specific bits in _in_data
// repeat above statement for other indexed bits of hash
return hash;
}
我想知道在整数数据类型中访问和设置相应位的最有效方法是什么。 我已经尝试过像
这样的事情了(((x) & (1<<(n)))?1:0)
确定任何索引处的位是1还是0。有什么比这更好的吗?
答案 0 :(得分:3)
您首先要关注的是拥有正确且可移植的版本。如今,编译器将非常巧妙地优化这种位操作。
您应该始终注意您使用的掩码与您正在测试的数据类型相对应。使用int
或unsigned
可能是不够的,因为您对uint64_t
的位感兴趣并且移位超过位是未定义的行为。
在你的情况下,你可能会使用像
这样的东西(UINT64_C(1) << (n))
用于面具。如果您想以更通用的方式执行此操作,则必须通过
之类的方式获得基本类型的1
(1 ? 1U : (X))
一起在宏
中#define MASK(X, N) ((1 ? 1U : (X)) << (N))
然后测试看起来像
#define BIT(X, N) !!((X) & MASK(X, N))
答案 1 :(得分:3)
我认为这是速度与记忆类型的问题。 (更新了MrSmith42s的建议):
如果你真的想要速度,我会为每个比特定义一个掩码进行比较。也许是这样的事情:
const uint8_t BitMask[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
/* Find out if LSB is set */
if( hash & BitMask[0] ) { ... }
移位的问题在于它每个移位使用一条指令,而固定掩码在比较之前只有一个存储器访问。
答案 2 :(得分:2)
要查找快速设置的位,请尝试以下操作:
int oneBit = x & ~(x-1);
在此之后,oneBit
将只有X集的最低位
(例如,如果x
为1011 0100
,则oneBit将为0000 0100
,例如,仅为最低位)
之后,您可以使用以下方法关闭最低位:
x &= x-1;
(例如:如果x
为1011 0100
,则新x
应为1011 0000
)
然后你可以重复第一个操作来找到设置的下一个最低位。
这样做有一个很大的好处,就是你不要花费时间“测试”一点只是为了找出它的零。
它可以直接找到那些设置的位,并跳过零位。
以下示例代码显示了它的实际效果:
int main(void)
{
int x = 180; // 1011 0100
while (x)
{
printf("Low Bit is: %d\n", x & ~(x-1));
x &= (x-1);
}
}
输出:
Low Bit is: 4 // eg. 0000 0100
Low Bit is: 16 // eg. 0001 0000
Low Bit is: 32 // eg. 0010 0000
Low Bit is: 128 // eg. 1000 0000