当前位置: 首页 > ds >正文

【日撸 Java 三百行】综合任务 1

目录

Day 10:综合任务 1

 一、题目分析

1. 数据结构

2. 相关函数基本知识

二、模块介绍

1. 初始化与成绩矩阵的构建

2. 创建总成绩数组

3. 寻找成绩极值

三、代码与测试

小结

拓展:关于求极值的相关算法


Day 10:综合任务 1

Task:

        学生的成绩存放于一个矩阵,其中行表示学生,列表示科目。如:第 0 行表示第 0 个学生的数学、语文、英语成绩。要求:

        进行学生成绩的随机生成, 区间为 [50, 100].
        找出成绩最好、最差的同学。但有挂科的同学不参加评比.

  • 实际代码中,for 和 if 是最常见的, switch 和 while 使用少得多.
  • 使用了 continue, 它是指继续跳过本次循环后面的代码,直接进入下一次循环. 而 break 是跳出整个循环体.
  • 为了随机数,迫不得已提前使用了 new 语句生成对象.
  • 通过数据测试找出程序中的 bug.

 一、题目分析

1. 数据结构

        每个学生的科目都是三科,不会多不会少,因此多个学生之间的记录是定长记录,因此可以考虑使用固定的一个m*3二维数组来记录所有学生的成绩。此外,题目要求记录成绩最好和最差的同学,因此,可以考虑使用一个数组记录每个同学的成绩和,然后通过成绩统计最高成绩与最低成绩。

        注:就实现统计最好最差同学来说,这里的求和数组不是必要的,可以在设计学生成绩时就完成相关统计。因此代码是可以简化的,只是此处为了练习java代码内容故尽可能让数据结构完善。

2. 相关函数基本知识

1) Random.nextlnt()
        为避免问题模拟时考虑设置数据的麻烦,这里使用了数据数生成的基本方法。
        java提供了Random库,此库中包含了一些系列可用的随机数生成工具。今天我们将使用如下函数:

java Random.nextInt()方法
public int nextInt(int n)
        该方法的作用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n

        有几个注意点是使用这个方法要注意的。

  • 此随机数的生成前闭后开的区间是,因此是无法生成n的
  • 此数据生成最低值是0,若要完成指定[a, b)的生成需要额外设计代码:a + temRandom.nextInt(b - a);
  • 数据是整型,不包含浮点(虽然成绩兼容浮点值,我们这暂时就整型来说明)

2)关于循环语句
        参考:【Java 专题补充】流程控制语句-CSDN博客

3)关于 continue 和 break
        参考: 【Java 专题补充】流程控制语句-CSDN博客

二、模块介绍

1. 初始化与成绩矩阵的构建

        初始化定义的上限不是100而是101是因为随机函数的右界是个开区间,因此要取满需要额外加一。
        此外,考虑到学生数量是不确定的,且考虑到成绩表的可扩展性,这里采用的是动态分配的方法创建矩阵。

// Step 1. Generate the date with n student and m course.// Set these value by yourself.int n = 10;int m = 3;int lowerBound = 50;int upperBound = 101;int threshold = 60;// Here we have to use an object to generate random numbersRandom temRandom = new Random();int[][] data = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {data[i][j] = lowerBound + temRandom.nextInt(upperBound - lowerBound);} // Of for j} // Of for i

2. 创建总成绩数组

        创建总成绩数组。再次强调,这个数组不是必须的,此处是为了区分过程为了理清楚原理特别使用的一个存储空间。本质上可以通过成绩矩阵直接获得这一步的结果。
        当某个学生成绩低于及格线时,其总分无效,依据题意,这里令其总成绩为0。
        这里的0更多起了标记这个学生成绩无效的作用。

// Step 2.Compute the total score of each student.int[] totalScores = new int[n];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (data[i][j] < threshold) {totalScores[i] = 0;break;} // Of iftotalScores[i] += data[i][j];} // Of for j} // Of for i

3. 寻找成绩极值

