Java位运算知识总结

Java位运算知识主要涉及:1.进制转换。2.有符号数:原码、反码、补码。3.位运算符概述。

1.进制转换

此部分涉及到进制的概念。二进制、八进制、十六进制与十进制相互转换的方法,比较基础
虽然底层都是二进制,但是计算机需要知道你输入的数据要以何种进制来解读。
所以Java中以0b开头的是二进制数,以0开头的是八进制数,以0x开头的是16进制数。

int x = 0b100;	//这样,x的十进制值实际上是4,二进制是100

2.原码、补码、反码

这部分需要讲一讲。正数在计算机中都是以二进制形式来存储这个好理解,但是如果我们要存负数呢?这时我们就把这个有符号数 的二进制首位当作符号位。如果首位是1表示它是负数,首位为0就代表它是正数。这就涉及到要讲的原码、补码、反码

正数:

通俗点讲,以5为例,假设它是一个int类型(4个字节,32个bit)
因此它的原码是:

0b00000000000000000000000000000101

正数的补码反码和原码保持一致。

负数:

那么-5在计算机中是怎样的呢?
有人说,太简单了,直接把上面5的原码的符号位改成1不就行了
即:0b10000000000000000000000000000101
可是输出一下,你会发现,这并不是-5,而是-2147483643.

为什么呢?

哈哈,这就是因为,计算机中存储正数和负数,都是以补码的形式来存储的,而不是直接存储原码噢!!!

0b10000000000000000000000000000101		//这只是-5的原码

通过原码,我们可以取反得到反码(除符号位以外取反),然后反码 + 1才得到我们最终存到计算机中的补码。

所以-5的反码、补码:

0b10000000000000000000000000000101		//这只是-5的原码
0b11111111111111111111111111111010		//这只是-5的反码
0b11111111111111111111111111111011		//这只是-5的补码

所以,真正的-5,应该是0b11111111111111111111111111111011(补码)
写上System.out.println(0b11111111111111111111111111111011);这才会出现-5输出


3。位运算符概述

&, | , ~, ^, >>, <<, >>>
与 或 非 异或 右移 左移 无符号右移

位运算符就这几种,其中只有~是单目运算符
以下操作数默认为二进制:
&:只有当两个都为1,那么结果才为1
如:101 & 011 = 001

|:只要有一个为1,那么结果就为1
如:101 | 011 = 111

~:取反
如:~101 = 010

^:相同的结果为0,不相同的结果为1
如:101 ^ 011 = 110
再如:101 ^ 100 = 001

左移<<:相当于结果乘2的n次幂。n为移动的位数
如: 101 << 2 = 10100
101十进制为5 ;10100十进制为20
原理:
101 十进制结果 = 2 ^ 2 + 2 ^ 0 = 5
10100十进制结果 = 2 ^ 4 + 2 ^ 2 = 2 ^ 2 * (2 ^ 2 + 2 ^ 0) = 20

右移>>:相当于结果除以2的n次幂,n为移动的位数
理由同上。

无符号右移>>>:
这里注意一下,右移最高位补的内容和符号位一样。如果符号为是1,那么最高位右移时补1
但是无符号右移不同,无符号右移最高位始终补0

因此,无论什么数,无符号右移之后得到的一定是一个正数!

-5右移和无符号右移的区别
0b11111111111111111111111111111011		//-5的补码(左移右移都是对-5的补码操作)
0b11111111111111111111111111111110		//-5 >> 2	
0b00111111111111111111111111111110		//-5 >>> 2

显然,移完之后结果完全不同

最后再提醒一下,这些操作都是对补码进行操作的!计算机都是以补码的形式将数字存储进去的。


【拓展:异或运算符的两个作用】

异或有个很神奇的特点:若一个数对另一个数异或两次,那么这个数还是其本身。
说通俗点,即a = a ^ b ^ b
原理可以这样解释:
1.如果a = 0, b = 0。那么a ^ b = 0, a ^ b ^ b = 0 ^ 0 = 0 = a;成立
2.如果a = 1, b = 1。那么a ^ b = 0, a ^ b ^ b = 0 ^ 1 = 1 = a;成立
3.如果a = 0, b = 1。那么a ^ b = 1, a ^ b ^ b = 1 ^ 1 = 0 = a;成立
4.如果a = 1, b = 0。那么a ^ b = 1, a ^ b ^ b = 1 ^ 0 = 1 = a;成立

因为二进制中,只有0和1,所以上面4种情况都满足,那么可以证明,a = a ^ b ^ b;

利用这个性质,有很多用处:

1.加密

文件为file, 密钥为key。
那么我们在传输文件之前,对info = file ^ key。那么即使窃取到这个信息,不知道key也无法解读。
收件人收到文件之后,利用性质,info ^ key = file;这样就可以得到原文件了。


2.快速交换两个变量的值

此种方法不需要借用额外变量
int a = 3, b = 4;
a = a ^ b;
b = a ^ b;
a = a ^ b;
三句话完成交换

原理:

a = a ^ b = 3 ^ 4,		
//这句话把a ^ b赋值给了a,也就是说a = 3 ^ 4
b = a ^ b = 3 ^ 4 ^ b = 3 ^ 4 ^ 4 = 3;
//因为此时b = 4,所以这句话做完,b就已经变成3的值了,也就变成了a的初始值
a = a ^ b = 3 ^ 4 ^ 3 = 4		
//因为a = 3 ^ 4,b = 3,所以a ^ b = 4 = a

过程非常巧妙。得需要细细思考一下,注意a, b和一开始a, b初值3, 4不要搞混了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值