1.记住移位操作符或者位操作符是作用于二进制的补码
正数的原码反码补码都是一样的
负数的反码是原码取反,0变为1,1变为0,注意第一位及符号位保持不变;
补码是反码加一;
记住位运算符是作用于二进制的
正数的原码反码补码都是一样的
负数的反码是原码取反,0变为1,1变为0,注意第一位及符号位保持不变;
补码是反码加一;
2.左位操作符的用法 <<
假设a,b是整数的话,a << b中a是一个数,b是向右移动几位;
负数变为原码的小技巧:补码取反在加一;跟原码变为补码一样,怎么样容易记吧!!!
按照int四个字节来算,假设a=1,它的补码二进制就是00000000000000000000000000000001,
-1的补码是1111111111111111111111111111111111111;
+2的补码是00000000000000000000000000000010;
-2的补码是1111111111111111111111111111111111110;
左移一个位后,它的补码向左移动一个位,即左边丢掉一个数,右边补上一个零;记住符号位不要动;再结合目录1我讲得二进制补码原码转换就可以得出这个结果了
3.右移操作符的用法 >>
右移一个位后,它的补码向右移动一个位,即右边丢掉一个数,左边补上一个零;记住符号位不要动;再结合目录1我讲得二进制补码原码转换就可以得出这个结果了
右移是算术右移,所以不动符号位;逻辑右移是将符号位也动了
+4的补码是00000000000000000000000000000100;
-4的补码是1111111111111111111111111111111111100;
+2的补码是00000000000000000000000000000010;
-2的补码是1111111111111111111111111111111111110;
4.按位于 &操作符的用法
a & b 的意思是将补码中一一对应的位,如果全为1就为1,反之为0;
5的补码:00000000000000000000000000000101
7的补码:00000000000000000000000000000111
5&7补码 00000000000000000000000000000101
那么5 & 7等于5;
5.按位或的用法
a | b 的意思是将补码中一一对应的位,如果全为0就为0,反之为1;
5的补码:00000000000000000000000000000101
7的补码:00000000000000000000000000000111
5 | 7补码 00000000000000000000000000000111
那么5 | 7等于7;
6.按位异或的用法
a | b 的意思是将补码中一一对应的位,如果相同就是0,相反就是1;
5的补码:00000000000000000000000000000101
7的补码:00000000000000000000000000000111
5 ^ 7补码 0000000000000000000000000000010
5 ^ 7 = 2
7.按位取反的用法
~a的用法是将二进制的数值全部取反(包括符号值)
1的补码是00000000000000000000000000000001
-2的补码111111111111111111111111111111111110
~1的补码是111111111111111111111111111111111110
所以 ~1等于 -2
我们将移位操作符和位操作符讲完了,接下来我们来讲一下它们的用途
它们通常用于二进制中,但也有别的情景;
8.移位操作符和位操作符的用途
曾经出现过一道变态的面试题
如何不创建第三个变量来交换两个变量的值?
这道题可谓难倒了大部分人;
但是也有人解决了它
但是这么写也有缺陷,有可能两数相加的值过大,导致超出最大值;
因此,咱们结合前面我们讲得,可以考虑另一种做法;
首先我们讲一下底层逻辑:
a ^ a = 0;
a ^ 0 = a;
接下来咱们来实现交换它们:
这样写就不会导致数值溢出了;
但是这种做法也仅仅适用于面试,正常情况下直接建立一个变量就行了,因为那样更具有可读性;
接下来你会怎么考虑将一个十进制转换为二进制并且打印二进制的1的个数呢?
我接下来先讲一种思路
例如11的二进制有多少个1?
首先我们可以算出它的补码,11%2=1 ,11/2=5, 5%2=1, 5/2=2, 2%2 =0, 2/2=1, 1%2=1, 1/2=0,然后从右往左用它的余数就是他的补码1011。这个方法适用于所有数,数越大越好用。
接下来我们来用代码实现一下
当然我们也可以用刚刚讲的位操作符来实现它们
底层逻辑:减去n的补码中1的值,例如1000 &(0111)= 0;
n = 15的补码是1111
n &(n-1)即
1111 - n
1110 - n-1
1101 - n // 即1111&1110
1100 - n-1
1100 - n
1011 - n-1
1000 - n
0111 - n-1
0000 - n
好了讲到这里就差不多的结束了,让我们享受连续不断发生的奇迹(指日常)。