1.什么是原码?
-
就是把十进制表现成二进制,最左边是符号位是0则为正,是1则为负;
-
比如56转换成二进制00111000; 其中二进制的第一位就是符号位0; 后面的就是数据0111000;
-
当中二进制的一个数字就是一个“bit”比特位; 8个bit就是一组,也就是一个字节,这个字节是计算机当中最小的存储单元;
-
一个字节的最大值就是01111111;也就是+127; 一个字节的最小值是11111111;也就是-127;(10000000 = -0; 10000001 = -1);
2.什么是反码?
-
为了解决原码不能计算负数的问题而出现的;
-
规则:正数的反码不变,负数的反码在原码的基础上,符号位不变,数值取反,0变1,1变0;
-
比如 -56 的原码是 10111000, 它的反码是 11000111; 也就是说符号位不变,别的比特位 0 变 1, 1 变 0;
-
0有两种表现形式:原码(00000000 = 0, 10000000 = -0); 反码(00000000 = 0, 11111111 = -0); 补码的0只有一个状态 00000000;
3.什么是补码?
-
补码是为了解决负数计算诞生的,因为在二进制中的原码和反码计算,如果跨入0的层次,比如负数加正数等于正数的时候,它跨入了0,就会存在1的误差,因为0有两种表现形式!
-
用补码去计算负数,就可以完美解决这些误差,因为补码的0它只有一种状态,就是八个零;
-
而补码就是反码的基础上+1; 比如-3的原码是1000 0011,反码是1111 1100,所以它的补码应该是1111 1101;
-
再比如-2的原码是 1000 0010, 反码是 1111 1101,在右边最后一位的基础上+1,(二进制遇2进1)所以它的补码就是1111 1110;
-
-128是没有原码和反码的,补码是1000 0000,但是丝毫不影响计算,因为计算机的计算和存储都是用补码进行计算的
-
正数的原码,补码,反码都是一样的
我们了解到原码,补码,反码后,我们再来看基本数据类型:
byte类型的10 = 1个字节 (8个比特位) 0000 1010
short类型的10 = 2个字节 (16个比特位) 0000 0000 0000 1010
int类型的10 = 4个字节 (32个比特位) 0000 0000 0000 0000 0000 0000 0000 1010
long类型的10 = 8个字节 (64个比特位) 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1010
我们再来看一段代码来解释:
public class Demo {
public static void main(String[] args) {
// int类型是4个字节: 0000 0000 0000 0000 0000 0000 1100 1000
int a = 200;
// 在这里强转换为byte的一个字节类型,我们只需要砍掉int类型的32-8=24个比特位就行,所以它应该只剩下1100 1000
byte b = (byte)a;
// 注意:这里第一位是符号位,它变成了1,所以是负数-56
System.out,println(b); //-56
}
}
我们再使用其他的运算符来解释:
运算符 | 含义 | 运算规则 |
---|---|---|
& | 逻辑与 | 0为false 1为true |
| | 逻辑或 | 0为false 1为true |
<< | 左移 | 向左移动,低位补0 |
>> | 右移 | 向右移动,高位补0 |
public class Demo {
public static void main(String[] args) {
// 因为 “|” 两边都为假,结果才是假; 也就是说只要有个1 就是1,否则就是0;
int a = 200; // 0000 0000 0000 0000 0000 0000 1100 1000
int b = 10; // 0000 0000 0000 0000 0000 0000 0000 1010
System.out,println(a | b); // | ————————————————————————————————————————
// 0000 0000 0000 0000 0000 0000 1100 1010
}
}