原码、补码、反码

in 星海拾贝 with 0 comment

人有十个手指头,所以就有了十进制,满十进一。

template.png

计算机的存储单元受限于物理设备,只能有两种状态,即传统意义上的“开”和“关”,”高“和”低“,”1“和”0“,对计算机来说,二进制是它最擅长的。早期的计算机有尝试过用十进制存储和使用数据,但和二进制相比效率非常底下,后来这种方案被时代所抛弃了。此外二进制还和布尔代数相互映衬,有着坚实的理论基础。

机器数和真值

机器数

机器数:一个数在计算机中的实际存储形式。

机器数是带符号的,在计算机用一个数的最高位存放符号, 非负数为0, 负数为1。

如果用8位去表示一个数字,则十进制的3机器数为0000 0011;-3的机器数为1000 0011

如果用16位去表示一个数字,则十进制的3机器数为0000 0000 0000 0011;-3的机器数为1000 0000 0000 0011

真值

真值:机器数实际表示的值。

机器数的第一位为符号位,1代表负,0代表0或正。

例:0000 0011的真值为3;1000 0011 的真值为-3

原码, 反码, 补码

对于同一个机器码,可以有不同的理解方式。最初机器码是原码,后来又出现了反码和补码。

原码

正数的原码是其二进制本身;负数是符号位为1,数值部分取绝对值的二进制。

如果用8位去表示一个数字,则十进制3的原码为0000 0011;-3的原码为1000 0011

表示范围为[-127,127]。其中0有两种表示形式,0000 0000 (正零),1000 0000(负零)

反码

正数的反码和原码相同;负数是符号位为1,其它各位是原码取反。

如果用8位去表示一个数字,则十进制3的反码为0000 0011;-3的原码为1000 0011,反码为1111 1100

表示范围为[-127,127]。其中0也有两种表示形式,0000 0000 (正零),1111 1111(负零)

补码

正数的补码和原码相同;负数是符号位为1,其它各位是原码取反,未位加1。

如果用8位去表示一个数字,则十进制3的反码为0000 0011;-3的原码为1000 0011,补码为1111 1101

表示范围为[-128,127]。其中0只有一种表示形式 0000 0000 ,-128为1000 0000

运算过程

早期计算机设计时需要添加加减运算,加法可以利用微小电路单元加法器轻松实现。但是减法实现起来就没有那么容易了。考虑到减去一个正数等于加上一个负数,即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 也就不需要再为减法设计多余的电路了。

对于计算十进制的表达式: 1-1=0

原码计算

$$ 1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2 $$

反码计算

$$ 1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0\\ 2 + (-1) = [0000 0010]反 + [1111 1110]反 = [1,0000,0000]反 = (循环进位) [0000,0001] = 1 $$

补码计算

$$ 1-1 = 1 + (-1) = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原 = 0 $$

原码计算结果为-2,与实际不符,故不能化减法为加法。

反码计算是由于-0的存在,可能需要循环进位,会让人很迷惑。

补码的出现解决了-0的问题,同时又能够多表示一个数-128。现代计算机一般使用原码。

同余

“模”的概念

想象日常使用的钟表,它可以显示0~12点的时间,假设现在是2点钟,请用手动拨动时针的方式将时间减4小时,你会怎么做?

有两种方式:

  1. 逆时针将时针拨4小时
  2. 顺时针将时针拨8(12-4)小时

拨动12-4也可以得到2,这里就涉及了同模的概念。

取模公式

$$ x\;\%\;y=x \; mod \; y =x-y\lfloor x/y \rfloor\quad for\; y\neq 0 $$

两个整数a,b,若它们除以整数m所得的余数(与m同号)相等,则称a,b对于模m同余

记作 a ≡ b (mod m),读作 a 与 b 关于模 m 同余。

例如4 mod 12 = 16 mod 12 = -8 mod 12 = 4

所以4,16,-8关于模12同余。

在模的范围内做减法,可以将“X-Y”的减法变更为“X+Y的补数“的加法

8位二进制数一共可以表示2的8次方,256个数,即0~255,他们的极限就是256,即256是8位二进制数的模。

假设有一个256刻度的时钟,当前时钟处于20,现在需要减去100,结果应该为-80。

用时钟方法,减去100就等价于加上156(256-100),结果为176,刚好与-80关于256同余。

为此可以得出正确的求补码方法:正数的补码为其本身,负数的补码为256-负数的绝对值。

取反加一

记得不太清楚了,好像是有这个公式。具体怎么解释这个公式,等想起来了再修改吧。

$$ ([原码]+[补码])\% 256 =1 $$

补码和原码的相互转化均为”取反加一“

”取反加一”和同模比起来更加好记,但是要记住补码的本质是什么。

参考

原码, 反码, 补码 详解

补码是怎么计算出来的?还是约定的?

Responses