☰
PTA习题2-1求整数均值:从整数除法和格式化输出到OJ满分
2026/10/10 7:55:05 网站建设 项目流程

PTA 习题2-1 求整数均值,可能是很多同学大学阶段在OJ平台上遇到的第一道真正需要琢磨的题。题目本身一句话就能读完:输入四个整数,输出它们的和与平均值,平均值保留一位小数。但它背后藏着的考点,比表面看起来多得多。我的经验是,这道题表面是“入门送分题”,实际上至少埋了三个隐蔽的坑:整数除法的截断、格式化输出的精确控制、以及提交代码时的“多余内容”问题。每年都能看到一批同学因为这几个小坑反复提交拿不到全分。

这篇文章不打算只贴一份答案,而是把这道题从题目拆解、原理剖析、多语言实现,到常见错误排查和扩展思路,完整过一遍。不管你是刚学C语言的新手,还是带新生的助教,或者是刷题准备考试的自学者,都能从中找到值得带走的东西。读完你不仅能拿到满分,还能彻底搞懂为什么平均值的写法必须是sum / 4.0而不是sum / 4,以及以后遇到类似“保留N位小数”的题目时,怎么一次就写对。

1. 题目到底在考什么?从需求拆解到核心考点

1.1 需求逐行拆解:输入、计算、输出

先原原本本看题目要求:输入在一行中给出4个整数,其间以空格分隔。计算这4个整数的和与平均值,在一行中按照格式“Sum = 和; Average = 平均值”输出,其中平均值精确到小数点后一位。

拆成三个动作就是:读入、求和、格式化输出。读入动作需要4个变量,求和就是一个简单的+运算,输出是关键。有些同学觉得这题太简单,直接在 main 里三行代码写完交上去,结果被判格式错误,又找半天找不到原因。原因就在输出格式上:Sum = 和; Average = 平均值,等号两边有空格,分号后面也有空格,Average首字母是大写,平均值要保留一位小数。任何一个细节差一点,OJ的比对程序都会判定结果错误。

1.2 躲不开的整数除法陷阱

这是这道题最大的考点,也是很多同学第一次意识到 C 语言的“整数除法”和数学里的除法不是一回事。

两个整数相除,如果操作数都是整数,C 语言执行的是整除运算,结果直接舍弃小数部分。比如10 / 4得到 2,而不是 2.5。哪怕你写double average = 10 / 4;,也救不回来——因为10 / 4这个表达式在赋值之前就已经被算成了整数 2,然后才转成 double 类型的 2.0。

正确写法是用浮点数参与运算。常见做法有两种:把除数写成浮点数sum / 4.0,或者做一次强转(double)sum / 4。这两种都能让编译器把sum提升为 double 后再除,得到正确的小数结果。从可读性角度我更喜欢sum / 4.0,因为字面上就能看出来“这里不是整除,是要保留小数的精确除法”。

1.3 输出格式里的“隐藏扣分点”

保留一位小数,在 printf 里就是格式控制符%.1f。这里的.1指小数点后显示 1 位数字,不是总共 1 位数字,也不是有效数字 1 位。很多同学第一次写会写成%f,结果输出 2.500000 或者 3.000000,和答案对不上;也有的写成%d想输出 double 类型,直接乱码。

还有一个细节:sum 是整数,用%d输出没问题;average 是浮点数,用%.1f输出。两个格式控制符必须和变量的类型一一对应,顺序错了、个数少了都不行。在 C 语言里,printf 并不会检查你的格式控制符和变量是否匹配,写错了它照样编译通过,运行出来就是垃圾值,这种错误特别难排查,因为你盯着代码看半天,语法完全没问题。

所以这道题从考点角度可以总结为:变量类型的正确选择、整数除法和浮点数除法的区别、printf 格式控制符的精确使用。三个点都是后续学习里高频复用的基础。

2. 多语言实现:给出一份可以直接提交的参考代码

2.1 C语言参考实现与关键点注释

先给出最标准、最贴合 PTA 老式 C 语言评测环境的代码。如果你用的是 C(gcc),下面这份直接提交就能过。

#include <stdio.h> int main() { int a, b, c, d; scanf("%d %d %d %d", &a, &b, &c, &d); int sum = a + b + c + d; double average = sum / 4.0; printf("Sum = %d; Average = %.1f\n", sum, average); return 0; }

注意printf里的写法:"Sum = %d; Average = %.1f\n"。这里的空格分别在Sum后面一个、等号后面一个、分号后面一个、Average后面一个。别小看这些空格,OJ 是全字比对,少一个空格输出结果就是 Wrong Answer。换行符\n也可以带,评测时多一个换行通常不影响,但带上更规范。

2.2 C++实现:注意流式输出的精度控制

C++ 里用cin和cout实现更简洁,但保留一位小数的写法需要额外处理。

#include <iostream> #include <iomanip> using namespace std; int main() { int a, b, c, d; cin >> a >> b >> c >> d; int sum = a + b + c + d; double average = sum / 4.0; cout << "Sum = " << sum << "; Average = " << fixed << setprecision(1) << average << endl; return 0; }

