无符号数的表示

寄存器的位数反应无符号数的表示范围

mark

有符号数的表示

机器数与真值

mark

其中小数点的位置是以约定的方式给出的.

原码表示法

整数

mark

正数的原码反码补码都是一样的, 负数就厉害了, 原码反码补码都不相同. 当我们用原码表示负数的时候, 只需要将这个数的符号位置为1就可以,假设这个负数为x即 $|x|+2^n$ , 因为x是负数, 所以上面的公式也就可以写为 $2^n - x$ .

小数

mark

但是用原码表示数有一个问题, 就是会出现两个0,如下所示: $$ [+0.0000]_原 = 0.0000 \ [-0.0000]_原 = 1.0000 \ [+0]_原 = 0,0000 \ [-0]_原 = 1,0000 \ $$

很明显$[+0]_原 \not= [-0]_原$.

虽然原码表示很简单, 直观, 但是还有以下问题:

mark

为了解决以上问题:让计算机只做加法, 找一个与负数等价的正数来代替这个负数. 补码就诞生了.

补码表示法

补的概念: 以时钟为例, 当前时钟的指针在6上, 需要将它拨到3, 可以采用两种方法: 1. 逆时针拨三格; 2. 顺时针拨九格. 即: $$ (6 - 3) \mod 12 = 3 \ (6 + 9) \mod 12 = 3 \ $$

mark

结论: 1. 一个负数加上之后,得到该负数的补数; 2. 一个正数和一个负数互为补数时,他们的绝对值之和为数.

mark

这个和时钟的例子其实是一样的.

另外正数的补数就是它本身, 两个互为补数的数加上模, 得到的结果仍然互为补数. 例如,在模等于$2^4$ 的情况下

mark

问题来了, 如何确定$+0101$是$+0101$还是$-1011$的补数呢? 很简单用$0,0101$表示$+0101$,用$1,0101$表示$-1011$,因为补了一位符号位,所以模变成了$2^{4+1}$. 在此基础上$00101+100000=100101$,第一位丢掉, 得到的结果还是$0,0101$,且

mark 所以补码的定义就出来了.

整数

mark

小数

mark

求补码的快捷方式

mark

负数的补码就是:原码除符号位外,每位取反,末位+1. 负数的原码也可以用:补码除符号位外,每位取反,末位+1来求得.

反码表示法

为了解决原码做减法的问题, 出现了反码, 而人们发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. $[+0]_反=0,0000$, $[-0]_反=1,11111$, 然后才是出现了补码解决0的问题.

整数

负整数的补码是:原码除符号位外, 每位取反, 末位+1,即$2^{n+1}+x$ ; 而负整数的反码是:原码除符号位外, 每位取反. 所以由上式推导得出负整数的反码定义 $(2^{n+1}-1)+x$.

mark

小数

负小数的补码是:原码除符号位外, 每位取反, 末位+1,即$2+x$, 这里的末位+1实际上是加了一个$2^{-n}$ ; 而负小数的反码是:原码除符号位外, 每位取反. 所以由上式推导得出负小数的反码定义 $(2-2^{-n})+x$.

mark

三种机器数小结

  1. 原码简单,直观,但是没有解决减法问题;
  2. 反码解决了减法问题,但是没有解决两个0的问题;
  3. 补码的引入解决了上述问题.

mark 当然也有:负数的补码除符号位外每位取反末位+1得到原码.

int8可以表示的范围是$[-128,127]$

mark

已知$[y]_补$求$[-y]_补$

mark

移码表示法

补码表示很难直接判断其真值大小, 如:

mark

移码的定义

mark 移码只有整数形式的定义, 这个与移码在计算机的数据表示中的作用有关, 移码通常表示浮点数据表示的阶码部分.

移码和补码的比较

mark

真值, 补码和移码的对照表

mark

移码的特点

mark