众所周知,计算机中是以二进制来存储数据的,计算机顾名思义设计之初也是为了计算,那么计算机是如何进行运算的呢?
原码:二进制形式
反码:最高位符号保持不变,其余取反
补码:正数和0的补码等于原码,负数的补码将其对应正数按位取反再加1
1.计算机中的计算也都以补码来进行运算的, 那么为什么要引入这三种码呢?
以Java中的byte类型为例,byte类型占1B(8bit),取值范围为[-128, 127],这个取值范围是怎么来的呢?
0000 0000 ~ 1111 1111 这个区间是8b的取值范围共256,我们把最高位作为符号位,将其分为正数和负数来看:
如下是按照原码来区分:
0000 0000 ~ 0111 1111 => [0, 127]
1000 0000 ~ 1111 1111 => [-127, -0]
假如我们在原码上计算1 + (-1)
0000 0001
1000 0001
---------
1000 0010
出现的问题:
如下是按照补码来区分:
0000 0000 ~ 0111 1111 => [0, 127]
1000 0000 ~ 1111 1111 => [-128,-1]
注意:补码1000 0001并不是-1,1000 0001 - 1 = 正数按位取反 => 0111 1111 = 正数,所以1000 0001对应的是-127
同理:补码1000 0000 - 1 = 正数按位取反 => 1000 0000 = 正数,所以1000 0000 对应的是-128, 同理1111 1111对应的-1
因此byte的取值范围为[-128, 127]
此时我们再执行1 + (-1), 可以看到结果为0, 使用补码之后上面的两个问题都得以解决
0000 0001
1111 1111
---------
0000 0000
总之:引入反码和补码之后,就可以解决负数运算的问题了
我们再以java中int的取值范围为例[-2147483648, 2147483647],首先通过如下的代码,打印出具体的补码
// 这里打印的是补码的逆序
public static void printTwosComplement(int target) {
int value = target;
for (int j = 0; j < 32; j ++ ) {
System.out.print(value & 1);
value >>= 1;
}
System.out.println();
}
public static void main(String[] args) {
// 10000000000000000000000000000000
printTwosComplement(-2147483648);
// 10000000000000000000000000000001
printTwosComplement(-2147483647);
// 11111111111111111111111111111111
printTwosComplement(-1);
// 00000000000000000000000000000000
printTwosComplement(0);
// 01111111111111111111111111111110
printTwosComplement(2147483646);
// 01111111111111111111111111111111
printTwosComplement(2147483647);
}
按照上述所说:根据补码推断正数,因此对于-2147483648:
补码: 100000000 00000000 00000000 00000000
补码-1: 011111111 11111111 11111111 11111111
取反: 100000000 00000000 00000000 00000000
取反后得到的正数是2^31,也即2147483648
2. Java中 为什么两数相乘结果不对呢?两数相加结果是对的呢?
// e = 0.010000001
float e = 0.1f * 0.1f;
System.out.println(e);
// f = 0.2
float f = 0.1f + 0.1f;
System.out.println(f);
0.1的补码是多少呢?
0.1 * 2 = 0.2 ------ 0
0.2 * 2 = 0.4 ------ 0
0.4 * 2 = 0.8 ------ 0
0.8 * 2 = 1.6 ------ 1
0.6 * 2 = 1.2 ------ 1
0.2 * 2 = 0.4 ------ 0
0.4 * 2 = 0.8 ------ 0
......
以此类推,0.1的补码为 0.00011001100110011...... 计算机是无法准确表达0.1的,因此计算结果出现误差也可以理解, 但是为什么0.1 + 0.1的结果确是对的呢?
这个原因是Java编译器做了相关的优化,从而使结果为正确的
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。