Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 确定位是否在整数数据类型中设置的最快方法_C_Algorithm_Mathematical Optimization - Fatal编程技术网

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