分析代码如下:
        这里统计时将总分数为0(标记的不及格/通过)的学生跳过统计,符合题意要求
        这里使用了编程中常见得不能再常见的求极值方案——通过给预求极值设定一个反方向的最极限值(说人话就是给最大值设定一个能取的最小值为初始值,给最小值设定一个能取的最大值为初始值。这是一个求极值很常见的方法)
        这里能取的最小值就是0,最大值就是m * upperBound,因此只要保证最大值初始值小于等于0即可,最小值初始值大于等于m * upperBound即可。
        但是要说明,这个最值的含义只有在元素集的数目大于0才有意义。

// Step 3. Find the best and worst student.// Typical initialization for index: invalid value.int tempBestIndex = -1;int tempWorstIndex = -1;// Typical initialization for best and worst values.// They must be replaced by valid values.int tempBestScore = 0;int tempWorstScore = m * upperBound + 1;for (int i = 0; i < n; i++) {// Do not consider failed students.if (totalScores[i] == 0) {continue;} // Of ifif (tempBestScore < totalScores[i]) {tempBestScore = totalScores[i];tempBestIndex = i;} // Of if// Attention: This if statememt cannot be combined with the last one// using "else if",because a student can be both the best and the// worst. I found this bug while setting upperBound = 65.if (tempWorstScore > totalScores[i]) {tempWorstScore = totalScores[i];tempWorstIndex = i;} // Of if} // Of for i

三、代码与测试

package basic;import java.util.Arrays;
import java.util.Random;/*** The usage of sth.** @author: Changyang Hu joe03@foxmail.com* @date created: 2025-05-10*/
public class Task1 {/*** ********************** @Title: main* @Description: The entrance of the program.** @param args Not used now.* @return void **********************/public static void main(String args[]) {task1();}// Of main/*** ********************** @Title: task1* @Description: Method unit test.* * @return void **********************/public static void task1() {// Step 1. Generate the data with n student and m courses.// Set these values by yourselfint n = 10;int m = 3;int lowerBound = 50;int upperBound = 101; // Should be 100. I use this value for testingint threshold = 60;// Here we have to use an object to generate random numbers.Random tempRandom = new Random();int[][] data = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {data[i][j] = lowerBound + tempRandom.nextInt(upperBound - lowerBound);} // Of for j} // Of for iSystem.out.println("The data is:\r\n" + Arrays.deepToString(data));// Step 2. Compute the total score of each student.int[] totalScores = new int[n];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (data[i][j] < threshold) {totalScores[i] = 0;break;} // Of iftotalScores[i] += data[i][j];} // Of for j} // Of for iSystem.out.println("The total scores are:\r\n" + Arrays.toString(totalScores));// Step 3. Find the best and worst student.// Typical initialization for index: invalid value.int tempBestIndex = -1;int tempWorstIndex = -1;// Typical initialization for best and worst value.// They must be replaced by valid values.int tempBestScore = 0;int tempWorstScore = m * upperBound + 1;for (int i = 0; i < n; i++) {// Do not consider failed students.if (totalScores[i] == 0) {continue;} // Of ifif (tempBestScore < totalScores[i]) {tempBestScore = totalScores[i];tempBestIndex = i;} // Of if// Attention: This if statement cannot be combined with the last one// using "else if", because a student can be both the best and the// worst. I found this bug while setting upperBound = 65.if (tempWorstScore > totalScores[i]) {tempWorstScore = totalScores[i];tempWorstIndex = i;} // Of if} // Of for i// Step 4. Output the student number and score.if (tempBestIndex == -1) {System.out.println("Cannot find best student. ALL students have failed.");} else {System.out.println("The best student is No." + tempBestIndex + " with scores: "+ Arrays.toString(data[tempBestIndex]));} // Of ifif (tempWorstIndex == -1) {System.out.println("Cannot find worst student. All students have failed.");} else {System.out.println("The worst student is No." + tempWorstIndex + " with scores: "+ Arrays.toString(data[tempWorstIndex]));} // Of if}// Of task1}// Of class Task1

