998 字
5 分钟
CSAPP_小数的表示

二进制小数的定点表示#

回忆上面用进制表示数的方法,小数部分的表示与整数部分类似,只不过是多了负的位权

N=±[an2n+an12n1++a121+a020+b121+b222++bm2m]其中a1an,b1bm 是0~1中的一个数码N=\pm [a_n\cdot 2^n+a_{n-1}\cdot 2^{n-1}+\dotsc+a_1\cdot 2^1+a_0\cdot 2^0+\boxed{b_1\cdot 2^{-1}+b_2\cdot 2^{-2}+\dotsc+b_m\cdot 2^{-m}]}\\[10pt] \text{其中$a_1\dotsc a_n,b_1\dotsc b_m$ 是0~1中的一个数码}
  1. 十进制小数 \to 二进制小数:不断乘以2,取整数部分(0或1)依次作为二进制位,直到小数部分为0或达到所需精度。

  2. 二进制小数 \to 十进制小数:小数点右边第n位的位权是 2n2^{-n}(n从1开始),将每一位乘以对应的位权(2i2^{-i})并求和。

例如将13.25转换为二进制:

  1. 整数部分13转换为二进制:13 ÷ 2 = 6 余 1;6 ÷ 2 = 3 余 0;3 ÷ 2 = 1 余 1;1 ÷ 2 = 0 余 1。倒序排列余数得到1101。

  2. 小数部分0.25转换为二进制:0.25 × 2 = 0.5 取整为0;0.5 × 2 = 1.0 取整为1。得到二进制小数为0.01。

因此,13.25的二进制表示为1101.01。

二进制小数的无限循环#

但是二进制小数只能表示形如 a2b\dfrac{a}{2^b} 的数,像0.1这样的数在二进制中是无限循环的:

0.110=0.0001100110011001120.1_{10}=0.00011001100110011\dotsc_2

二进制科学计数法:规格化数的表示#

规格化数由三部分组成:符号位S,指数E,尾数M

=(1)SM2EE=eBias\text{值} = (-1)^S M 2^{E}\\ E= e-Bias\\

浮点数表示法IEEE 754#

  • 符号位S:1位,0表示正数,1表示负数

  • 尾数M:只存储二进制小数的小数部分,删除1.

  • 指数E:表示指数部分,一般用 2E<value<2E+12^{E}<value<2^{E+1} 求得

  • Bias:偏移值,半精度是7,单精度是127,双精度是1023,保证阶码e是非负数

  • e:e=E + Bias,是个无符号整数(exp的十进制表示)

  • 阶码exp:e的二进制表示

C语言中常用的浮点数类型有两种:float(单精度)和 double(双精度)。

以float为例:C语言中的float类型占4个字节,也就是32位二进制表示,具体分配如下:

字段位数说明
(高位:31)符号位S10表示正数,1表示负数
(30~23)阶码exp8e=E+127
(22~0 低位)尾数M23存储二进制小数的小数部分

在float类型下,偏移值 Bias=2811=127Bias=2^{8-1}-1=127

浮点数数值分类#

根据阶码字段将浮点数分为以下几类:

  1. 规格化数(Normalized Numbers):

    • 阶码exp不全为0且不全为1(即 1e2541 \leq e \leq 254126E127-126\leq E \leq 127)。
    • 值的范围:(1)S×1.M×2eBias(-1)^S \times 1.M \times 2^{e-Bias}`
  2. 非规格化数(Denormalized Numbers):

    • 阶码exp全为0,尾数M不全为0。
    • 用于表示非常接近于零的数值
    • 值的范围:(1)S×0.M×21Bias(-1)^S \times 0.M \times 2^{1-Bias}
  3. (Zero):

    • 阶码exp全为0,尾数M全为0。
    • 有正零和负零两种表示,值为0。
  4. 无穷大(Infinity):

    • 阶码exp全为1,尾数M全为0。
    • 用于表示超出表示范围的数值,值为正无穷或负无穷。
  5. 非数(NaN, Not a Number):

    • 阶码exp全为1,尾数M不全为0。
    • 用于表示未定义或不可表示的数值(如0除以0)。

舍入误差#

这里重点讲偶数舍入(Round to Nearest, Even)

对于十进制数,四舍六入五取偶

例如:在保留小数点后两位的条件下:

  • 2.345 约为 2.34 (4是偶数,舍去5)
  • 2.355 约为 2.36 (5是奇数,进1)

对于二进制数:

定义最低有效位(LSB)为0的二进制数为偶数,LSB为1的二进制数为奇数。

例如:在保留小数点后两位的条件下:

  • 0.1010 约为 0.10 (LSB为0,舍去1)
  • 0.1111 约为 1.00 (LSB为1,进1)

舍入误差的影响#

浮点数的运算性质#

由于舍入误差的存在,浮点数运算(+,*)不满足交换律,结合律与分配率

类型转换#

小类型转大类型(int/floatdoubleint/float\to double):精度不变,数值不变

大类型转小类型(doublefloat/intdouble\to float/int):可能发生舍入误差,数值可能改变,或者溢出。

CSAPP_小数的表示
https://biscuit0613.github.io/posts/csapp/csapp_float/
作者
Biscuit
发布于
2025-11-04
许可协议
CC BY-NC-SA 4.0