操作系统:(二)原码,反码,补码,计算丢失精度
1.原码
对于一个数, 计算机要使用一定的编码方式进行存储。原码, 反码, 补码是机器存储一个具体数字的编码方式。在计算机中数据存储都是以二进制的形式表示数据,那么将一个十进制数转换为其二进制形式称为其原码。二进制最左边的是符号位,0为正,1为负。
计算机中存储的最小单元是字节
,字节以二进制存储数据,一个字节对应8个比特位
。也就是说一个字节的最大值的二进制表示形式为0111 1111
,其中第一个0为符号位,最大值对应十进制就是127。最小值为1111 1111
,十进制为-127。
2.反码
当前讨论的反码和补码都是讨论负数,正数的反码和补码等于其原码
在原码为负数的情况进行相加,会出现运算结果不一致的情况,例如1000 0001
,加1,那么理论得到的结果应该是1000 0000
(十进制0),实际得到的是100000010(十进制-2)。
为了解决原码不能计算负数,遵循以下反码的计算规则:正数反码不变,负数的反码在原码的基础上,符号位不变,0变1,1变0。计算完后再取反码就可以得到负数的运算结果。
但是在跨0计算的时候会存在误差:例如-5+6得0(当前讨论一个字节,多出去的1直接忽略)
3.补码
当前讨论的反码和补码都是讨论负数,正数的反码和补码等于其原码
为了针对0在二进制中有两个表示形式,引出使用补码进行计算,即负数的补码等于负数的反码+1
由于原码的0占了两个反码,在修改成补码后会多出一个数字,二进制数字为1000 0000
,即-128,所以规定-128的补码为1000 0000
。
在计算机中存储和计算都采用补码,所以即使-128没有原码和反码也不碍事(在1个字节的情况下)。
4.Java中的隐式转换和强制转换(拓展)
隐式转换直接加0
强制转换直接删掉字节前面的全部内容,得到补码进行计算(在计算机中存储和计算都采用补码)
b的值就是二进制-1后取反,得到原码,最后是-56。因为b是补码形式的二进制数据。
5.其他运算符(拓展)
左移一次乘2,右移一次除2。
6.十进制转二进制
小数部分的转换不同于整数部分,它采用的是乘2取整法,将十进制中的小数部分乘以2作为二进制的一位,然后继续取小数部分乘以2作为下一位,直到不存在小数为止。
但是,并不是所有小数都可以用二进制表示,前面提到的0.625小数是一个特例,刚好通过乘2取整法的方式完整的转换成二进制。
如果我们用相同的方式,来把0.1 转换成二进制,过程如下:
所以只能无限接近0.1而取不到0.1的值,所以算出来就不是0.3