第1关:学生成绩信息处理
任务描述
编写程序:该程序用于根据Java面向对象程序设计这门课程的成绩评定规则,完成对学生最终成绩的评定。 最终成绩=平时成绩×30%+实验成绩×30%+期末考试×40% 平时成绩、实验成绩、期末考试都按百分制给出,使用单精度型。
相关知识
Java语言基础、类与对象。
如何运用面向对象编程的思想进行问题求解
面向对象编程思想的运用体现在,在求解问题之初,首先,要针对待解决的问题,从以下几个方面展开思考: (1)待求解的问题涉及到哪几类对象? (2)这些不同类别的对象有哪些属性和行为? (3)这些对象之间有什么联系。 例如,这一关卡所要求解的问题,结合实际情境,可以对上述几个问题提供如下解答: (1)涉及到学生对象、输入信息者(这里假设为老师(Teacher)) (2)这里涉及到的学生对象的属性有“学号”、“姓名”、“平时成绩”、“实验成绩”、“期末考试”,该对象应该具有输出自我信息的行为,该对象应该能根据计算规则,自动算出当前的总评成绩及其等级。 这里涉及到的Teacher类应该能提供输入学生信息的功能(行为)。 (3)教师通过输入把信息存储到学生对象中,于是就和学生产生了依赖关系。 得到了上述分析结果后,我们便可以通过归纳,提炼出如下类: Student Teacher 他们的数据成员和方法成员进而都可以根据任务要求设计出来,这已经体现在 主类对应上面这两个类的使用上。 可见,面向对象编程强调行为的执行者(即类的对象),每一个行为的发生,都是某个类或这个类的对象通过方法调用产生的。而面向过程编程,则只关注行为(功能),在复杂问题的求解中,往往不容易进行抽象思考,而人类最善于抽象思考。面对一个问题,首先想到的里面都有谁?他们的状态和行为如何? 试想一下,如果这个程序用C语言编写,你又是如何思考的呢?和这里所提供的思路区别在哪里? 本程序最终源码由三个源文件组成:
- MainClass.java:主类
import java.util.Scanner; public class MainClass { public static Scanner sc=new Scanner(System.in); public static void main(String[] args) { // TODO Auto-generated method stub Student stu=new Student(); //从控制台输入学生信息 Teacher.inputInfo(stu,sc); //根据输入的学生信息进行处理:计算总评成绩及对应等级 stu.updateGrade(); //输出处理后的结果 stu.outputInfo(); sc.close(); } }
- Teacher.java:提供输入学生信息的方法
- Student.java:存储一个学生信息、提供最终成绩的计算、输出结果信息等方法。 这三个文件都可以通过右上角的文件夹图标打开。 在本程序中,为了培养大家用面向对象对象方法进行问题求解,强调必须重视类的设计与实现,为此,给出了MainClass.java的代码,如下: 你必须在读懂上述代码的基础上,完成使主方法能够正常运行的所有类的设计与实现。
编程要求
(1)程序运行时,依次提示输入学号、姓名、平时成绩、实验成绩及期末考试成绩。 (2)要输出最终成绩的计算结果(四舍五入到小数点后2位有效数字)及对应的“A”(>=90)、“B”(>=80 and <90)、“C”(>=70 and <80)、“D”(>=60 and <70)、“E”(<60) (3)你只需要在Teacher.java和Student.java中完成使主类正常运行的类的定义即可。
测试说明
平台会对你编写的代码进行测试,以下是完整的测试结果(下面的标点符号都是英文标点符号)。
学号=1800330101 姓名=刘德华 平时成绩=90 实验成绩=89 期末考试=78.5 刘德华(1800330101)的课程"Java面向对象程序设计"的成绩评定如下: 平时成绩:90.00 实验成绩:89.00 期末考试:78.50 总评:78.50,等级:B
import java.util.Scanner;
//请在下面实现Teacher类的定义。
public class Teacher {
public static void inputInfo(Student stu, Scanner sc){
stu.setStudentNumber(sc.nextDouble());
stu.setName(sc.next());
stu.setUsualGrades(sc.nextDouble());
stu.setExperimentalGrades(sc.nextDouble());
stu.setFinalGrades(sc.nextDouble());
}
}
//请在下面给出Student类的定义。
//请在下面给出Student类的定义。
public class Student {
private double studentNumber;
private String name;
private double usualGrades;
private double experimentalGrades;
private double finalGrades;
private double totalGrades;
char level;
public void setStudentNumber(double studentNumber) {
this.studentNumber = studentNumber;
}
public void setName(String name) {
this.name = name;
}
public void setUsualGrades(double usualGrades) {
this.usualGrades = usualGrades;
}
public void setExperimentalGrades(double experimentalGrades) {
this.experimentalGrades = experimentalGrades;
}
public void setFinalGrades(double finalGrades) {
this.finalGrades = finalGrades;
}
public void updateGrade() {
this.totalGrades = this.usualGrades * 0.3 + this.experimentalGrades * 0.3 + this.finalGrades * 0.4;
int grade = (int) this.totalGrades;
switch (grade / 10) {
case 10:
case 9:
this.level = 'A';
break;
case 8:
this.level = 'B';
break;
case 7:
this.level = 'C';
break;
case 6:
this.level = 'D';
break;
default:
this.level = 'E';
break;
}
}
public void outputInfo() {
System.out.printf("学号=姓名=平时成绩=实验成绩=期末考试=%s(%.0f)的课程\"Java面向对象程序设计\"的成绩评定如下:\n", this.name, this.studentNumber);
System.out.printf("平时成绩:%.2f\n",this.usualGrades);
System.out.printf("实验成绩:%.2f\n",this.experimentalGrades);
System.out.printf("期末考试:%.2f\n",this.finalGrades);
System.out.printf("总评:%.2f,等级:%c",this.totalGrades,this.level);
}
}
第2关:矩阵类的实现
任务描述
矩阵运算是线性代数中的基本运算。请实现一个Matrix类,可以实现矩阵乘法、矩阵的数组乘法、矩阵相加、相减,矩阵转置、矩阵和一个标量的乘积。
相关知识
为了完成本关任务,你需要掌握: 1.构造方法的定义 2.类的数据成员与方法成员。 3.System.out.println(A),假设A是类型为DemoClass(类名)的变量,该代码相当于: String s=A.toString(); System.out.println(s); 因此,你可以在DemoClass中定义一个public String toString()的方法,就可以使 System.out.println(A)输出你想输出的信息。 3.关于矩阵运算,请参考线性代数相关介绍。

编程要求
(1)本程序的主类文件(MainClass.java)中的代码如下:
import java.util.Scanner;
public class MainClass {
public static Scanner sc=new Scanner(System.in);
public static void main(String[] args) {
int rowCount,colCount;
System.out.println("输入矩阵行列数");
rowCount=sc.nextInt();
colCount=sc.nextInt();
//创建1个rowCount×colCount的矩阵,矩阵所有元素初始化为0
Matrix matA=new Matrix(rowCount,colCount);
MainClass.inputMatrix(matA);
System.out.println("矩阵A=\n"+matA);
Matrix matB=new Matrix(rowCount,colCount);
MainClass.inputMatrix(matB);
System.out.println("矩阵B=\n"+matB);
System.out.println("运算结果如下:");
//执行矩阵相加运算
Matrix matC=matA.plus(matB);
System.out.println("C=\n"+matC);
//修改matA的第2行,第2列的那个元素
matA.data[1][1]=89.4;
//执行矩阵与一个数相加的运算,即矩阵的所有元素都加上这个数
Matrix matD=matA.plus(5.6);
System.out.println("D=\n"+matD);
//执行矩阵和1个数相乘,即矩阵的所有元素都乘上这个数
Matrix matF=matA.multiply(3.4);
System.out.println("F=\n"+matF);
//求转置矩阵
Matrix matG=matA.transpose();
System.out.println("G=\n"+matG);
//执行矩阵乘法,不清楚矩阵乘法的真正含义,请参考线性代数教材。
Matrix matE=matA.multiply(matG);
//按[[1,2,3],[4,5,6]]类似格式输出矩阵,这里的逗号都是英文逗号
System.out.println("E=\n"+matE);
MainClass.sc.close();
}
private static void inputMatrix(Matrix mat) {
int rowCount=mat.getRowCount();
int colCount=mat.getColCount();
System.out.println("输入"+rowCount+"×"+colCount+"矩阵");
for(int i=0;i<rowCount;i++) {
for(int j=0;j<colCount;j++) {
System.out.print("["+i+"]["+j+"]=");
mat.data[i][j]=sc.nextDouble();
}
}
}
}
你需要在研读上述代码并结合下面的测试画面中的数据输出格式化,在右侧代码区中完成Matrix的定义。
测试说明
平台会对你编写的代码进行测试,以下是测试画面之一: 输入矩阵行列数 2 3 输入2×3矩阵 [0][0]=1 [0][1]=2 [0][2]=3 [1][0]=4 [1][1]=5 [1][2]=6 矩阵A= [[1.00, 2.00, 3.00], [4.00, 5.00, 6.00]] 输入2×3矩阵 [0][0]=4 [0][1]=5 [0][2]=3 [1][0]=8 [1][1]=7 [1][2]=0.3 矩阵B= [[4.00, 5.00, 3.00], [8.00, 7.00, 0.30]] 运算结果如下: C= [[5.00, 7.00, 6.00], [12.00, 12.00, 6.30]] D= [[6.60, 7.60, 8.60], [9.60, 95.00, 11.60]] F= [[3.40, 6.80, 10.20], [13.60, 303.96, 20.40]] G= [[1.00, 4.00], [2.00, 89.40], [3.00, 6.00]] E= [[14.00, 200.80], [200.80, 8044.36]]
//定义一个Matrix类,表示一个矩阵
public class Matrix {
//定义一个二维数组,用来存储矩阵的元素
public double[][] data;
//定义一个构造方法,用来创建一个指定行列数的矩阵,并初始化为0
public Matrix(int rowCount, int colCount) {
data = new double[rowCount][colCount];
for(int i = 0; i < rowCount; i++) {
for(int j = 0; j < colCount; j++) {
data[i][j] = 0;
}
}
}
//定义一个方法,用来获取矩阵的行数
public int getRowCount() {
return data.length;
}
//定义一个方法,用来获取矩阵的列数
public int getColCount() {
return data[0].length;
}
//定义一个方法,用来将矩阵转换为字符串,方便输出
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0; i < getRowCount(); i++) {
if(i != 0) {
sb.append(" ");
}
sb.append("[");
for(int j = 0; j < getColCount(); j++) {
sb.append(String.format("%.2f", data[i][j]));
if(j != getColCount() - 1) {
sb.append(",");
}
}
sb.append("]");
if(i != getRowCount() - 1) {
sb.append(",\n");
}
}
sb.append("]");
return sb.toString();
}
//定义一个方法,用来实现矩阵与另一个矩阵相加,返回一个新的矩阵
public Matrix plus(Matrix other) {
//判断两个矩阵是否有相同的行列数,如果不同,则抛出异常
if(getRowCount() != other.getRowCount() || getColCount() != other.getColCount()) {
throw new IllegalArgumentException("两个矩阵的行列数不相等,无法相加");
}
//创建一个新的矩阵,用来存储相加的结果
Matrix result = new Matrix(getRowCount(), getColCount());
//遍历两个矩阵的元素,逐个相加,并赋值给新矩阵
for(int i = 0; i < getRowCount(); i++) {
for(int j = 0; j < getColCount(); j++) {
result.data[i][j] = data[i][j] + other.data[i][j];
}
}
//返回新矩阵
return result;
}
//定义一个方法,用来实现矩阵与一个数相加,返回一个新的矩阵
public Matrix plus(double num) {
//创建一个新的矩阵,用来存储相加的结果
Matrix result = new Matrix(getRowCount(), getColCount());
//遍历矩阵的元素,逐个与数相加,并赋值给新矩阵
for(int i = 0; i < getRowCount(); i++) {
for(int j = 0; j < getColCount(); j++) {
result.data[i][j] = data[i][j] + num;
}
}
//返回新矩阵
return result;
}
//定义一个方法,用来实现矩阵与另一个矩阵相乘,返回一个新的矩阵
public Matrix multiply(Matrix other) {
//判断两个矩阵是否满足相乘的条件,即第一个矩阵的列数等于第二个矩阵的行数,如果不满足,则抛出异常
if(getColCount() != other.getRowCount()) {
throw new IllegalArgumentException("两个矩阵不满足相乘的条件,无法相乘");
}
//创建一个新的矩阵,用来存储相乘的结果,其行数等于第一个矩阵的行数,其列数等于第二个矩阵的列数
Matrix result = new Matrix(getRowCount(), other.getColCount());
//遍历新矩阵的元素,根据矩阵乘法的规则,计算每个元素的值,并赋值给新矩阵
for(int i = 0; i < result.getRowCount(); i++) {
for(int j = 0; j < result.getColCount(); j++) {
//计算新矩阵的第i行第j列的元素的值,即第一个矩阵的第i行与第二个矩阵的第j列的点积
double sum = 0;
for(int k = 0; k < getColCount(); k++) {
sum += data[i][k] * other.data[k][j];
}
result.data[i][j] = sum;
}
}
//返回新矩阵
return result;
}
//定义一个方法,用来实现矩阵与一个数相乘,返回一个新的矩阵
public Matrix multiply(double num) {
//创建一个新的矩阵,用来存储相乘的结果
Matrix result = new Matrix(getRowCount(), getColCount());
//遍历矩阵的元素,逐个与数相乘,并赋值给新矩阵
for(int i = 0; i < getRowCount(); i++) {
for(int j = 0; j < getColCount(); j++) {
result.data[i][j] = data[i][j] * num;
}
}
//返回新矩阵
return result;
}
//定义一个方法,用来实现矩阵的转置,返回一个新的矩阵
public Matrix transpose() {
//创建一个新的矩阵,用来存储转置的结果,其行数等于原矩阵的列数,其列数等于原矩阵的行数
Matrix result = new Matrix(getColCount(), getRowCount());
//遍历原矩阵的元素,将其赋值给新矩阵对应位置上的元素,即原矩阵的第i行第j列的元素赋值给新矩阵的第j行第i列的元素
for(int i = 0; i < getRowCount(); i++) {
for(int j = 0; j < getColCount(); j++) {
result.data[j][i] = data[i][j];
}
}
//返回新矩阵
return result;
}
}