1. Question & Analysis
- Question: 最近在牛客网上刷题练手,遇到这样一道题:依次输入一个学生的学号,以及3科(C语言,数学,英语)成绩,在屏幕上输出该学生的学号,3科成绩(注:输出成绩时需进行四舍五入且保留2位小数)。数据范围:学号满足1≤n≤20000000 ,各科成绩使用百分制,且不可能出现负数 。
- Analysis: 我个人觉得,根据题目已知条件,我觉得代码中应该要有判断非法输入的条件语句(这里不符合条件的输入均认为非法输入!走这里就不专门加限制非法输入的条件了,因为这里想要讲的是浮点型数据的四舍五入格式化输出问题)。这里难点就是要搞懂浮点数四舍五入的规则。
2. Code Module
case1: 对 float 类型来说: 可以借助 printf("%.nf", goal_number) 自动四舍五入保留小数点后 n 位小数;
#include <stdio.h>
int main(int agrc, const char* agrv[]) {
int id;
float c, math, english;
scanf("%d;%f,%f,%f", &id, &c, &math, &english);
printf("The each subject score of No. %d is %.2f, %.2f, %.2f.\n", id, c, math, english);
return 0;
}
case2: 对 double 类型来说,printf("%.nlf", goal_number) 自动四舍五入的规则不明确,感觉有点随机性,我现在还没有弄明白原因!<此处求助一波各位路过的大神帮忙指导或者解释一下> Bug如下:
#include <stdio.h>
int main(int agrc, const char* agrv[]) {
int id;
double c, math, english;
scanf("%d;%lf,%lf,%lf", &id, &c, &math, &english);
printf("The each subject score of No. %d is %.2lf, %.2lf, %.2lf.\n", id, c, math, english);
return 0;
}
case3: 据说这是通用版的 四舍五入格式化输出浮点数 方法,自己测试过,能用,但不一定是完美的。上代码看看吧 假设目标操作数 a = 3.141592654; 如果需要 四舍五入 保留 n 位小数,那么就 (int)(a * 10的 n 次方 + 0.5)/ (10 的 n 次方 * 1.0) , (eg: 保留四位小数输出 a , printf("%.4lf\n", (int)(a * 10000.0 + 0.5) / 10000.0) ).
#include <stdio.h>
int main(int agrc, const char* agrv[]) {
int id;
double c, math, english;
scanf("%d;%lf,%lf,%lf", &id, &c, &math, &english);
// 这里备注说明一下,正数则+0.5,负数则-0.5;
c = (int)(c * 100.0 + 0.5) / 100.0;
math = (int)(math * 100.0 + 0.5) / 100.0;
english = (int)(english * 100.0 + 0.5) / 100.0;
printf("The each subject score of No. %d is %.2lf, %.2lf, %.2lf.\n", id, c, math, english);
return 0;
}
3. Summary
虽然,这些都是很弱智的低级问题,但是不弄明白的话,以后用到了,肯定会出Bug的。我始终坚信,Bug都是细节问题演化来的。继续要加油呀!好多天没发贴了。不过并不代表没有学习。发帖其实也蛮费时间的,毕竟要组织语言,排版之类的,哈哈哈(虽然我的帖子也很简化)。发帖就是记录自己的学习和遇到的问题,当然,如果能够得到各路大神的指点,那就是我赚到了,荣幸之至!
找了半天,似乎标准库没有规定舍入的方法,只保证了位数
不过我今天刚好看了IEEE 754的舍入标准,一般使用向偶数舍入的方法,我想你用的编译器就是采用这种方法的,正好对的上,80.555->80.56,90.845->90.84,看和你要保留的最后一位的距离,这样保证了落到两边的概率是50%,在计算概率论的一些东西的时候不会有很大的误差
然后我也在微软的文档找到了相应的说明,printf、_printf_l、wprintf、_wprintf_l | Microsoft Docs
这就更印证了我认为的没有舍入标准的说法,实际上你要注意有些东西不能先入为主,四舍五入是我们生活中惯用的舍入方法,程序里也不一定表现为四设五入,不过好在你的求知欲帮你“矫正”了