 第一次运行结果:upperBound = 101

在一次运行后数据如我们预期那样,对于不及格的学生,其总分是按照0处理的。
为了验证我们预先的特殊情况,我们先将随机生成的分数上限下调到66,让我们的分数随机数更容易落到不及格:upperBound = 66

可以发现,因为每个人存在不及格学科(由于是随机生成,所以也存在第一张图片所示,仍然有结果),因此大家总分都不及格,因此,这里大家的分数在比较时都跳过了,出现了“无最高分,无最低分”的人为规定条件。 


小结

        本篇展示了数据处理中很多比较常见的方法,包括总分求和、极值的计算与分析等。要注意的点就是灵活对于数据进行分析,合理利用数据结构即可,属于是基础的表格数据的应用。
        但是引起我思考的是其中求极值的方法。本篇代码中我们使用的是一种给极值赋相反的极限值的一种无效赋值法,我提到了“ 数据集合元素要大于0时,极值才有意义 ”。

拓展:关于求极值的相关算法

        任何最大值最小值的含义都是在元素集大于0才有意义,这个不言而喻。
        也是因为这个原因,还有另一种设置初值的方案是——将第一个元素的值设定给初始极值,并由此衍生——只记录最大值的下标而不记录最大值本身,然后下标初始值为0(就是默认为第一个元素的值)。如果这么做了,我们设定的变量似乎就更少了呢,而且,对于随机存取的数组来说,下标的信息熵比元素本身要多***(知道极值下标的话,在知道数据顺序之余还能以O(1)速度立马知道数据,而只知道数据最大值本身的话,那也就知道数据本身而已了)***。
        但是事物要辩证看待,本代码使用的无效赋值方法其实可以让数据本身起到一种标签的作用,若比大小时候有特殊处理时(比如这里的0分不统计),通过判断极值是否有效也可以用以断定“ 是不是所有大小判断都已经跳过 ”这种极特殊情景。

        除此之外,一般常见的求极值的算法还有:三分、二元函数、退火求极值的方法。更详细的可以参考如下博文:
优化算法:一元与二元函数极值求解与退火方法-CSDN博客

http://www.xdnf.cn/news/5376.html

相关文章:

  • Spark流水线在线演示
  • 小程序初始化加载时间优化 步骤思考与总结
  • (二)Linux下基本指令 2
  • 碰一碰发视频源码搭建的定制化开发指南,支持OEM
  • Vue v-model 深度解析:实现原理与高级用法
  • 【c++】多态详解
  • 【MySQL】数据表插入数据
  • 基于python的少儿兴趣班推荐系统的设计与实现
  • 微服务6大拆分原则
  • C++修炼:stack和queue
  • 服务器综合实验(实战详解)
  • 【新教程】Linux服务器ssh启用两步验证
  • 什么是深拷贝什么是浅拷贝,两者区别
  • PPO近端策略优化算法
  • Tailwind CSS v4 主题化实践入门(自定义 Theme + 主题模式切换)✨
  • shell 编程之正则表达式与文本处理器
  • JS逆向-7881游戏平台Lb-Sign参数和Lb-Timestamp参数
  • SaaS场快订平台项目说明【持续更新】
  • ensp的华为小实验
  • 管道-验证和转换
  • 关于“铜宝”电线的质量,以下是综合分析:
  • 第3.2.3节 Android动态调用链路的获取
  • 【程序员AI入门:开发】11.从零构建智能问答引擎:LangChain + RAG 实战手册
  • 计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 08.阴影
  • Python函数式编程入门:闭包与装饰器详解
  • 【数据结构】子串、前缀
  • 数据库索引详解:原理 · 类型 · 使用 · 优化
  • 傅利叶十周年,升级核心战略:“有温度”的具身智能蓝图
  • 【STM32 学习笔记】USART串口
  • ScaleTransition 是 Flutter 中的一个动画组件,用于实现缩放动画效果。