编码
真值
带符号位的机器数对应的真正数值称为机器数的真值
原码
原码就是符号加上真值的绝对值,即用第一位表示符号,其余表示值
反码
正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反
补码
正数的原码和补码相同。
负数的补码原码之间的转换方式:符号位不变,数值位取反后+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.xxxx 或 1.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位符号位),用规格化的补码表示。
阶码的范围(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$。尾数的范围(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}$。浮点数的表示范围
浮点数的真值 $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}$
结论
该浮点数格式所能表示的数值范围是:
- 负数范围:
$-2^{63} \le N \le -(2^{-1} + 2^{-8}) \times 2^{-64}$ - 正数范围:
$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)。