编码


编码

真值

带符号位的机器数对应的真正数值称为机器数的真值

原码

原码就是符号加上真值的绝对值,即用第一位表示符号,其余表示值

反码

正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反

补码

正数的原码和补码相同。

负数的补码原码之间的转换方式:符号位不变,数值位取反后+1.

移码

用于比大小,负数的补码比正数大,不利于比大小。一个数的移码越大,其真实值越大。

移码=真值+偏移量

n位二进制数的偏移量一般为$2^{n-1}$。

浮点数

(一般定点小数就是纯小数:小数点死死固定在符号位后面,只能表示 $-1 \le x < +1$ 之间的数)

一个二进制浮点数由三部分组成:符号位(S)指数位(E)尾数位(M)

它把一个数表示成类似科学计数法的形式:$(-1)^S × M × 2^E$。

规格化

是为了最大化浮点数的精度,并保证一个有效数值在浮点数表示中的唯一性,而对尾数提出的一种特定格式要求。

如果不进行规格化,同一个数会有多种表示方式。例如,对于二进制小数 $0.5$:
可以表示为 $0.1 \times 2^0$
也可以表示为 $0.01 \times 2^1$
还可以表示为 $0.001 \times 2^2$

规格化就是通过移动小数点并调整阶码,使得尾数变成一个“标准”的形式。通常我们默认尾数是纯小数,且基数为 2。

原码表示下的规格化规则:小数点后第一位必须是1.

补码表示下的规则化原则:符号位与小数点后第一位的数值必须相反。

规格化数就是让浮点数的尾数变成最简标准形式

IEEE 754

之前的通用教科书格式,尾数默认是纯小数,即格式为 符号位 . 数值位 (如 0.xxxx1.xxxx)。

隐藏位规格化

在 IEEE 754 中,规格化数的真值形式被定义为:$(−1)^S×1.尾数×2^{阶码}$。

规格化要求小数点前不能是 0,这个整数永远是 1,直接“省略”掉。

非规格化数

当要表示的数非常非常小,比规格化数能表示的最小正数($1.0×2^{E_{min}}$)还要小时,如果强制规格化,阶码就会溢出(变成负无穷),导致结果直接变成 0。

为了处理这种极小的数,IEEE 754 规定:当阶码全为 0 时,取消隐藏的 1,默认整数部分是 0。这样就可以表示$0.000…01×2^{E_{min}}$这样极小的数字了。

此时,数值的计算公式变成了:
$V=(−1)^S×0.尾数×2^{1−127}=(−1)^S×0.尾数×2^{−126}$.

此时阶数固定为-126,(即 $1 - \text{Bias}$)。它保证了非规格化数和最小规格化数在量级上是平滑衔接的。

假设我们要表示一个非常小的数:$2^{−127}$。

  • 用规格化数表示:做不到,因为阶码无法变成 -127。
  • 用非规格化数表示
    因为 $2^{−127}=0.1(二进制)×2^{−126}$。
    这里,阶码对应的真实指数是 −126(所以阶码字段全填 0,表示非规格化)。
    尾数部分去掉隐藏的 0 后,实际存储的是 100...0(即二进制的 0.1)。
    这样,这个极小的数就被精确地保存下来了,而没有被粗暴地记为 0。

只有当阶码全为 0,且尾数也全为 0 时,才表示真正的数值 0(包含 +0 和 -0)。

如果不引入非规格化数,从最小规格化数 $1.0×2^{−126}$往下,数字会直接断崖式跌落到 0,这在数学上意味着“间距突然变为无穷大”。
引入非规格化数后,从 $1.0×2^{−126}$ 往下,数字会以等差数列的形式(每次增加$2^{−23}×2^{−126}$)慢慢逼近 0。虽然最后还是会到达 0,但这种平滑的过渡避免了数学计算上的断层,这就是所谓的渐进下溢

例题

某浮点数格式如下:7 位阶码(包含一个符号位),9 位尾数(包含一个符号位)。若阶码用移码、尾数用规格化的补码表示,则浮点数所能表示的数的范围是?

总位数:阶码 7 位,尾数 9 位。
阶码:7位(包含1位符号位),用移码表示。
尾数:9位(包含1位符号位),用规格化的补码表示。

  1. 阶码的范围(7位移码)
    对于 $n$ 位移码(通常偏移量为 $2^{n-1}$),其表示范围是对称的整数范围。
    位数 $n = 7$
    偏移量 = $2^{7-1} = 2^6 = 64$
    7位移码的二进制范围:从 0000000 到 1111111(即十进制 0 到 127)
    对应的真值范围:$0 - 64 = -64$,到 $127 - 64 = 63$
    因此,阶码 $E$ 的真值范围为:$-64 \le E \le 63$。

  2. 尾数的范围(9位规格化补码)
    对于 $n$ 位补码小数(1位符号位,其余为数值位),规格化补码的规则是:符号位与小数点后第一位数值相反。
    位数 $n = 9$(1位符号位 + 8位数值位)
    最大正尾数:符号位为0,小数点后第一位必须为1,其余位全为1。
    二进制表示:0.11111111
    真值:$1 - 2^{-8}$
    最小负尾数(绝对值最大的负数):符号位为1,小数点后第一位必须为0,其余位全为0。
    二进制表示:1.00000000
    真值:$-1$
    因此,尾数 $M$ 的真值范围为:$-1 \le M \le 1 - 2^{-8}$。

  3. 浮点数的表示范围
    浮点数的真值 $N = M \times 2^E$。要求数的表示范围,就是求最大正数、最小负数(绝对值最大的负数)以及最接近0的正负数。
    最大正数:
    尾数取最大正数:$1 - 2^{-8}$
    阶码取最大值:$2^{63}$
    最大正数 = $(1 - 2^{-8}) \times 2^{63}$

最小负数(绝对值最大的负数):
尾数取最小负数:$-1$
阶码取最大值:$2^{63}$
最小负数 = $-1 \times 2^{63} = -2^{63}$

最小正数(最接近0的正数,下溢界限):
尾数取最小正规格化数:0.10000000,即 $2^{-1}$
阶码取最小值:$2^{-64}$
最小正数 = $2^{-1} \times 2^{-64} = 2^{-65}$

最大负数(最接近0的负数,下溢界限):
尾数取最大负规格化数:1.01111111,即 $-(2^{-1} + 2^{-8})$
阶码取最小值:$2^{-64}$
最大负数 = $-(2^{-1} + 2^{-8}) \times 2^{-64}$

结论
该浮点数格式所能表示的数值范围是:

  1. 负数范围:
    $-2^{63} \le N \le -(2^{-1} + 2^{-8}) \times 2^{-64}$
  2. 正数范围:
    $2^{-65} \le N \le (1 - 2^{-8}) \times 2^{63}$
    (注:如果仅问宏观的数值上下界,则范围为 $[-2^{63},\ (1 - 2^{-8}) \times 2^{63}]$,其中 $0$ 也可精确表示。)

CRC校验码

规定一个k阶生成多项式,将数据左移k位,然后除以这个多项式,得到k位余数加在后面这k个左移产生的0上。得到了发送的数据帧。

检验:将用于发送的数据帧除以这个多项式,因为模2除法的性质,只要数据未受损,一定是整除的。由此检验数据的完整性。

模2除法

在模2除法(常用于CRC循环冗余校验)中,核心规则是不借位减法,也就是异或运算(XOR)


文章作者: v
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 v !
  目录