这里的关键是fixed << setprecision(1)。setprecision本身控制的是有效数字位数,不加fixed时,2.5会输出成2.5没问题,但100.0可能输出成1e+02这种科学计数法,OJ 里直接判错。加上fixed后表示小数点后固定保留 1 位,输出100.0,这才是题目要求的意思。这个知识点在后面的编程题里会反复用到,建议一次记住。

2.3 Python实现:用最少的代码完成需求

如果题目允许用 Python 提交,写起来更短,但格式化输出依然不能大意。

a, b, c, d = map(int, input().split()) total = a + b + c + d print(f"Sum = {total}; Average = {total / 4:.1f}")

Python 的整数除法是//,单个/得到的是浮点数,所以直接total / 4就是精确除法。f-string 里的:.1f同样表示保留一位小数。这里的 input 一次读一行,题目输入正好在一行里,所以写起来很干净。如果格式不对,多半是 f-string 内部的冒号和点号没写对,建议先在本地试几个用例,确认输出和题目样例一致再提交。

2.4 Java实现:面向OJ提交的细节

Java 提交时类名必须叫 Main,入口方法写成public static void main,这个细节能卡掉一多半第一次用 Java 刷题的人。

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int b = sc.nextInt(); int c = sc.nextInt(); int d = sc.nextInt(); int sum = a + b + c + d; double average = sum / 4.0; System.out.printf("Sum = %d; Average = %.1f%n", sum, average); } }

System.out.printf和 C 的 printf 几乎一样,%n是跨平台的换行符。在 Java 里,sum / 4.0同样会自动把 int 提升为 double,所以不会丢精度。这里唯一的提交陷阱是类名大小写:必须public class Main,文件里其他修饰都别乱加。

3. 实测中的常见错误与排查实录

3.1 平均数整个变成整数

这是我在给新生讲这道题时最常看到的问题。学生写完代码,输入1 2 3 4,输出Average = 2.0,怎么想都觉得不对:平均数明明是 2.5 啊,为什么输出 2.0?

原因百分之百出在sum / 4这行。两个整数相除,得到整数 2,再存进 double 变量变成 2.0。修改方法就是我在前面强调的:除数写成4.0,或者强转(double)sum / 4。这一处修改,味道完全不一样了:前者从字面上告诉读者“我要做浮点除法”,后者是显式类型转换的经典用法。我建议新手先习惯4.0写法,因为绝大多数场景下它比强转更直观,也不容易漏括号。

3.2 输出格式与样例差一个空格

另一个高频问题不是算错,而是输出的字符串和题目要求不严格一致。比如有人写成"Sum=%d; Average=%.1f\n",等号两边少了空格;有人写成"Sum = %d ; Average = %.1f\n",分号前面多了空格;还有人把 Average 首字母小写成 average。

在本地运行怎么都对,提交到 OJ 上就是 Presentation Error 或 Wrong Answer。这类问题唯一的可靠解法就是眼睛死死盯着题目的输出样例,把这行格式当成一个整体去复刻。有一个训练习惯值得养成:第一次读题时,就把输出要求的字符串原样写在草稿纸或者注释里,写代码时对照着抄,不要凭记忆打。因为“看起来差不多”和“完全一致”之间,隔着一个评测机。

3.3 多余的提示信息

我见过有同学为了“友好交互”,在 scanf 之前加了一句printf("请输入四个整数:\n");。在本地跑没问题,人看了觉得很贴心,但 OJ 是全量比对输出内容,它期望的第一行就是Sum = ...,你前面突然多出来一行“请输入”,整个输出全对不上,直接判错。

在线评测系统不是聊天机器人,它不关心你的程序是否友好,只关心输出和期望是否完全匹配。所以刷题提交的那份代码里,一律不要写任何提示输入、欢迎语、分隔线之类的输出。平时自己练习当然可以加提示,真正提交前记得删干净。

3.4 一个更隐蔽的坑:scanf 里的格式

scanf("%d %d %d %d", &a, &b, &c, &d)这行也有讲究。新手最容易漏的是变量前的取地址符&,一旦漏掉,程序运行时会直接把读进来的整数当内存地址往里写,轻则值不对,重则段错误崩溃。

还有一种写法问题,比如写成scanf("%d,%d,%d,%d", &a, &b, &c, &d);,这表示输入时必须带逗号,比如1,2,3,4。但题目说“以空格分隔”,所以格式串里必须是空格而不是逗号。看起来都是分隔符号,评测数据不会陪你变,它按题目要求的格式给,你按题目不匹配的格式等,整行输入就读不进去。

3.5 错误排查的通用方法论

很多同学本地跑不出问题、提交就是错,就慌。这里分享一个通用的排查顺序,适用于所有类似的基础题:

第一,拿题目给的样例输入跑一遍,看输出是否一模一样。第二,自己再构造几组边界数据,比如全负数、全零、全部相同、既有大正数又有大负数。第三,对照题目里的输出格式说明,用眼睛检查每个字符。第四,把代码里的输出部分单独拎出来读一遍,确认没有多余输出。

