题目描述
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整 数。
输入描述
输入的第一行包含一个整数 n ,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
输出描述
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分四舍五入保留整数。
算法描述
得到及格率与优秀率并不难,我们首先在输入成绩时统计对应的及格和优秀人数,然后将其分别除以总人数 n即可,关键在于最后的四舍五入。
一开始我自己是想到直接对结果强制类型转换成 int,但是调试的结果并不正确。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, ans1, ans2;
double jige, youxiu, score;
cin >> n;
for(int i = 0; i < n; i++){
cin >> score;
if(score >= 60){
jige++;
if(score >= 85){
youxiu++;
}
}
}
ans1 = (int)(jige / n * 100);
ans2 = (int)(youxiu / n * 100);
cout << fixed << setprecision(4);
cout << endl << youxiu / n * 100 << endl << ans2;
//cout << ans1 << endl << ans2;
}
下面是代码调试的一组输入输出
6
10 60 85 90 95 100
66.6667
66
可以看到对于优秀率66.67% ,使用强制类型转换后,结果变成了66%,但是四舍五入后正确结果应该是67%,这说明强制类型转换并不会自动四舍五入,而是直接舍弃掉小数部分。
那么,怎么样进行四舍五入呢?
其实,C++的STL库中有提供四舍五入的round()函数,我们将上述代码的四舍五入部分改成如下
ans1 = round(jige / n * 100);
ans2 = round(youxiu / n * 100);
再重新对之前的输入进行测试可得到
6
10 60 85 90 95 100
66.6667
67
这一次round()函数成功帮我们进行了四舍五入的操作,那么,我又会想round()函数也是被别人写出来的,那么他是怎么实现round()函数的四舍五入功能呢?
其实,并不难,我们只要把握四舍五入的原则就可以自己实现round()函数。
ans1 = (int)(jige / n * 100 + 0.5);
ans2 = (int)(youxiu / n * 100 + 0.5);
我们将结果先加上0.5,若其小数部分够五入,那么加上0.5后会进1,反之则不会,然后再对处理后的结果进行强制类型转换就实现了四舍五入的功能啦,是不是非常简单@~@。
在上述代码中,我们使用了fixed和setprecision(n)实现了控制浮点数小数部分的有效位数,那么如果让我们自己实现控制有效位数呢?
比如,题目要求百分数精确到小数点后两位,并且要求四舍五入。
如果理解了上面的round 函数的原理,其实要实现这个要求并不难,只要稍微变通一下@~@。
比如之前的优秀率为66.6667,我们想要保留小数点后两位,并且要四舍五入,那么,我们先把结果乘上100,得到6666.67,此时是不是就变成了四舍五入取整的问题了!然后就是加上0.5,再强制类型转换的套路啦,就得到了6667的整型数,那么如何把结果转换回去呢,我们会想到再除以100可以了,但是两个整型数相除,结果一定还是整型,也就是说,int 6667 / int 100得到的结果会是 int 66,没错,在除法的过程中,结果自动强制类型转换了,那么怎么办呢?很简单,除以浮点数就可以了,整型与浮点型的运算结果会是浮点型,所以只要除以100.0就可以了,如下所示。
ans2 = (int)(youxiu / n * 100 * 100 + 0.5) / 100.0;
同理,我们可以得到小数点后有效N位的结果,只要将其乘上10的N次方,转换为四舍五入取整问题,然后再将结果除以10的N次方对应的浮点数就可以啦@~@