可能重复:
Efficient bitwise operations for counting bits or find the right|left most ones
有没有一种快速的方法可以找到(32位)二进制数中的前1个?
e.g。如果我有数字00000000 00000000 00000000 10000000
我想计算价值" 7" (或" 24",如果从另一侧读取),因为数字中的第一个零存储在右起第7位。
有没有比
更快的方法int pos=0;
int number = 127; //binary from above
while ((number>>pos) > 0) { pos++; }
也许是特定的x86汇编指令?
答案 0 :(得分:5)
使用gcc,您可以使用__builtin_ctz
和__builtin_clz
。 ctz
给出尾随0位的数量,clz
给出前导0位的数量。
答案 1 :(得分:3)
是的,有一种更快的方法 - 不使用宏。
使用您的方法,您最多可以拥有32 * 2个操作。
这是一个对数算法。
首先,您将数字拆分为2个短路,并检查0是否为短路。如果为0,则去检查高位部分,保持偏移= 16。如果不是0,则去检查低部分,偏移= 0.您将保留短和偏移
接下来,将剩余部分分成2个字符,然后继续进行。您将保留char和偏移量。
接下来,将char分成2位4位,并检查相同的内容。
您将进行最大日志32 * 2操作。
答案 2 :(得分:3)
您正在寻找x86的位扫描指令
__inline__ size_t bsf(size_t input) {
size_t pos;
__asm__ ("bsf %1, %0" : "=r" (pos) : "rm" (input));
return pos;
}
如果使用内联asm,请确保pos
和input
都是相同的存储类(2个,4个或8个字节的整数类型)。这个内联函数应该没问题。
大多数编译器都有使用此指令的内在函数,但MSVC是我所知道的唯一具有直接指令的编译器。
对于最高位的位集,请改用bsr
指令,使用相同的语法。
注意:如果输入为0(未设置位),则结果未定义!
如果输入为0,这是一个将预定义常量放入pos
的版本:
#define BIT_SCAN_IFZERO 0
__inline__ size_t bsf(size_t input) {
size_t pos, ifzero = BIT_SCAN_IFZERO;
__asm__ ( "bsf %1, %0\n\t"
"cmovz %2, %0"
: "=r" (pos)
: "rm" (input)
, "rm" (ifzero));
return pos;
}
将BIT_SCAN_IFZERO
定义为您喜欢的任何内容。如果您想要一个负数,那么请将size_t
更改为ssize_t
(签名大小类型)
答案 3 :(得分:1)
MSVC内在函数为_BitScanForward
和_BitScanReverse
。
您可以查找他们的参数here,它们不是过于直观(您想要的值不是返回值)。
答案 4 :(得分:-2)
这几乎是最快的方法。如果你正在处理多个单词的潜力,你可以测试第一个单词然后第二个单词,然后找到最低的不是0个单词。你仍然需要改变它。