这个方法能解决90%的入门题提交失败问题,建议刻进肌肉记忆。

4. 从这道题延伸出去的思考与技术储备

4.1 从4个数到n个数:结构如何升级

题目要求固定4个数,所以开4个变量直接读入。但现实中更常见的场景是“第一行给一个 n,接下来读 n 个整数,求平均值”。这种结构也很基础,值得提前会写。

#include <stdio.h> int main() { int n, x; scanf("%d", &n); int sum = 0; for (int i = 0; i < n; i++) { scanf("%d", &x); sum += x; } double average = sum / (double)n; printf("Sum = %d; Average = %.1f\n", sum, average); return 0; }

这段代码把“固定4个数”升级成了“任意个数”,核心点有两个:一是sum要初始化成 0,否则它是个随机值;二是除数变成了 n,强转(double)n来避免整数除法。循环读入是后续所有算法题的基本功,能和这道均值题无缝衔接。

4.2 数据范围的长远问题:从 int 到 long long

题目里说输入和输出都在整型范围内,所以用 int 是安全的。但如果你拿这道题练手时,把四个数都换成很大的数,比如四个都是 20 亿,sum 就是 80 亿,妥妥超出 int 能表达的范围(约 21 亿多)。这时候输出会变成负数,完全无法理解。

遇到不确定范围的情况,直接用long long更安心。C 语言里对应 read 是%lld,printf 是%lld:

long long a, b, c, d; scanf("%lld %lld %lld %lld", &a, &b, &c, &d); long long sum = a + b + c + d; double average = sum / 4.0; printf("Sum = %lld; Average = %.1f\n", sum, average);

虽然这道题不需要这么谨慎,但从第一次写代码开始就养成“看数据范围定数据类型”的习惯,后面会省很多事。刷题时永远记住一句话:int 不是默认正确答案,它只是一个 32 位整数类型,超过 21 亿就会爆。

4.3 浮点数输出到底有没有四舍五入?

printf("%.1f", 2.45)得到的是 2.5 还是 2.4,这个问题偶尔会跳出来吓人一下。实际上,C 语言的 printf 在输出浮点数时,会根据当前舍入模式(通常是舍入到最近偶数)对显示位数的后一位进行取舍。个别边界值会因为二进制浮点数表示不完全精确而出现“看起来没按四舍五入”的现象。

但在这道均值题里,四个整数之和除以 4,结果的小数部分只有 0、0.25、0.5、0.75 这四种情况,显示一位小数时分别对应 .0、.3、.5、.8 或者 .2、.2(取决于具体数值)。这些小数在二进制里都能精确表示,所以不会出现精度意外。我的建议是:这种入门题放心用%.1f,不用为浮点数误差焦虑。等将来做浮点数高精度计算时,再专门研究舍入策略也不迟。

4.4 自查清单:提交前用这几个用例过一遍

我每次给学生演示这题,都会让他们准备一张“自测用例表”,把常见情况覆盖全。这里整理一份可以直接用的:

输入预期输出检查点
1 2 3 4Sum = 10; Average = 2.5平均值是 .5,非整数
12 3 4 -5Sum = 14; Average = 3.5正负数混合
5 5 5 5Sum = 20; Average = 5.0平均值为整数,也要显示 .0
0 0 0 0Sum = 0; Average = 0.0全零场景
-1 -2 -3 -4Sum = -10; Average = -2.5全负数场景

拿这5组数据本地跑一通,如果全部和预期一致,大概率提交就过了。特别提醒第三行:平均值是整数时,也要输出5.0而不是5,这是%.1f自动补出来的效果,考前最容易忽略。

5. 一些教学过程中的体会

这道题我前前后后看不同的同学写过很多遍,每一遍都能看到新的错误姿势。有个 A 同学让我印象很深:他的计算完全正确,输出格式就是多了个分号前的空格,自己盯着看十分钟看不出来,拿去问别人一眼就发现。这类问题不是细心不细心的问题,而是没有形成“用眼睛逐字符检查输出”的习惯。后来我让他在本地写完代码后,把输出抄一遍到注释里,和题目要求并排对比,才慢慢改掉这个毛病。

我个人建议,如果你刚开始刷题,可以把这道题当成基准题,立下一个规矩:不看任何参考代码,从读题开始自己写,写完用自查用例跑通,再故意写错两个版本(比如sum / 4和漏空格)看看报错长什么样。这个流程走完一遍,你对变量类型、格式化输出、OJ 判题规则的理解都会上一个大台阶。以后遇到的第一道真难题,往往不是算法本身难,而是这些基本功不够扎实,错误定位找不到方向。

顺带说一句,这道题的后续可以玩的花样真不少。比如把四个数改成五个数、十个数,或者要求平均值保留两位小数,甚至让我们自己从键盘读入一个n再读n个数。核心逻辑都一样,只是输入处理和输出格式微调。所以把这一道题吃透,等于把一类“整数求和求均值”的题目全部吃透了。下次再在 OJ 上看到类似题,应该闭着眼睛都能写出来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询