浮点数表示——2(小班讨论3)

问题描述:

选题 4:在 C 中,如下代码:
float e = 1.1110999f;
printf(“1.1110999f 打印真实为:%f” , e);
会输出:1.1110999f 打印真实为:1.1111
深入分析其原因,并给出判断一个浮点数是否能精确表示的思路。

一.分析原因:

1首先我们对数据进行规格化:

(1) 对于数据e = 1.1110999f,我们先将其转化为数学形式:1.1110999*10^0
(2) 然后符号位S=0
(3) 阶码值esp=0+127=01111111
(4) 尾数为0.1110999转化为二进制:
0.0001110001110001000010110000010100010110110000000011011
由于float的frac只有23位,所以我们要对frac值做一个四舍五入(不是向偶数舍入):
Frac=00011100011100010000101——> 00011100011100010000110
(5) 最终的表示结果:
00111111 10001110 00111000 10000110
我们用图来表示这个过程:
浮点数表示——2(小班讨论3)_第1张图片

2.printf函数打印:

printf("%f" , e)没有指定输出保留多少位,默认是保留6位小数,而浮点数可以表示e为

保留6位小数后,四舍五入输出结果为1.111000。

浮点数表示——2(小班讨论3)_第2张图片

验证我们的观点:

上述观点是否正确?我们可以上机运行,查看变量e在内存中的值,我们还可以打印16位观察数据是否准确
(1) 调试程序,运行结果查看e在内存中的值
浮点数表示——2(小班讨论3)_第3张图片
可以发现存储方式和规格化值一致

(2) 修改程序,打印16位
浮点数表示——2(小班讨论3)_第4张图片
浮点数表示——2(小班讨论3)_第5张图片
可以看到,输出16位的结果和我们预测的结果一致,由此证明我们的结论正确。

二.判断一个浮点数是否能精确表示的思路

一个浮点数内否被精确表示这需要从规格化的原理来寻找答案,我们可以从如下几个角度来判断是否能被精确表示:

我们假设一个浮点数由m+n+1表示:
在这里插入图片描述
计算出bits=2^(k-1)-1

(1) 首先是范围:

这样一个浮点数的表示范围是-(2-(1/2)^n)*2^bits~+(2-(1/2)^n)*2^bits
如果数据不再这个范围内,那么不用考虑,他一定不能被精确表示

(2) 规格化数和非规格化数:

对于可以被表示的数据,我们要进行计算,观察表示后的数据截取frac的n位后是否发生了舍入,如果不发生说明该数据可以被精确表示,否则不能被精确表示,例如:

以单精度浮点数为例:

单精度Float e=1.1110999
计算frac尾数0001110001110001000010110000010100010110110000000011011
由于单精度只有23的frac位,所以要发生位舍入(截取),所以不能被精确表示

单精度float F= 0.002838134765625,我们将其表示为二进制存储的形式时
符号位:s=0
阶码值Exp=00000000
frac=00000000 10111010 0000000……没有发生位的截取,所以说F可以被精确表示。

总结:

总结:

  • printf("%f" , e)没有指定输出保留多少位,默认是保留6位小数
  • 浮点数的表示范围是-(2-(1/2)^n)*2^bits~+(2-(1/2)^n)*2^bits
  • frac的n位后是否发生了舍入,如果不发生说明该数据可以被精确表示,否则不能被精确表示
  • 最小的非规格化数:2^(-n)*2^(-bits+1)
  • 最大的非规格化数:(1-(1/2)^n)*2^(-bits+1)
  • 最小的规格化数:2^(-bits+1)
  • 最大的规格化数: (2-(1/2)^n)*2^bits

你可能感兴趣的:(计算机系统)