位运算和进制转换,原码,反码

左移 <<

举个栗子,5 << 2 将5左移2 结果为20 为啥?注意是对二进制进行的操作,来看:

首先会将5转为二进制表示形式(Java中,整数默认就是int类型,也就是32位):

null
怎么去理解,首先在Java中,整数默认就是int类型,也就是占4个字节32位,你就可以想成这样

0000 0000 0000 0000 0000 0000 0000 0000

这就是32位,但是每位上都是0,这是一个标准,用于后面的比较,比如5的二进制是

0000 0000 0000 0000 0000 0000 0000 0101

然后把它与标准的进行对比,也就是这样:

null
这时候的区别就在后四位,然后将5左移(<<)2,也就是5的二进制以标准为参考整体左移2位,也就是这样:

null

这样一来,就产生了错位,看图:
null
不过这时候看着总是有点别扭,应该都是四位四位的在一块吧,所以从低位开始,四位一组,就成了这样
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

看图:

null

仔细看图分析分析😃

无符号右移 >>>

先记住这句话:*正数右移,高位补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补*

时间关系,就不赘述了。

位与 &

其实核心都是二进制,所以掌握好进制转换是关键,看看位与 &是怎么计算的:

null

这里要看两个操作数的二进制的各个位的对应情况,总结起来也就是:

有0则0,否则为1

什么意思呢?我们举一个例子来看看
我们猜这个结果是什么,答案是
null
注意这里可不是6除以3,它是这样计算的,首先6和3都要转成二进制,6的二进制是110,3的二进制是11也就是011,那么这样运算

null
我相信看图就能明白的,而二进制的010就是2啦,这就是位与的操作,对于或和亦或其实同样道理,我们继续来看~

位或 |

规则就是:有1则1

看例子:

null

位异或 ^

规则是:相同则0,不同则1

看例子:

null

有点难懂的位非 ~

这是网站随便找的一个例子,你看看,求~5,得-6,为啥?

null
它这里的规则是:操作数的第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
2
3
[-0]原=10000000

[+0]原=00000000

反码也有两种表示法:

1
2
3
[+0]反=00000000

[- 0]反=11111111

这就有点难受啊,不都是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