我尝试确定最右边的第n位设置
if (value & (1 << 0)) { return 0; }
if (value & (1 << 1)) { return 1; }
if (value & (1 << 2)) { return 2; }
...
if (value & (1 << 63)) { return 63; }
如果比较需要进行64次。有没有更快的方法?
答案 0 :(得分:5)
这有一个小技巧:
value & -value
这使用负数的二进制补码整数表示。
编辑:这并不完全给出问题中给出的确切结果。其余的可以用一个小的查找表来完成。
答案 1 :(得分:5)
如果您使用的是GCC,请使用__builtin_ctz
或__builtin_ffs
功能。 (http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005fffs-2894)
如果您使用的是MSVC,请使用_BitScanForward
功能。请参阅How to use MSVC intrinsics to get the equivalent of this GCC code?。
在POSIX中还有一个ffs
函数。 (http://linux.die.net/man/3/ffs)
答案 2 :(得分:2)
您可以使用循环:
unsigned int value;
unsigned int temp_value;
const unsigned int BITS_IN_INT = sizeof(int) / CHAR_BIT;
unsigned int index = 0;
// Make a copy of the value, to alter.
temp_value = value;
for (index = 0; index < BITS_IN_INT; ++index)
{
if (temp_value & 1)
{
break;
}
temp_value >>= 1;
}
return index;
与if
语句提议相比,它占用的代码空间更少,具有类似的功能。
答案 3 :(得分:1)
如果您的编译器支持它们,KennyTM的建议很好。否则,您可以使用二进制搜索加速它,例如:
int result = 0;
if (!(value & 0xffffffff)) {
result += 32;
value >>= 32;
}
if (!(value & 0xffff)) {
result += 16;
value >>= 16;
}
等等。这将进行6次比较(一般来说,log(N)比较,而线性搜索则为N)。
答案 4 :(得分:1)
b = n & (-n) // finds the bit b -= 1; // this gives 1's to the right b--; // this gets us just the trailing 1's that need counting b = (b & 0x5555555555555555) + ((b>>1) & 0x5555555555555555); // 2 bit sums of 1 bit numbers b = (b & 0x3333333333333333) + ((b>>2) & 0x3333333333333333); // 4 bit sums of 2 bit numbers b = (b & 0x0f0f0f0f0f0f0f0f) + ((b>>4) & 0x0f0f0f0f0f0f0f0f); // 8 bit sums of 4 bit numbers b = (b & 0x00ff00ff00ff00ff) + ((b>>8) & 0x00ff00ff00ff00ff); // 16 bit sums of 8 bit numbers b = (b & 0x0000ffff0000ffff) + ((b>>16) & 0x0000ffff0000ffff); // 32 bit sums of 16 bit numbers b = (b & 0x00000000ffffffff) + ((b>>32) & 0x00000000ffffffff); // sum of 32 bit numbers b &= 63; // otherwise I think an input of 0 would produce 64 for a result.
当然是在C语言中。
答案 5 :(得分:0)
这是利用逻辑AND操作和条件指令执行或指令管道的短路的另一种方法。
unsigned int value;
unsigned int temp_value = value;
bool bit_found = false;
unsigned int index = 0;
bit_found = !bit_found && ((temp_value & (1 << index++)); // bit 0
bit_found = !bit_found && ((temp_value & (1 << index++)); // bit 1
bit_found = !bit_found && ((temp_value & (1 << index++)); // bit 2
bit_found = !bit_found && ((temp_value & (1 << index++)); // bit 3
//...
bit_found = !bit_found && ((temp_value & (1 << index++)); // bit 64
return index - 1; // The -1 may not be necessary depending on the starting bit number.
此方法的优点是没有分支,并且指令管道不受干扰。这在执行条件执行指令的处理器上非常快。
答案 6 :(得分:-1)
适用于Visual C ++ 6
int toErrorCodeBit(__int64 value) {
const int low_double_word = value;
int result = 0;
__asm
{
bsf eax, low_double_word
jz low_double_value_0
mov result, eax
}
return result;
low_double_value_0:
const int upper_double_word = value >> 32;
__asm
{
bsf eax, upper_double_word
mov result, eax
}
result += 32;
return result;
}