本文介绍如何使用arraylist动态存储用户多次输入的成绩计算结果,并对其进行求和,解决初学者在qpi(质量点指数)计算项目中无法保存多科成绩值的问题。
本文介绍如何使用arraylist动态存储用户多次输入的成绩计算结果,并对其进行求和,解决初学者在qpi(质量点指数)计算项目中无法保存多科成绩值的问题。
在你的QPI计算程序中,当前逻辑存在一个关键问题:每次循环中重新赋值 newgrade = total * grade,导致只有最后一次输入的结果被保留,之前的计算值全部丢失。因此,当最后执行 qpi = newgrade / total 时,实际只用了最后一门课的数据,无法正确计算整体QPI(即:∑(gradeᵢ × unitsᵢ) / ∑unitsᵢ)。
要真正实现“收集所有科目成绩乘以学分的结果并求和”,你需要一个可动态扩容的容器来持续保存每次计算出的 newgrade 值。Java 中最合适的工具是 ArrayList<Integer> ——它无需预先声明长度,支持随时添加元素。
以下是优化后的核心实现步骤(已整合进完整可运行代码):
✅ 第一步:声明 ArrayList 存储每科的加权分(grade × units)
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
import java.util.ArrayList;
import java.util.Scanner;
public class QPI {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Integer> weightedGrades = new ArrayList<>(); // ✅ 动态存储每科 newgrade
int totalUnits = 0; // ✅ 同时累计总学分(用于最终QPI分母)✅ 第二步:在循环中持续 add() 而非覆盖变量
System.out.println("Enter your quality point equivalent for each subject:");
double grade = scanner.nextDouble(); // ⚠️ 注意:grade 应为 double(含3.5等小数)
// 成绩等级映射(建议用 switch 或 Map 优化,此处简化保留 if)
if (grade == 4.0) System.out.println("A");
else if (grade == 3.5) System.out.println("B+");
else if (grade == 3.0) System.out.println("B");
else if (grade == 2.5) System.out.println("C+");
else if (grade == 2.0) System.out.println("C");
else if (grade == 1.0) System.out.println("D");
else if (grade == 0.0) System.out.println("F");
System.out.println("Enter your total units for this subject:");
int units = scanner.nextInt();
int weightedGrade = (int) Math.round(grade * units); // 四舍五入取整(QPI常用处理)
weightedGrades.add(weightedGrade); // ✅ 添加到列表,而非覆盖
totalUnits += units; // ✅ 累计总学分✅ 第三步:循环收集,直到用户选择计算
int response;
do {
System.out.println("Type 1 to add another subject, or 2 to calculate QPI:");
response = scanner.nextInt();
if (response == 1) {
System.out.println("Enter quality point equivalent:");
grade = scanner.nextDouble();
// (同上等级输出逻辑...略)
System.out.println("Enter units:");
units = scanner.nextInt();
weightedGrades.add((int) Math.round(grade * units));
totalUnits += units;
}
} while (response != 2);✅ 第四步:安全求和并计算QPI(需处理除零)
if (totalUnits == 0) {
System.out.println("Error: Total units cannot be zero.");
return;
}
// 方法1:传统for循环求和(清晰易懂,推荐初学者)
int sumWeightedGrades = 0;
for (int wg : weightedGrades) {
sumWeightedGrades += wg;
}
// 方法2:使用Stream(Java 8+,简洁但需理解)
// int sumWeightedGrades = weightedGrades.stream().mapToInt(Integer::intValue).sum();
double qpi = (double) sumWeightedGrades / totalUnits;
System.out.printf("Your QPI is: %.2f%n", qpi); // 保留两位小数更专业
}
}? 关键注意事项:
- grade 必须声明为 double(或 float),否则 3.5 会被截断为 3;
- 使用 else if 替代独立 if,避免无效判断(如输入3.5时不会误触发 grade == 3);
- weightedGrades 存储的是整型加权分,若需更高精度(如保留小数),可改用 ArrayList<Double>;
- 最终QPI是加权平均值,分母是总学分(totalUnits),不是单科 units —— 原代码中 qpi = newgrade/total 是严重逻辑错误;
- 始终校验 totalUnits != 0,防止运行时除零异常。
通过以上改造,你的程序就能真正实现“输入多门课 → 自动存储每科加权分 → 求和 → 计算QPI”的完整流程,既符合学术要求,也体现了良好的编程实践。

















