位运算和进制转换,原码,反码
位运算和进制转换,原码,反码
左移 <<
举个栗子,5 << 2 将5左移2 结果为20 为啥?注意是对二进制进行的操作,来看:
首先会将5转为二进制表示形式(Java中,整数默认就是int类型,也就是32位):
怎么去理解,首先在Java中,整数默认就是int类型,也就是占4个字节32位,你就可以想成这样
0000 0000 0000 0000 0000 0000 0000 0000
这就是32位,但是每位上都是0,这是一个标准,用于后面的比较,比如5的二进制是
0000 0000 0000 0000 0000 0000 0000 0101
然后把它与标准的进行对比,也就是这样:
这时候的区别就在后四位,然后将5左移(<<)2,也就是5的二进制以标准为参考整体左移2位,也就是这样:
这样一来,就产生了错位,看图:
不过这时候看着总是有点别扭,应该都是四位四位的在一块吧,所以从低位开始,四位一组,就成了这样
0000 0000 0000 0000 0000 0000 0001 0100
换算成十进制就是20了 这就是5 << 2得到结果的由来。
右移 >>
还是先将5转为2进制表示形式:
0000 0000 0000 0000 0000 0000 0000 0101 然后右移2位,高位补0:
0000 0000 0000 0000 0000 0000 0000 0001
看图:
仔细看图分析分析😃
无符号右移 >>>
先记住这句话:*正数右移,高位补0,负数右移,高位补1,负数无符号右移,高位补0 正数无符号右移 ,高位补0 正数换算成二进制后的最高位为0,负数的二进制最高位为1*
接下来依然是看例子,在此之前我看过好多别人写的,发现好多都喜欢用5举例子你知道为啥吗😂
5换算成二进制是: 0000 0000 0000 0000 0000 0000 0000 0101
5右移3位后结果为0,0的二进制为: 0000 0000 0000 0000 0000 0000 0000 0000 // (这里高位补0)
-5换算成二进制是: 1111 1111 1111 1111 1111 1111 1111 1011
-5右移3位后结果为-1,-1的二进制为: 1111 1111 1111 1111 1111 1111 1111 1111 // (高位补1)
-5无符号右移3位后的结果 536870911 换算成二进制: 0001 1111 1111 1111 1111 1111 1111 1111 // (高位补0)
这里需要注意了:*以上说的都是右移的情况,如果是左移,无论是正数还是负数,低位都是用0补*
时间关系,就不赘述了。
位与 &
其实核心都是二进制,所以掌握好进制转换是关键,看看位与 &是怎么计算的:
这里要看两个操作数的二进制的各个位的对应情况,总结起来也就是:
有0则0,否则为1
什么意思呢?我们举一个例子来看看
我们猜这个结果是什么,答案是
注意这里可不是6除以3,它是这样计算的,首先6和3都要转成二进制,6的二进制是110,3的二进制是11也就是011,那么这样运算
我相信看图就能明白的,而二进制的010就是2啦,这就是位与的操作,对于或和亦或其实同样道理,我们继续来看~
位或 |
规则就是:有1则1
看例子:
位异或 ^
规则是:相同则0,不同则1
看例子:
有点难懂的位非 ~
这是网站随便找的一个例子,你看看,求~5,得-6,为啥?
它这里的规则是:操作数的第n位为1,那么结果的第n位为0,反之。
不知道你懂吗?有这么一个解释:
6的二进制数为: 0000 0000 0000 0000 0000 0000 0000 0110 然后6的二进制反码为: 1111 1111 1111 1111 1111 1111 1111 1001 将反码+1得到-6的补码二进制数:1111 1111 1111 1111 1111 1111 1111 1010
所以这里就牵涉到原码,反码和补码了,另外还有个重点的点就是:
负数在计算机中是以补码的形式存在的
好了,我们赶紧来看看什么是原码,反码和补码吧!
最后攻克原码,反码和补码
这是非常重要的概念,需要熟练掌握,要记得。开始之前,先上一个重要的结论:
数据在计算机中的存储是二进制的形式,二进制简单来说就是0和1组合的,无论原码,反码还是补码,都是二进制的形式
其次我们要注意的点就是正数和负数的原码,反码和补码,是有区别的。
原码
什么是原码嘞?
对于正数来说,我们把它的绝对值转换成的二进制数叫做正数的原码,对于负数来说我们把它的绝对值转换成的二进制数,然后最高位补1,称为原码。看看,还是有区别的。
发现关键所在了吧,原码是绝对值转换成的二进制数,那正负数自然存在本质差别了
比如 :
00000000 00000000 00000000 00000101 是 5的 原码。
10000000 00000000 00000000 00000101 是 -5的 原码。
这里有个点就是最高位是0代表正数,是1代表负数。
正数和负数在计算机中怎么表示的
接下来就是在计算机中的表示:
对于正数:原码,反码和补码都是一样的,所以在计算机中怎么说都一样,反正就是本身转换成二进制的结果,可以说原码,也可以说补码,因为都是一样的
对于负数:原码,反码和补码是不一样的,在计算机中*负数是以补码的形式存在的*
所以说,重点聚焦在负数上,看它的反码和补码是怎么表示的
反码
那反码是啥嘞?
*负数的反码为对该数的原码除符号位外各位取反[每一位取反(除符号位)]。*
**
*要理解什么是符号位*
这里有个符号位,啥?还记得刚刚说的吗?
最高位是0代表正数,是1代表负数。
也就是最左边的那一位,叫做符号位!二进制数从右往左看,依次由低变高,所以最左边的就是最高位,通常也叫做符号位!
取反操作指:原为1,得0;原为0,得1。(1变0; 0变1)
比如:
正数00000000 00000000 00000000 00000101 的反码还是
00000000 00000000 00000000 00000101
负数10000000 00000000 00000000 00000101 的反码则是
11111111 11111111 11111111 11111010
另外啊反码是相互的,因此也可称:
10000000 00000000 00000000 00000101 和 11111111 11111111 11111111 11111010互为反码。
不过这里有个问题,那就是+0和-0,什么意思呢?
原码和反码在表示数的时候的有点尴尬啊,比如表示零的时候,同样都是0,但是原码就有两种表示法:
1 | [-0]原=10000000 |
反码也有两种表示法:
1 | [+0]反=00000000 |
这就有点难受啊,不都是0吗,于是乎,就出了补码
补码
那啥又是补码嘞?
*负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1*
比如:10000000 00000000 00000000 00000101 的反码是:11111111 11111111 11111111 11111010
那么,补码为:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
这里有两点需要注意:
1、从补码求原码的方法跟原码求补码是一样的 ,也可以通过完全逆运算来做,先减一,再取反。
2、补码却规定0没有正负之分
第二个啥意思呢,也就是说对于0的表示,补码只有一种[-0]补=00000000。感觉这样就正常多了。
总结一下
原码表示法规定:用符号位(最左边)和数值表示带符号数,正数的符号位用“0”表示,负数的符号位用“1”表示,数值部分用二进制形式表示。
反码表示法规定:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反。
补码表示法规定:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1~
正零和负零的补码相同,[+0]补=[-0]补=0000 0000B