计算机基础——原码、反码、补码转换
说明
在看JDK源码的过程中,可以看到很多关于位运算的内容,位运算当然涉及计算机中二进制数字的存储方式以及值之间的转换,本文介绍一下二进制的三种表示方式:原码、反码、补码。
概念
原码: 将最高位作为符号位(0表示正,1表示负),其它数字位代表数值本身的绝对值。 反码:正数的反码和原码相同。如果是负数,则将原码符号位不变,其余各位取反,得到的就是负数的反码。
补码:正数的补码和原码相同。如果是负数,则将原码符号位不变,其余各位取反,然后将得到的数值加1(负数的补码也可以理解成反码加1)。
示例
通过上面的介绍,我们已经知道了几种二进制码之间的关系,下面用一个示例更直观表示一下。为了计算方便起见,假设计算机存储的是8位下的值。
总结一下:
- 正数的原码、反码、补码是相同的。
- 负数的反码是符号位不变其余按照原码按位取反,负数的补码是反码加1;
- 计算机运算以及存储都是基于补码形式。
- 0的补码只有唯一表示0000 0000
- -128没有原码和反码,因为已超表示范围,原码和反码区分正0负0,但是补码不需要,空出来的这个位置用来表示-128即1000 0000
- 8位有符号数值的范围为[-128,127)注意包含-128
计算机中二进制为什么使用补码表示
这里面牵扯到一个很重要的计算方式模运算。通过模运算实现化减为加,本质上是将溢出的部分舍去而不改变计算结果。 8位运算的模为256=2^8。 在无符号位的情况下:127+2=129 129超出了8位运算的最大表示范围,所以上面的二进制的结果1000 0001表示的转换为原码为1111 1111即为-127。意思就是说129在计算机中的表示和-127是一样的,就像是时钟过了12点重新从0点开始了,超过了最大的数就从最小的数开始,256类似于时钟的一圈。 这里我们可以得出结论:负数的补码为模减去该数的绝对值 以-3为例: -3原码:1000 0011 -3反码:1111 1100 -3补码:1111 1101 使用模运算计算结果:-3=256-3=253=1111 1101(二进制)
根据下面的例子我们看一下补码是如何化减为加的 127-3=127+(-3)=124=0111 1100(二进制) 由于我们存储的是8位,因此溢出舍弃得到的是0111 1100=124(十进制),因此补码的化减为加核心是通过溢出舍弃操作来完成的。