我想要切换我的数字的最高位。这里有一个例子:
x = 100101 then answer should be 00101
我有一台64位计算机,因此我不希望答案是100000..<51 0's>..100101
。 我想到的一种方法是计算我的数字中的位数,然后切换最高位,但是不确定如何计算。
我想要切换我的数字的最高位。这里有一个例子:
x = 100101 then answer should be 00101
我有一台64位计算机,因此我不希望答案是100000..<51 0's>..100101
。 我想到的一种方法是计算我的数字中的位数,然后切换最高位,但是不确定如何计算。
i ^ (1 << (sizeof i * CHAR_BIT - clz(i) - 1))
CLZ
指令,用于计算前导零位。i == 0
,则会导致未定义行为。clz()
。在GCC中,这是__builtin_clz
;在Visual Studio C++中,这是_BitScanForward
。(sizeof(i)*8 - clz(i))
。 - Eldar Abusalimovclz()
是什么?需要哪些头文件? - Kerrek SB__builtin_clz
别名。有关“clz”的通用实现,请参见[我的答案](https://dev59.com/1GjWa4cB1Zd3GeqPtbch#12534059)。 - Eldar Abusalimov__builtin_clz
,在OpenCL中是clz
,在Visual C++中是_BitScanForward
等等。 - jleahy@jleahy已经发布了一个在使用GCC时的好选择,我只会在这里留下一个通用的clz
实现,它不使用任何编译器内置函数。然而,对于已经具有本地位数计数指令的CPU(例如x86),它不是最优选择。
#define __bit_msb_mask(n) (~(~0x0ul >> (n))) /* n leftmost bits. */
/* Count leading zeroes. */
int clz(unsigned long x) {
int nr = 0;
int sh;
assert(x);
/* Hope that compiler optimizes out the sizeof check. */
if (sizeof(x) == 8) {
/* Suppress "shift count >= width of type" error in case
* when sizeof(x) is NOT 8, i.e. when it is a dead code anyway. */
sh = !(x & __bit_msb_mask(sizeof(x)*8/2)) << 5;
nr += sh; x <<= sh;
}
sh = !(x & __bit_msb_mask(1 << 4)) << 4; nr += sh; x <<= sh;
sh = !(x & __bit_msb_mask(1 << 3)) << 3; nr += sh; x <<= sh;
sh = !(x & __bit_msb_mask(1 << 2)) << 2; nr += sh; x <<= sh;
sh = !(x & __bit_msb_mask(1 << 1)) << 1; nr += sh; x <<= sh;
sh = !(x & __bit_msb_mask(1 << 0)) << 0; nr += sh;
return nr;
}
x ^= 1ul << (sizeof(x)*8 - clz(x))
这里提供一种使用查找表的方法,假设 CHAR_BIT == 8
:
uint32_t toggle_msb(uint32_t n)
{
static unsigned char const lookup[] =
{ 1, 0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7 };
for (unsigned int i = 0; i != sizeof n; ++i)
{
// omit the last bit for big-endian machines: ---VVVVVVVVVVVVVVVVVV
unsigned char * p
= reinterpret_cast<unsigned char *>(&n) + sizeof n - i - 1;
if (*p / 16 != 0) { *p = *p % 16 + (lookup[*p / 16] * 16); return n; }
if (*p % 16 != 0) { *p = 16 * (*p / 16) + lookup[*p % 16]; return n; }
}
return 1;
}
并且只需将所有内容放在一起,以GCC的一些示例代码:
#include <stdio.h>
#define clz(x) __builtin_clz(x)
int main()
{
int i = 411; /* 110011011 */
if( i != 0 )
i ^= (1 << (sizeof(i)*8 - clz(i)-1));
/* i is now 10011011 */
printf("i = %d\n", i);
return(0);
}
CHAR_BIT
而不是8
,但我认为这并不严重到足以引起反对票。 - Jerry Coffin
x
的类型中有多少位?是16位、32位、64位还是其他的? - Analog File