java第二期:位运算

一、位运算的介绍

位运算:又称是二进制运算,位(代表的是二进制,或者是bit位)1字节 = 8bit(位)。
连接的操作数:其实也是二进制,返回值是一个数据类型。
存储格式:二进制数存储在计算中都是以补码的形式进行存储的。
原码 --> 反码 --> 补码
--------1--------- 2
步奏1:反码 = 0和1的替换
步奏2:补码 = 在反码的前提下+1

原码 <-- 反码 <-- 补码
-------- 2--------- 1
步奏1:反码 = 补码-1
步奏2:原码 = 反码的0、1替换
下面有步奏案例
关于3种状态码的认知在第六标题处,可往下观看。

二、位运算符的使用(bit的补码形式)

介绍运算符:
| & ^ :双目运算符,操作数有两个
~ : 单目运算符,操作数只有一个

3 和 4 的一个按位运算,底层转换为二进制数进行一个运算
3的二进制数:0b0000000000 00000000000 000000000 11
4的二进制数:0b0000000000 00000000000 000000001 00
因为一个int = 4byte 1byte = 8bit
所以将int转二进制数为 32bit(位)

1、按位与 &
规则:在二进制数位上只有相同1的时候才为true
0 1 1
1 0 0 上下都不同,所有结果为 0 0 0
3 & 4 = 0b0000000000 00000000000 000000000 00 最终结果为:0

2、按位或 |
规则:在二进制数位上,只要有一个为1时就为true
0 1 1
1 0 0 上下都有一个1,所以结果为 1 1 1
3 | 4 = 0b0000000000 00000000000 000000001 11 最终结果为:7

3、按位异或 ^
规则:在二进制数位上,相同的为0(不管是0,还是1),不同的为true
0 1 1
1 0 0 上下不相同,所以结果为 1 1 1
3 ^ 4 = 0b0000000000 00000000000 000000001 11 最终结果为:7
有个小特点:
对一个数进行两次异或,那么这个数的结果是不变的(自己尝试3 ^ 4 ^ 4=3)
一般用于加密,也就是说你拿到这个数据后,再进行一个异或才能获取到正确的数

4、取反 ~
3的二进制数:0b 0000000000 00000000000 000000000 11 (补码)
进行取反操作:0代表的是正数,1代表的是负数
规则:在单目运算中,0变1,1变0
3的取反二进制数为:0b1111111111 1111111111 1111111111 00 (补码)负数
已知补码求反码?
在补码-1后取反,先将二进制-1,在进行一个0、1替换的操作(符位号不变)
相减操作:
0 b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0

  •                                               1(减1)
    

0 b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1
上述是相减后的最终二进制结果,再将其取反就得原码(符号为不变)
取反:0b 11111111 11111111 11111111 111110 11
原码:0b 10000000 00000000 00000000 000001 00
~3 = -4 最终的结果为:-4

三、面试小题

题目:两数替换操作,给你两个数,不能使用第三个数实现一个替换?
Int a = 3
Int b = 4
// 题目:有两个数,实现替换操作(不可以使用第三个数)
int a = 3;
int b = 4;

	// 1、以前的操作,利用第三个数为桥梁,实现数据的替换操作
	int c = 0;
	
	c = a; // c = 3
	a = b; // a = 4
	b = c; // b = 3

这是没使用按位操作符的前提原始替换的一个操作
具体实现步奏:
1、现将a的数据赋值给c 那么c = 3
2、将b的数据赋值给a 那么a = 4 -->之前a = 3的
3、将c的数据赋值给b 那么b = 3 -->之前b = 4的
4、最终结果 a = 4 b = 3(成功)

// 2、使用按位异或的操作
a = a ^ b;
b = a ^ b; --> a^ b ^ b 异或两次 a不变
a = a ^ b; --> a ^ a ^ b 异或两次 b不变
小特点:异或两次值不变

四、位移操作

1、左移(<<)
3 << 4,让操作数乘以2的n次幂,n就是移动的位数
3 << 4 = 3 * 2 ^ 4 = 48
看看底层的实现:
3的二进制数:0b00000000 00000000 00000000 000000 11
向左移动就是左边减少4,但是位数缺失4位,那么在最右边补齐,变为:
0b0000 00000000 00000000 000000 110000
最终结果为:16 + 32 = 48

2、右移(>>)
32 >> 2,让操作数除以2的n次幂,n就是移动的位数
32 >> 2 = 32 / 2 ^ 2 = 8
看看底层的实现:
32的二进制数:0b00000000 00000000 00000000 001000 00
向右移动就是右边边减少2,但是位数缺失2位,那么在最左边补齐(符号位是数字就补什么数字“0、1”),变为:
0b0000000000 00000000 00000000 001000
最终结果为:2^3 = 8
负数右移:
-32 >> 2,让操作数除以2的n次幂,n就是移动的位数
-32 >> 2 = -32 / 2 ^ 2 = -8
看看底层的实现:
-32的二进制:
原码:0b10000000 00000000 00000000 001000 00
反码:0b11111111 11111111 11111111 110111 11(1、0替换)
补码:0b11111111 11111111 11111111 110111 11(+1)

  •                                    1(加1)
    

