原码
原码是最直观的二进制表示法:
- 符号位:最高位表示符号(0为正,1为负)。
- 数值位:剩余位表示绝对值。
- 例如:
+5→0 0101(假设为5位二进制)-5→1 0101
原码的运算缺陷
- 加减法需要区分符号:
- 同号相加:直接相加,符号不变。
- 异号相加:需转换为减法,可能导致结果符号错误。
- 符号位参与运算:
- 原码的符号位和数值位需分开处理,导致硬件电路复杂。
- 示例:计算
1 - 1(即1 + (-1)):- 原码形式:
0 0001(+1) +1 0001(-1) - 直接相加:符号位参与运算 →
1 0010(-2),显然错误
- 原码形式:
反码
为了解决原码不能计算负数的问题出现的
计算规则:正数的反码不变,负数的反码在原码的基础上,符号位不变,数值取反,0变1,1变0
反码的弊端:
| 十进制数 | 原码 | 反码 |
|---|---|---|
| +1 | 0000 0001 | 0000 0001 |
| +0 | 0000 0000 | 0000 0000 |
| -0 | 1000 0000 | 1111 1111 |
| -1 | 1000 0001 | 1111 1110 |
缺陷:反码出现从负数计算结果到正数这种跨0的情况,因为反码存在-0和+0故最终结果与真实结果会有1个误差
补码
为了解决反码跨0计算出现误差1的情况出现的
计算规则:正数补码不变,负数补码是在反码的基础上+1
| 十进制数 | 原码 | 反码 | 补码 |
|---|---|---|---|
| 0 | 0000 0000 | 0000 0000 | 0000 0000 |
| -1 | 1000 0001 | 1111 1110 | 1111 1111 |
| -2 | 1000 0010 | 1111 1101 | 1111 1110 |
计算机中存储的数据都是以补码形式存储的哦!这就解释了为什么byte的数据类型是-127到+128了
类型转换原理
隐式类型转换:核心就是前面补0
public class Test{
public static void main(String[] args){
byte a=10;//0000 1010
int b=a;//在a前面补上3个字节的0即3*8=24个0 0000 0000 0000 0000 0000 0000 0000 1010
}
}
强制类型转换:
public class Test{
public static void main(String[] args){
int a=300;//0000 0000 0000 0000 0000 0001 0010 1100
byte b=(byte)a;//将前面3个字节3*24个0去掉,0010 1100
//因为是去掉前面的0这就解释了为什么强制类型转换会导致数据丢失了!
}
}
位运算
-
&,逻辑与:0为false,1为true,如果都是true结果才为true否则都为false举例:
int a=200 int b=10 int sum=a&b 变为补码形式 a: 0000 0000 0000 0000 0000 0000 1100 1000 b: 0000 0000 0000 0000 0000 0000 0000 1010 &--------------------------------------------- sum:0000 0000 0000 0000 0000 0000 0000 1000 再转换为十进制sum=8 -
|逻辑或:0为false,1为true,只要有true结果就是true举例
int a=200 int b=10 int sum=a|b 变为补码形式 a: 0000 0000 0000 0000 0000 0000 1100 1000 b: 0000 0000 0000 0000 0000 0000 0000 1010 |--------------------------------------------- sum:0000 0000 0000 0000 0000 0000 1100 1010 再转换为十进制sum=202 -
<<左移:把二进制向左移动,低位补0举例
a=200 a: 0000 0000 0000 0000 0000 0000 1100 1000 a<<2 将a的二进制向左移2bit 00 0000 0000 0000 0000 0000 1100 100000 此时变为800 记住左移一次就是乘2 -
>>右移:把二进制向右移动,高位补0或1举例
a=200 a: 0000 0000 0000 0000 0000 0000 1100 1000 a>>2 将a的二进制向右移动2bit 000000 0000 0000 0000 0000 0000 1100 10 符号位根据原来是正数还是负数进行补 原来是正数补0,负数补1 并且右移一次除2 -
无符号右移
>>>向右移动,高位补0