happyhippy

这个世界的问题在于聪明人充满疑惑,而傻子们坚信不疑。--罗素

下面的结论都是基于用补码表示负数的计算机平台
 1void 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}


计算x中有多少个为1的位:
 1int Count1(int x)
 2{
 3    int n = 0;
 4    while(x)
 5    {
 6            n++;
 7            x&=x-1;
 8    }

 9    return n;
10}


获取下一个具有同样数量的1位的更大的数;应用:在用位串表示集合的子集时
1unsigned 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}
posted on 2007-04-24 13:10  Silent Void  阅读(1216)  评论(3编辑  收藏  举报