HIT-ICS Lab1题目 程序运行分析:浮点数的坑

问题描述

注:本题目来自2022春HIT-ICS Lab1 程序运行分析(2)浮点数的坑
感觉自己还是用心写了滴,供大家参考~如有不对欢迎指正

给定一段代码:

int main(){
    
    
	float f;
	for(;;){
    
    
		printf("请输入一个浮点数:");
		scanf("%f", &f);
		printf("这个浮点数的值是:%f\n",f);
		if (f==0) break;
	}
	return 0;
}

运行输入:
61.419997
61.419998
61.419999
61.420000
61.420001
0

运行输入:
10.186810
10.186811
10.186812
10.186813
10.186814
10.186815
0

请运行程序,并分析程序为什么是这样的执行结果?
程序中浮点数比较、汇总统计等应注意什么呢?

运行结果

运行结果1
运行结果2

现象分析

仅供参考~如有不对欢迎指正

原因:

  1. 浮点数在计算机中的存储(以单精度为例)是1位符号位、8位阶码、23位尾数组成;

    扫描二维码关注公众号,回复: 16649902 查看本文章
  2. 因为尾数只有23位,而部分十进制小数只能转换成无穷为二进制小数,只能通过截取二进制数满足存储要求,此时涉及到截取后是否舍入的问题;

  3. 通常采用“向偶数进位的方法”来决定截取后是否舍入;

  4. 计算机对浮点数61.419997、61.419998、61.419999、61.420000、61.420001按照上述规则进行截断、进位处理后存储在计算机中;这些浮点数二进制表示的符号位和阶码都一样,这里仅展示尾数,如下图所示。可以看到,61.419997、61.419998、61.419999、61.420000的截断后的尾数一样(处于上方的红框),而61.420001与61.420002的尾数一样(处于下方的红框);
    图1

  5. 所以61.419997、61.419998、61.419999、61.420000在计算机中的二进制表示一样,61.420001与61.420002的二进制表示一样;

  6. C语言的printf在打印%f格式的数字时,首先将二进制浮点数表示转换为十进制,然后对求得的十进制数字保留小数点后6位,查阅资料得知决定此时是否舍入的依据是四舍五入,而头4个浮点数的二进制表示转换为十进制后,为61.41999816894531,保留6位小数后为61.419998,而61.420001与61.420002的二进制表示转换为十进制后,为61.42000198364258,保留6位小数后为61.420002,与打印出来的结果一致;

  7. 至于右边的数字(10.18681x)为何能正常显示不出错,其道理同上,这些浮点数的二进制表示的尾数见下图,可以看到尾数各异,而恰好转为十进制并截取小数位时,与原来的结果一样,因而可以正常显示不出错。
    图2

猜你喜欢

转载自blog.csdn.net/weixin_52027058/article/details/125727962
今日推荐