Java学习笔记1.——原码反码补码和数据类型
文章目录
前言
学习记录,巩固知识,查缺补漏,我观看的是黑马程序员的视频做的笔记。
原码反码补码的正数均是相同的,有差异的只是负数。
提示:以下是本篇文章正文内容,下面案例可供参考
一、原码
十进制数的二进制表现形式,比如0000 0001,其中一个字节有8位,所以1B(Byte) = 8 b(bit)
从左往右,第一位为符号位,所以一字节最大为0111 1111 等于+127十进制。
原码的负数就是符号位取反,其余位不变,所以-1的原码是1000 0001。同理原码的最小负数为-127。
原码的0有两种表示方法,分别是 0000 0000 和 1000 0000为什么有两个0,则是在减法那里说了。
1.原码的加法
0000 0001 加1等于 0000 0002B == 2D
0000 0002 +1 == 0000 0003B ==3D
因为原码有两种表示方法,所以原码的减法就会有一定的问题。
2.原码的减法
1000 0001 - 1000 0001 = 1000 0000=0
0000 0001 - 0000 0001 = 0000 0000=0(这就是为什么原码有两个0的原因。)
1000 0000 等于 -0(也是0) 按理来说0+1==1可是原码算出来是等于-1
1000 0000 +1 == 1000 0001 == -1 与实际值0+1 ==1不同
1000 0001 +1 == 1000 0010 == -2 与实际值 -1+1 == 0不同
1000 0010 +1 == 1000 0011 == -3 与实际值-2+1 == -1不同
它们总是差值总是为2.
从数轴上看是因为两者的方向是相反的。
所以在这里引入反码,使它们方向相同。
二、 反码
因为符号位变了代表方向相反,所以把数值位也取反代表整体换了个方向,因此反码就是原码的基础上取反。
原码的正数和反码相同,只有负数才不一样,因为原码的正数计算是没有问题,有问题的是反码。
原码的0有两种表示方式,所以反码的0也有两种表示方式,分别是
0000 0000 和 1111 1111
现在来试试反码的减法是否正确。
1.反码的计算
原码1000 0001 的反码是 1111 1110 -1 +1
1111 1110 + 0000 0001 == 1111 1111 == 0
现在再看发现没有问题了。
再来试一个-1-1是否等于-2
1111 1110 - 0000 0001 == 1111 1101 == -2
注意! -1-1与-1-(-1)是不一样的 因为1111 1110 - 1111 1110 == 1000 0000 == -127
2.反码的跨零计算
再次注意,当反码-2+3时结果有不一样了。
-2+3=1
但是反码就不一样了,加起来会等于0
1111 1101 + 0000 0011 =0000 0000 (超出的部分不用管,所以这里符号位变了。)
这是因为0有两个表示方法,所以在这里进行夸0运算时会比实际值少1.
为了解决这个办法就在此引入了补码。
三、补码
补码是反码的基础上加一,且补码的0只有一种表示方法。
十进制数 | 原码 | 反码 | 补码 |
---|---|---|---|
+0 | 0000 0000 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 | 0000 0000 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
-2 | 1000 0010 | 1111 1101 | 1111 1110 |
-3 | 1000 0011 | 1111 1100 | 1111 1101 |
-4 | 1000 0100 | 1111 1011 | 1111 1100 |
-5 | 1000 0101 | 1111 1010 | 1111 1011 |
-6 | 1000 0110 | 1111 1001 | 1111 1010 |
-7 | 1000 0111 | 1111 1000 | 1111 1001 |
… | … | … | … |
-127 | 1111 1111 | 1000 0000 | 1000 0001 |
-128 | 无 | 无 | 1000 0000 |
如表所示,补码与反码是错开的,-2的补码与-1的反码相同,但是意思却是不一样的。现在再来进行减法运算。
1.补码的计算
-1+2=1
1111 1111 + 0000 0010 = 0000 0001
现在就是没有问题了。
四、数据类型
数据类型 | 长度 | 值 |
---|---|---|
byte的10 | 1字节 | 0000 1010 |
short的10 | 2字节 | 0000 0000 0000 1010 |
int的10 | 4字节 | 0000 0000 0000 0000 0000 0000 0000 1010 |
long的10 | 8字节 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1010 |
懂了上面的知识就懂了下面的强制与隐式转换了。
1.隐式转换
public class test{
public static void main(String[] args){
byte a = 10;
int b = a;
System.out.println(b);
}
}
范围小的自动转成范围大的,转换方法:
byte a 0000 1010
int b 0000 0000 0000 0000 0000 0000 0000 1010
2.强制转换
public class Test {
public static void main(String[] args){
int a = 200;
byte b = (byte)a;
System.out.println(b);
}
}
此时a 0000 0000 0000 0000 0000 0000 1100 1000
转换成byte 就是只后面这一字节 1100 1000
我们通过上面知道计算机中运算是用补码来计算的,并且字节的第一位是符号位,所以这个数的负数为-56
3.其他运算符
项目 | 含义 | 运算规则 |
---|---|---|
& | 逻辑与 | 相同为1,不同为0 |
l | 逻辑与 | 有1为1 |
<< | 左移 | 向左移动,低位补0 |
.>> | 右移 | 向右移动,高位补0或1 |
.>>> | 无符号右移 | 高位都补0 |
逻辑与
public class Test {
public static void main(String[] args){
int a = 8;
byte b = 9;
System.out.println(a & b);
}
}
0000 1000
0000 1001=0000 1000
所以运行结果为8
同理逻辑或就是9
提示:计算数字中没有短路
左移与右移
public class Jy {
public static void main(String[] args){
int a = 8;
byte b = 9;
System.out.println(a <<2 >> 1);
}
}
结果为16,因为先左移变成32再右移除以2
左移一位增大两倍,右移一位缩减两倍
总结
提示:这里对文章进行总结:
1.因为计算机中都是用补码计算,所以一个字节byte的范围是-128~+127
2.数据类型的转换,小转大隐式转换,大转小强制转换
3.其他运算符