浮点数的规格化表示 & 非规格化表示
1 浮点数的一般表示
阶符 | 阶码 | 数符 | 尾数 |
阶码的位数决定了浮点数的表示范围的大小,尾数的位数决定了浮点数的表示精度
- 阶符:阶码的符号位。1为负;0为正
- 阶码:即幂的大小。设幂
- 数符:尾数的符号位。1为负;0为正
- 尾数:尾数的大小。设尾数
一般基数,则浮点数真值
2 IEEE 754标准的浮点数
2.1 规格化浮点数的格式
数符 | 阶码,用移码表示 | 尾数,用原码表示 |
- 数符:尾数的符号位。1为负;0为正
- 共三部分组成,省略了阶符。因为移码就隐含表示了阶码的正负
- 规定尾数的最高有效位必须为1,若尾数最高有效位不是1,则需要进行左归(即尾数整体左移一位),每左归一次,阶码加1,直到最高有效位为1
- 尾数部分隐藏了一个整数1(隐藏一位1是为了增加一位有效位),因此尾数的实际大小为
基数为2,因此浮点数真值
类型 | 数符 | 阶码 | 尾数 | 总位数 | 阶码偏置值(十进制) |
---|---|---|---|---|---|
短浮点数 | 1 | 8 | 23 | 32 | 127 |
长浮点数 | 1 | 11 | 52 | 64 | 1023 |
临时浮点数 | 1 | 15 | 64 | 80 | 16383 |
1 关于阶码
- 阶码的偏置值。阶码部分用移码表示,假设阶码为 n 位,则阶码偏置值取 ,因此短浮点数、长浮点数、临时浮点数阶码偏置值为;
- 阶码的取值范围。假设阶码为 n 位,则可表示的范围为 ,,因此短浮点数、长浮点数的阶码取值范围为 0到255、0到2047。又规定当阶码全0时用来表示非规格化数,阶码全1时用来表示无穷大,所以阶码E的实际取值范围为 1到254、1到2046;
- 阶码的实际大小。阶码采用移码的形式表示,阶码的实际大小需要减去对应的偏置值,通过这种方式来表示阶码的正负值。所以短浮点数、长浮点数的阶码实际大小为 ,即
2.关于尾数
假设尾数位数为 m 位,因为尾数部分隐含了一位整数1,所以尾数的实际位数为 m+1 位,因此因此短浮点数、长浮点数、临时浮点数、临时浮点数尾数实际有效位数为24、53、65位,真值为
因此,规格化短浮点数的真值为
规格化长浮点数的真值为
2.2 规格化浮点数的取值范围
以短浮点正数为例:
当阶码和尾数都取最小时(E=1,M=0),表示的数值最小,阶码部分为 ,尾数部分为 隐含的1加上其余的23位0;
当阶码和尾数都取最大时(E全1,M全1),表示的数值最大,阶码部分为 ,尾数部分为 隐含的1加上其余的23位1;
所以取值范围为 ,即
格式 | 正数 | 负数 |
---|---|---|
单精度 | ||
双精度 |
2.3 类型转换时的精度损失和溢出
这里以C语言为例。C语言中的float、double型分别对应IEEE 754标准的单精度和双精度浮点数,一个int型数据占4个字节、float占4字节、double占8字节。
1 溢出
- 当float、double向int转换时可能会发生溢出,比如有符号int型表示的数据范围为 ,而float、double类型的数据的表示范围超过了int类型
- 当double向float、int转换时可能会发生溢出
2.精度损失
-
当int向float转换时可能会发生溢出,因为int类型共四字节32位,而float尾数的有效位数为24位,当int型数据的有效位数超过24的话就会发生精度损失。比如
因为 m 的尾数部分共31位1,超过了float的23位(不含隐藏的一位1),超出的1会被舍掉,所以就会产生精度损失 -
当double向float、int转换时可能会有精度损失,因为double类型尾数的有效位数位53,超过了float的24;而且浮点数向整数转换时,若是小数部分不为0,一定会有精度损失,因为整数没有小数部分