C 确定位是否在整数数据类型中设置的最快方法
我有一个方法,可以根据特定的算法计算散列值C 确定位是否在整数数据类型中设置的最快方法,c,algorithm,mathematical-optimization,C,Algorithm,Mathematical Optimization,我有一个方法,可以根据特定的算法计算散列值 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; } 我想知道在整数数据类型
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。还有比这更好的吗?您首先要考虑的是有一个正确的便携版本。现在的编译器将非常巧妙地优化这些位操作 您应该始终注意,您正在使用的掩码对应于您正在测试的数据类型。使用int或unsigned可能不够,因为您对uint64\u t的位感兴趣,并且移位超过位是未定义的行为 在您的情况下,您可能会使用
(UINT64_C(1) << (n))
(1 ? 1U : (X))
集合在一个宏中
#define MASK(X, N) ((1 ? 1U : (X)) << (N))
您首先要考虑的是有一个正确的、可移植的版本。现在的编译器将非常巧妙地优化这些位操作 您应该始终注意,您正在使用的掩码对应于您正在测试的数据类型。使用int或unsigned可能不够,因为您对uint64\u t的位感兴趣,并且移位超过位是未定义的行为 在您的情况下,您可能会使用
(UINT64_C(1) << (n))
(1 ? 1U : (X))
集合在一个宏中
#define MASK(X, N) ((1 ? 1U : (X)) << (N))
我认为这是一个速度与记忆类型的问题。更新了史密斯先生的建议: 如果你真的想要速度,我会为每一位定义一个掩码,并进行比较。也许是这样的:
const uint8_t BitMask[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
/* Find out if LSB is set */
if( hash & BitMask[0] ) { ... }
移位的问题是它每移位使用一条指令,而固定掩码在比较之前只有一个内存访问。我认为这是一个速度与内存类型的问题。更新了史密斯先生的建议: 如果你真的想要速度,我会为每一位定义一个掩码,并进行比较。也许是这样的:
const uint8_t BitMask[] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
/* Find out if LSB is set */
if( hash & BitMask[0] ) { ... }
移位的问题是,它每移位使用一条指令,而固定掩码在比较之前只有一个内存访问。要快速查找设置的位,请尝试以下操作:
int oneBit = x & ~(x-1);
在此之后,oneBit将仅具有X集合的最低位。
例如,如果x是1011010100,则一位将是0000 0100,例如,仅为最低位
之后,您可以使用以下选项关闭最低位:
x &= x-1;
如果x是10110100,那么新的x应该是10110000
然后,您可以重复第一个操作以查找设置的下一个最低位
这有一个很大的优点,就是你不需要花时间测试一个位,而只需要找出它的零。它可以让你直接找到那些设置好的位,并跳过零位
下面的示例代码显示了它的作用:
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
要快速查找设置的位,请尝试以下操作:
int oneBit = x & ~(x-1);
在此之后,oneBit将仅具有X集合的最低位。
例如,如果x是1011010100,则一位将是0000 0100,例如,仅为最低位
之后,您可以使用以下选项关闭最低位:
x &= x-1;
如果x是10110100,那么新的x应该是10110000
然后,您可以重复第一个操作以查找设置的下一个最低位
这有一个很大的优点,就是你不需要花时间测试一个位,而只需要找出它的零。它可以让你直接找到那些设置好的位,并跳过零位
下面的示例代码显示了它的作用:
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
我只需要使用一个数组,其中索引是要测试的位,值是对应的掩码。但这是相同的想法。这将更加清楚,因为数组名称将显示意图。我会更新答案以反映这一点。是的,我真正想要的是更快的计算速度。真正让我担心的是,我会对64位值使用移位运算符的次数。然后我会说,我刚刚创建了数组,然后牺牲了64B的内存来保存它:您应该知道,在常量表达式中使用移位运算符不会有问题。在编译时进行翻译。也就是说,上述减赤可以写成{ 1@Kenneth:该数组将需要64*8字节,因为64个掩码中的每个掩码的大小为64位=8字节。因此我们需要512字节。;-我只需要使用一个数组,其中索引是要测试的位,值是对应的掩码。但这是相同的想法。这将更清楚,因为数组名称将显示意图。我将更新答案为了反映这一点。是的,我真正想要的是更快的计算速度。真正让我担心的是,我将对64位值使用移位运算符的次数。然后我会说,刚刚创建了数组,然后牺牲64B的内存来保存它:你应该知道,在常量表达式中使用移位运算符不会有问题。这是在编译时翻译的。也就是说,上面的删减可以写成{1@Kenneth:阵列将需要64*8字节,因为64个掩码中的每个掩码的大小为64位=8字节。因此,我们需要512字节。;-我的主要目标是
为了尽量减少使用移位运算符的次数。我的主要目标是尽量减少使用移位运算符的次数。关于三元运算符,我缺少什么吗?我会吗?Foo:Bar不总是导致Foo?有符号和无符号类型的左移位总是逻辑移位,那么为什么还要麻烦类型呢?@Kenneth,当然,但是返回值的类型是由两个表达式的类型决定的。然后,移动有符号类型可能导致溢出,从而导致未定义的行为。我们必须处理类型,因为1U关于三元运算符,我有什么遗漏吗?我会吗?Foo:Bar不总是导致Foo?有符号和无符号类型的左移位总是逻辑移位,那么为什么还要麻烦类型呢?@Kenneth,当然,但是返回值的类型是由两个表达式的类型决定的。然后,移动有符号类型可能导致溢出,从而导致未定义的行为。我们不得不为类型而烦恼,因为1U