【问题标题】:How to find the first bit that is different in C?如何找到C中不同的第一位?
【发布时间】:2014-01-22 19:53:35
【问题描述】:

我想与 C 中的整数进行比较,问题是找到不同的最低有效位。 C 中最快的方法是什么?

例子:

               Bit
               3210
               ----
a = 13 (binary 1101)
b = 9  (binary 1001)
                ^

这里的结果应该是2,因为第2位是第一个不同的位。

【问题讨论】:

  • 做一个 XOR 并找到第一个设置位。
  • 为了找到第一位,无论是从左边还是从右边,寻找一个编译器内在函数;这通常由硬件本地提供,并由编译器方便地公开。

标签: c bit-manipulation


【解决方案1】:

ffs() from <strings.h> 返回第一个位集合的位置, 其中位从1 开始编号为最低有效位 (而ffs(0) 返回零):

unsigned a = 0x0D;
unsigned b = 0x09;

unsigned x = a ^ b;
int pos = ffs(x) - 1;
if (pos == -1) {
   // a and b are equal
} else {
   // pos is the position of the first difference 
}

【讨论】:

  • 感谢您的回答,现在使用 XOR,但是 GCC 中的 __builtin_ffs 而不是 string.h 中的 ffs!
  • 为什么VS找不到strings.h?
  • @herohuyongtao:strings.h(或 string.h)是 C 的 POSIX 扩展,它可能不适用于所有符合标准的 C 编译器。
  • @herohuyongtao:我没有测试过,但是对于 Visual Studio,_BitScanForward 似乎做了类似的工作。
【解决方案2】:

Bit Twiddling Hacks 提供了一个极好的集合,呃,有点小技巧,附有性能/优化讨论。对于您的问题(来自该站点),您可以使用乘法查找策略:

unsigned int c = a ^ b;  
int r;           // result goes here
static const int MultiplyDeBruijnBitPosition[32] = 
{
  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = MultiplyDeBruijnBitPosition[((uint32_t)((c & -c) * 0x077CB531U)) >> 27];

参考资料:

【讨论】:

  • c 是各个位(如 1、2、4、8、...)的 值,而不是其 位置 (比如 0、1、2、3,...),对吧? ideone.com/CzzYFj
  • 不要为此使用有符号整数。不保证使用二进制补码算法。 使用无符号整数.
  • @self。编辑了使用乘法查找策略的答案。
  • @EOF 编辑了使用乘法查找策略的答案。
  • @herohuyongtao Bit Twiddling Hacks 链接本身绝对值得一票:)
【解决方案3】:
#include <stdint.h>

int bit_count(uint32_t bits) {
    bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
    bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
    bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
    bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
    return (bits & 0x0000ffff) + (bits >>16 & 0x0000ffff);
}

int func(unsigned a, unsigned b){
    unsigned x = a ^ b;
    return x ? bit_count((x&(-x))-1) : -1;
}

【讨论】:

  • @herohuyongtao 只是一个分包功能。比使用对数函数分包要好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
相关资源
最近更新 更多