下面的结论都是基于用补码表示负数的计算机平台
1
void main(unsigned int x)
2
{
3
//判断无符号整数x是否是2的幂
4
if(x&(x-1))//若一个数是2的幂,则除最高位为1外,其余位均为0(二进制表示,下同)
5
printf("False\n");
6
else
7
printf("True\n");
8
9
//判断一个无符号整数是否为2^n-1的形式(原理同上)
10
if(x&(x+1))//若为2^n-1,则低位全为1
11
printf("False\n");
12
else
13
printf("True\n");
14
15
//整数能被最大的2的幂(?)整除 : 析出最右侧为1的位
16
//e.g.: 100->4
17
printf("%d\n",x&(-x));//将其余位置0
18
19
//析出最右侧为0的位(原理同上)
20
//e.g.:111b->1000b, 10->1
21
printf("%d\n",~x&(x+1));//将该位置1,其余位置0
22
23
//识别后缀0的掩码(将右侧连续的0位置1,其余各位置0)
24
//e.g.:1100b->0011b
25
printf("%d\n", ~x&(x-1)); //或
26
printf("%d\n", ~(x|-x)); //或
27
printf("%d\n", (x&-x)-1);
28
29
//识别最右侧的1未和后缀0的掩码(将最右侧的1位保留,并将其后面所有的0位置1)
30
//e.g.:1100b->0111b
31
printf("%d\n", x^(x-1));
32
33
//向右传播最右侧的1位
34
//e.g.:1100b->1111b
35
printf("%d\n", x|(x-1));
36
37
//将最右侧连续的1位置0
38
//e.g.:10110b->10000
39
printf("%d\n", ((x|(x-1))+1)&x);
40
}
void main(unsigned int x)2
{ 3
//判断无符号整数x是否是2的幂 4
if(x&(x-1))//若一个数是2的幂,则除最高位为1外,其余位均为0(二进制表示,下同)5
printf("False\n");6
else7
printf("True\n");8
9
//判断一个无符号整数是否为2^n-1的形式(原理同上) 10
if(x&(x+1))//若为2^n-1,则低位全为1 11
printf("False\n");12
else13
printf("True\n"); 14
15
//整数能被最大的2的幂(?)整除 : 析出最右侧为1的位16
//e.g.: 100->417
printf("%d\n",x&(-x));//将其余位置0 18
19
//析出最右侧为0的位(原理同上) 20
//e.g.:111b->1000b, 10->121
printf("%d\n",~x&(x+1));//将该位置1,其余位置022
23
//识别后缀0的掩码(将右侧连续的0位置1,其余各位置0)24
//e.g.:1100b->0011b25
printf("%d\n", ~x&(x-1)); //或 26
printf("%d\n", ~(x|-x)); //或 27
printf("%d\n", (x&-x)-1);28
29
//识别最右侧的1未和后缀0的掩码(将最右侧的1位保留,并将其后面所有的0位置1) 30
//e.g.:1100b->0111b31
printf("%d\n", x^(x-1)); 32
33
//向右传播最右侧的1位 34
//e.g.:1100b->1111b35
printf("%d\n", x|(x-1));36
37
//将最右侧连续的1位置038
//e.g.:10110b->1000039
printf("%d\n", ((x|(x-1))+1)&x); 40
}计算x中有多少个为1的位:
1
int Count1(int x)
2
{
3
int n = 0;
4
while(x)
5
{
6
n++;
7
x&=x-1;
8
}
9
return n;
10
}
int Count1(int x)2
{3
int n = 0;4
while(x)5
{6
n++;7
x&=x-1;8
}9
return n;10
}获取下一个具有同样数量的1位的更大的数;应用:在用位串表示集合的子集时
1
unsigned snoob(unsigned x)
2
{
3
unsigned smallest, ripple, ones;//e.g.: x=XXX0 1111 0000
4
smallest = x & -x; // 0000 0001 0000
5
ripple = x + smallest; // XXX1 0000 0000
6
ones = x ^ ripple; // 0001 1111 0000
7
ones = (ones >> 2) / smallest; // 0000 0000 0111
8
return ripple | ones; // XXX1 0000 0111
9
}
unsigned snoob(unsigned x)2
{3
unsigned smallest, ripple, ones;//e.g.: x=XXX0 1111 00004
smallest = x & -x; // 0000 0001 00005
ripple = x + smallest; // XXX1 0000 00006
ones = x ^ ripple; // 0001 1111 00007
ones = (ones >> 2) / smallest; // 0000 0000 01118
return ripple | ones; // XXX1 0000 01119
}


浙公网安备 33010602011771号