几个常用的位操作

本文介绍了一系列位操作技巧,包括如何判断一个数是否为2的幂、如何计算一个数中1的位数、如何找到下一个具有相同数量1位的更大数等。这些技巧对于优化算法性能和解决特定类型的编程问题非常有用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


下面的结论都是基于用补码表示负数的计算机平台
 1None.gifvoid main(unsigned int x)
 2ExpandedBlockStart.gif{     
 3InBlock.gif     //判断无符号整数x是否是2的幂 
 4InBlock.gif     if(x&(x-1))//若一个数是2的幂,则除最高位为1外,其余位均为0(二进制表示,下同)
 5InBlock.gif         printf("False\n");
 6InBlock.gif     else
 7InBlock.gif         printf("True\n");
 8InBlock.gif                      
 9InBlock.gif     //判断一个无符号整数是否为2^n-1的形式(原理同上) 
10InBlock.gif     if(x&(x+1))//若为2^n-1,则低位全为1 
11InBlock.gif         printf("False\n");
12InBlock.gif     else
13InBlock.gif         printf("True\n"); 
14InBlock.gif         
15InBlock.gif     //整数能被最大的2的幂(?)整除 : 析出最右侧为1的位
16InBlock.gif     //e.g.: 100->4
17InBlock.gif     printf("%d\n",x&(-x));//将其余位置0 
18InBlock.gif     
19InBlock.gif     //析出最右侧为0的位(原理同上) 
20InBlock.gif     //e.g.:111b->1000b, 10->1
21InBlock.gif     printf("%d\n",~x&(x+1));//将该位置1,其余位置0
22InBlock.gif     
23InBlock.gif     //识别后缀0的掩码(将右侧连续的0位置1,其余各位置0)
24InBlock.gif     //e.g.:1100b->0011b
25InBlock.gif     printf("%d\n"~x&(x-1));  //或 
26InBlock.gif     printf("%d\n"~(x|-x));   //或 
27InBlock.gif     printf("%d\n", (x&-x)-1);
28InBlock.gif     
29InBlock.gif     //识别最右侧的1未和后缀0的掩码(将最右侧的1位保留,并将其后面所有的0位置1) 
30InBlock.gif     //e.g.:1100b->0111b
31InBlock.gif     printf("%d\n", x^(x-1)); 
32InBlock.gif     
33InBlock.gif     //向右传播最右侧的1位 
34InBlock.gif     //e.g.:1100b->1111b
35InBlock.gif     printf("%d\n", x|(x-1));
36InBlock.gif     
37InBlock.gif     //将最右侧连续的1位置0
38InBlock.gif     //e.g.:10110b->10000
39InBlock.gif     printf("%d\n", ((x|(x-1))+1)&x);     
40ExpandedBlockEnd.gif}


计算x中有多少个为1的位:
 1None.gifint Count1(int x)
 2ExpandedBlockStart.gif{
 3InBlock.gif    int n = 0;
 4InBlock.gif    while(x)
 5ExpandedSubBlockStart.gif    {
 6InBlock.gif            n++;
 7InBlock.gif            x&=x-1;
 8ExpandedSubBlockEnd.gif    }
 9InBlock.gif    return n;
10ExpandedBlockEnd.gif}


获取下一个具有同样数量的1位的更大的数;应用:在用位串表示集合的子集时 
1None.gifunsigned snoob(unsigned x)
2ExpandedBlockStart.gif{
3InBlock.gif    unsigned smallest, ripple, ones;//e.g.: x=XXX0 1111 0000
4InBlock.gif    smallest = x & -x;              //        0000 0001 0000
5InBlock.gif    ripple = x + smallest;          //        XXX1 0000 0000
6InBlock.gif    ones = x ^ ripple;              //        0001 1111 0000
7InBlock.gif    ones = (ones >> 2/ smallest;  //        0000 0000 0111
8InBlock.gif    return ripple | ones;           //        XXX1 0000 0111
9ExpandedBlockEnd.gif}


本文转自Silent Void博客园博客,原文链接:http://www.cnblogs.com/happyhippy/archive/2007/04/24/725127.html,如需转载请自行联系原作者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值