0b11111111 11111111 11111111 111000 00
-32往右移动两位:那么右边的两位将被挤掉,在左边符号位是什么那么就添加什么(0、1)
补码:0b1111111111 11111111 11111111 1110 00
根据补码求原码:
0b1111111111 11111111 11111111 1110 00

  •                              1(减1)
    

反码:0b1111111111 11111111 11111111 1101 11(-1)
原码:0b1000000000 00000000 00000000 0010 00(1、0替换)
最终的结果为:-8

3、无符号右移(>>>)

3.1、为什么叫无符号右移,这里有必要解释一下:
在一个补码的情况下,向右移动n位,在最左边无视符号位,统统用0来补齐,这里的特殊点体现在负数的一个位移运算中

3.2、>>>与>>这个的区别:
2.1、在正数中的一个位运算中结果是一样的
2.2、在负数的运算中,下面将详细的步骤解析,可以尝试自己思考一下再看

正数的运算:
32 >>> 2,让操作数除以2的n次幂,n就是移动的位数
32 >>> 2 = 32 / 2 ^ 2 = 8
看看底层的实现:
32的二进制数:0b00000000 00000000 00000000 001000 00
无符号向右移动就是右边边减少2,但是位数缺失2位,那么在最左边补齐(忽略符号位,统统使用0来补齐),变为:
0b0000000000 00000000 00000000 001000
最终结果为:2^3 = 8 与 >>位运算没啥区别

负数的运算:
-32 >>> 2,让操作数除以2的n次幂,n就是移动的位数
-32 >>> 2 = -32 / 2 ^ 2 = -8
看看底层的实现:
-32的二进制:
原码:0b10000000 00000000 00000000 001000 00
反码:0b11111111 11111111 11111111 110111 11(1、0替换)
补码:0b11111111 11111111 11111111 110111 11(+1)

  •                                   1(加1)
    

0b11111111 11111111 11111111 111000 00
-32往右移动两位:那么右边的两位将被挤掉,那么将在最左边补齐(忽略符号位,统统用0来补齐)
补码:0b0011111111 11111111 11111111 1110 00
最终的结果为:1073741816很大(但是在int范围内)

五、有符号的数据表示

1、什么是有符号数?
-1、-5、+10…这些就是有符号数,有正负之分的。

2、在计算机中的表现形式为二进制
-7:这个数在计算机中的二进制数为:
1 0000000 00000000 00000000 00000111
int类型的一个数值范围(2^32有正负之分)
一个int整型4位,一个byte = 1字节,一字节 = 8bit,所以int = 4*8 =32bit(位)
第一个1:代表是符号位,也就是说1代表负数,0代表正数
第二组111:代表数据,也就是说,他们是转换的主要内容,通过8421码来进行一个运算
111 = 1+2+4 = -7(上面的二进制数java程序中是不能直接得到的-7的,下面会讲解到原因(补码问题))
提示:
在上期文档中进制之间的转换:有一个8421码,大家尽量记牢,背下每一位上对应的十进制数。

六、原码、反码、补码

1、介绍
在计算机中,所有的符号数据都是按照补码进行一个储存的
2、区分
正数的原码、反码、补码都是一样的
负数的就不一样了

符号位:就是二进制码的最左位数
原码:符号位+数值位(绝对值)
反码:就是将原码的0、1替换(0变为1,1变为0),符号位不变
补码:就是在反码的基础上进行一个+1的运算(计算机最终计算的二进制数据)

以+、-7最为举例:
+7
原码:0b00000000 00000000 00000000 00000111
反码:0b00000000 00000000 00000000 00000111
补码:0b00000000 00000000 00000000 00000111
-7
原码:0b10000000 00000000 00000000 00000111
反码:0b11111111 11111111 11111111 11111000

  •                                   1(加1)
    

补码:0b11111111 11111111 11111111 11111001

3、计算机显示给我们看的是原码,但是存储的是补码进行的一个运算
计算机是如何将-7的补码还原成原码呢?
补码:0b11111111 11111111 11111111 11111001(-1操作)

  •                                   1(减1)
    

反码:0b11111111 11111111 11111111 11111000(替换操作)
原码:0b10000000 00000000 00000000 00000111

很明显的一个操作,可以自己去写一个java程序,就以+、-7作为案例
打印
+7的原码:0b00000000 00000000 00000000 00000111 == 7
-7的原码:0b10000000 00000000 00000000 00000111 !=-7
原因是什么呢?(自己思考)
提示:上面已讲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿仁

多一分支持,多一分动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值