首页 > 代码库 > 位操作 注意事项
位操作 注意事项
逐步更新。。。
1.位操作符的运算优先级比较低,因此尽量使用括号来确保运算顺序,否则很可能会得到莫明其妙的结果。比如要得到像1,3,5,9这些2^i+1的数字。写成int a = 1 << i + 1;是不对的,程序会先执行i + 1,再执行左移操作。应该写成int a = (1 << i) + 1;
2.奇偶判断
for (i = 0; i < 100; ++i)//输出0~100内所有奇数 if (i & 1) printf("%d ", i); putchar('\n');
3.不用第三方变量交换两数
void Swap(int &a, int &b) { if (a != b)//这里是必须的,不然就会a^b==0,结果就是本来a、b用来交换的,经此函数操作后,都变成0了 { a ^= b; b ^= a; a ^= b; } }
4.变换符号
取反加一
int sign_rev(int a){ return ~a+1; }
5.求绝对值
int my_abs(int a) { int i=a>>31;//若a为正数,则i为0,若a为负数,则i为-1,0异或某数为某数,-1异或某数,等于某数取反 return (i^a)-i; }
6.二进制逆序
第一步:每2位为一组,组内高低位交换
10 00 01 10 11 01 10 00
-->01 00 10 01 11 10 01 00
第二步:每4位为一组,组内高低位交换
0100 1001 1110 0100
-->0001 0110 1011 0001
第三步:每8位为一组,组内高低位交换
00010110 10110001
-->01100001 00011011
第四步:每16位为一组,组内高低位交换
01100001 00011011
-->00011011 01100001
#include <stdio.h> void print(int a) { int i; for(i=sizeof(a)*8-1;i>=0;--i) { if((a>>i)&1) putchar('1'); else putchar('0'); if(i%8==0) putchar(' '); } putchar('\n'); } int main(int argc, char *argv[]) { unsigned int a=34520; print(a); a=((a&0xaaaaaaaa)>>1)|((a&0x55555555)<<1); print(a); a = ((a & 0xCCCCCCCC) >> 2) | ((a & 0x33333333) << 2); print(a); a = ((a & 0xF0F0F0F0) >> 4) | ((a & 0x0F0F0F0F) << 4); print(a); a = ((a & 0xFF00FF00) >> 8) | ((a & 0x00FF00FF) << 8); print(a); unsigned int b=0; for(short int i=1;i!=0;i<<=1) { b<<=1; if(a&1) b|=1; a>>=1; } print(b); return 0; }
7.二进制中1的个数
1)先写个衍生于树状数组中的做法:
int cnt=0; while(b){ b-=(b&-b); cnt++; } printf("cnt is %d\n",cnt);不断减去二进制最后一个1,最后就能到一共减了几次,也就是有多少个1。其运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有k个1,那么这个方法只需要循环k次即可
2)
速度不一定最快,但是想法绝对巧妙。 说一下其中奥妙,其实很简单,先将n写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。以217(11011001)为例,有图有真相,下面的图足以说明一切了。217的二进制表示中有5个1:
int BitCount4(unsigned int n) { n = (n &0x55555555) + ((n >>1) &0x55555555) ; n = (n &0x33333333) + ((n >>2) &0x33333333) ; n = (n &0x0f0f0f0f) + ((n >>4) &0x0f0f0f0f) ; n = (n &0x00ff00ff) + ((n >>8) &0x00ff00ff) ; n = (n &0x0000ffff) + ((n >>16) &0x0000ffff) ; return n ; }8. 缺失的数字 LeetCode的那个single number
必定有一个数只出现一次而且其它数字都出现了偶数次。用搜索来做就没必要了,利用异或运算的两个特性——1.自己与自己异或结果为0,2.异或满足交换律。因此我们将这些数字全异或一遍,结果就一定是那个仅出现一个的那个数
const int MAXN = 15; int data[MAXN] = {1, 347, 6, 9, 13, 65, 889, 712, 889, 347, 1, 9, 65, 13, 712}; int lostNum = 0; for (int i = 0; i < MAXN; i++) lostNum ^= data[i]; printf("缺失的数字为: %d\n", lostNum);
位操作 注意事项
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。