位运算
什么是位运算
在计算机系统中,所有数据都是以二进制的形式进行存储,位运算就是对二进制中进行操作。所有的计算都是通过位运算进行实现的。
整数在计算机中
原码
原码是最简单的表示法,对于一个整数而言,最高位代表数据的正负,其他数位代表数据
比如对于一个8位二进制而言 ,00000010
代表有符号整数和没符号整数的 2
10000010
代表有符号整数的的-2
和没符号整数的130
原码可以让我们更容易看出一个二进制的数值,但是也导致了 正数0和负数0的重合,比如00000000
和10000000
表示 +0和 -0,在数学中,都表示0.但是与在计算机中没一个数字代表唯一的数位是相悖的,这容易造成数位的加减问题
反码
反码是原码转向补码的中间状态,正数的反码为本身,负数的反码为除了符号位其他位取反这解决了加减的问题
比如 -1 + 1,转化为反码就是111111110
+0000000001
加起来为11111111
得-0
的反码,但是未解决0的问题。
补码
正数的补码是他原码,也是他的反码。负数的补码是反码加1。计算机存储都是以补码的形式存储的,
这个就很好解决了0 和 负数加减的问题。
比如 在8位二进制表示的数中,-1
的原码为10000001
。反码为11111110
,那么他的补码为111111111
,从补码我们可以看出,如果-1 + 1
,可以很简单的转化为00000000
,对应原码中的正数0,很好的解决了两个0的情况,也很好解决了数据的加减问题。
位运算
位运算的符号
位运算的优先级
那么问题: 给一串运算 1 | 1 ^ 1 & 1 << 1 等于多少?
1 | 1 ^ 1 & 1 << 1 = 1 | 1 ^ 1 & 2= 1 | 1 ^ 0= 1 | 1 = 1
位运算的进阶用法
改变某一位
//将最后一位置为1 a | 1//将最后一位置为0a | 1 - 1//最后一位取反a ^ 1//将倒数第n位变为1a | 1 << n //将倒数第n位变为0a & ~(1 << n)//第k位取反a ^ (1 << n)// 右边的第一个0 变为1 10001001 -> 10001011a | (a+1)// 右边的第一个1 变为0 10001010 -> 10001000a ^ (a & -a)
截取
//取最后一位a & 1//取最后第n位a & 1 << n 或者 a >> n & 1 //取最后n位 a << n 得 10000 减一则为01111末尾全是1a & (a << n - 1)//截取最后n位 011111 截取 2位 01111 a >> n // 取最后一个1得数位 比如 0110 取位 0010a & -a// 取右边连续的1 比如 100001111 变为 00001111a ^ (a+1)
改变几个数位
//右边连续n位 变为1 1001011 -> 1001111a | (a << n -1)//右边连续n位 取反 1001011 -> 1000100a ^ (a << n - 1)// 右边连续得1变为0 10001111 -> 1000000a & (a + 1)// 右边连续的0变为1 1001000 -> 10011111a | (a - 1)
负数的位运算
在进阶用法中我们用到了 a & -a,来取最后一个1的数位, 也就是00001110
取最后一个1保留其位置,得到00000010
如果一个数是14
那么他正负数的原码,反码,补码可以表示为
原码反码补码00001110 0000111000001110100011101111000111110010
那么可以很明显的看出来 补码相与就是最后一个1保留 其他全部为0;得到00000010
位运算的高级用法
判断一个数是否为2的n次幂
if(a & (a - 1)){//是2的整数次幂}else{//不是2的整数次幂}
乘法
a >> 1 // a / 2a << 1 // a * 2
交换两个数
public static void swap(){int a,int b;a ^= b;b ^= a;a ^= b;}
加减法
public int add(int a, int b){while (b != 0){//相同为0 不同为1int tempa = a ^ b;//进位 判断1的数量b = (a & b) << 1;a = tempa;}return a;}add(1,2);add(100,200);
乘法
public int muti(int a, int b){int number = 0;int count = 0;while (b != 0){if((b & 1) != 0){number = add(number, a << count);}b = b >> 1;count ++;}return number;}muti(1,2);muti(100,200);
在算法中的应用
https://leetcode-/problems/count-words-obtained-after-adding-a-letter/solution/by-ubk86jcv4a-wpri/https://leetcode-/problems/missing-two-lcci/solution/java-onshi-jian-o1kong-jian-by-ubk86jcv4-bni7/https://leetcode-/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/solution/yi-huo-by-ubk86jcv4a-94et/https://leetcode-/problems/palindrome-pairs/solution/yi-huo-da-fa-by-ubk86jcv4a-fng8/如果觉得《位运算以及位运算的应用》对你有帮助,请点赞、收藏,并留下你的观点哦!