浮点数的规格化表示 & 非规格化表示

1 浮点数的一般表示

JfJ_f J1J2JmJ_1J_2\dots J_m SfS_f S1S2SnS_1S_2\dots S_n
阶符 阶码 数符 尾数

阶码的位数决定了浮点数的表示范围的大小,尾数的位数决定了浮点数的表示精度

  • 阶符:阶码的符号位。1为负;0为正
  • 阶码:即幂的大小。设幂e=(J1J2Jm)2e=(J_1J_2\dots J_m)_2
  • 数符:尾数的符号位。1为负;0为正
  • 尾数:尾数的大小。设尾数M=(S1S2Sn)2M=(S_1S_2\dots S_n)_2

一般基数r=2r=2,则浮点数真值N=(1)Jfre(1)SfMN=(-1)^{J_f}*r^e*(-1)^{S_f}*M

2 IEEE 754标准的浮点数

2.1 规格化浮点数的格式

msm_s EE MM
数符 阶码,用移码表示 尾数,用原码表示
  • 数符:尾数的符号位。1为负;0为正
  • 共三部分组成,省略了阶符。因为移码就隐含表示了阶码的正负
  • 规定尾数的最高有效位必须为1,若尾数最高有效位不是1,则需要进行左归(即尾数整体左移一位),每左归一次,阶码加1,直到最高有效位为1
  • 尾数部分隐藏了一个整数1(隐藏一位1是为了增加一位有效位),因此尾数的实际大小为1+M=1.M1+M=1.M

基数为2,因此浮点数真值N=(1)ms2E(1.M)2N=(-1)^{m_s}*2^E*(1.M)_2

类型 数符 阶码 尾数 总位数 阶码偏置值(十进制)
短浮点数 1 8 23 32 127
长浮点数 1 11 52 64 1023
临时浮点数 1 15 64 80 16383

1 关于阶码

  • 阶码的偏置值。阶码部分用移码表示,假设阶码为 n 位,则阶码偏置值取 2n112^{n-1}-1,因此短浮点数、长浮点数、临时浮点数阶码偏置值为2811=12721111=102321511=163832^{8-1}-1=127、2^{11-1}-1=1023、2^{15-1}-1=16383
  • 阶码的取值范围。假设阶码为 n 位,则可表示的范围为 02n10到2^{n}-1,,因此短浮点数、长浮点数的阶码取值范围为 0到255、0到2047。又规定当阶码全0时用来表示非规格化数,阶码全1时用来表示无穷大,所以阶码E的实际取值范围为 1到254、1到2046;
  • 阶码的实际大小。阶码采用移码的形式表示,阶码的实际大小需要减去对应的偏置值,通过这种方式来表示阶码的正负值。所以短浮点数、长浮点数的阶码实际大小为 EE-偏置值,即 1127=126254127=12711023=102220461023=10231-127=-126到254-127=127、1-1023=-1022到2046-1023=1023

2.关于尾数

假设尾数位数为 m 位,因为尾数部分隐含了一位整数1,所以尾数的实际位数为 m+1 位,因此因此短浮点数、长浮点数、临时浮点数、临时浮点数尾数实际有效位数为24、53、65位,真值为 1.M1.M

因此,规格化短浮点数的真值为
(1)ms(1.M)2E127 (-1)^{m_s}*(1.M)*2^{E-127}
规格化长浮点数的真值为
(1)ms(1.M)2E1023 (-1)^{m_s}*(1.M)*2^{E-1023}

2.2 规格化浮点数的取值范围

以短浮点正数为例:

当阶码和尾数都取最小时(E=1,M=0),表示的数值最小,阶码部分为 1127=1261-127=-126,尾数部分为 隐含的1加上其余的23位0;

当阶码和尾数都取最大时(E全1,M全1),表示的数值最大,阶码部分为 254127=127254-127=127,尾数部分为 隐含的1加上其余的23位1;

所以取值范围为 1.0×21261.111×21271.0\times 2^{-126}到1.11\dots 1\times 2^{127},即

格式 正数 负数
单精度 2126(2223)×21272^{-126}到(2-2^{-23})\times 2^{127} 2126(2223)×2127-2^{-126}到-(2-2^{-23})\times 2^{127}
双精度 21022(2252)×210232^{-1022}到(2-2^{-52})\times 2^{1023} 21022(2252)×21023-2^{-1022}到-(2-2^{-52})\times 2^{1023}

浮点数的规格化表示 & 非规格化表示

2.3 类型转换时的精度损失和溢出

这里以C语言为例。C语言中的float、double型分别对应IEEE 754标准的单精度和双精度浮点数,一个int型数据占4个字节、float占4字节、double占8字节。

1 溢出

  • 当float、double向int转换时可能会发生溢出,比如有符号int型表示的数据范围为 23123112^{-31}到2^{31}-1,而float、double类型的数据的表示范围超过了int类型
  • 当double向float、int转换时可能会发生溢出

2.精度损失

  • 当int向float转换时可能会发生溢出,因为int类型共四字节32位,而float尾数的有效位数为24位,当int型数据的有效位数超过24的话就会发生精度损失。比如
    unsignedintm=FFFFFFFFH2231)×231 unsigned \quad int\quad m = FFFF \quad FFFFH\\ 即(2-2^{-31})\times 2^{31}
    因为 m 的尾数部分共31位1,超过了float的23位(不含隐藏的一位1),超出的1会被舍掉,所以就会产生精度损失

  • 当double向float、int转换时可能会有精度损失,因为double类型尾数的有效位数位53,超过了float的24;而且浮点数向整数转换时,若是小数部分不为0,一定会有精度损失,因为整数没有小数部分