[洛谷 3954][NOIP2017普及组]成绩

题目链接

https://www.luogu.org/problem/P3954

题解

其实作为第一题而言,这题基本没有难度,不过有个坑的地方,就是浮点误差,光这个问题,就足够我们讨论上一番了。

何谓浮点误差?就是浮点数运算产生的误差。例如本来结果应该是 \(1\),结果变成了 \(0.9999999\)。

接下来的两个程序,其实都是正确(官方评测的时候如此)的,但第一个产生了浮点误差问题,不算完美。

程序1:

#include <stdio.h>
int a,b,c,score;
int main()
{
 scanf("%d%d%d",&a,&b,&c);
 score=a*0.2+b*0.3+c*0.5;
 printf("%d",score);
 return 0;
}

如果程序是这样的话,那么样例 \(2\) 输出的结果会是 \(78\),而不是 \(79\)。

这里就是浮点误差的产物了,事实上,\(score=78.9999 \ldots \),虽然这里没有显示出来,但计算机内部存储的就是这个数,由于浮点数转整数时要截尾(就是舍弃小数点后面的数字),于是结果就是 \(78\) 了。

不过有一种方法可以避免这样的 bug 。

程序2:

#include <stdio.h>
int a,b,c,score;
int main()
{
 scanf("%d%d%d",&a,&b,&c);
 score=a/5+b/10*3+c/2;
 printf("%d",score);
 fclose(stdin);
 fclose(stdout);
 return 0;
}

这里由于采用了整数运算(别忘了 \(a,b,c \) 都是 \(10\) 的整数倍),避开了浮点误差,这时候程序就能正确输出了。

不过,写了程序 \(1\) 也不存在问题,至少今年是这样的。最终本题进行了重测,消除了浮点误差的影响。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据