课后作业一
Java 第二讲 方法|动手动脑与课后实验整理
课程来源:石家庄铁道大学《Java 语言程序设计》第二讲 方法
动手动脑 1:手写实现随机数发生器
题目
编写一个方法,使用给定算法生成指定数目(比如 1000 个)的随机整数。
- Modulus = (2^{31}-1) = Integer.MAX_VALUE
- Multiplier = 7⁵ = 16807
- C = 0
经过 (2^{31}-2) 个数之后才会出现重复。
算法原理
线性同余随机数发生器公式:
(next = (Multiplier * current + C)\bmod Modulus)
完整代码 MyRandomDemo.java
public class MyRandomDemo {
// 线性同余生成随机数
public static int myRandom(int seed) {
final int Modulus = Integer.MAX_VALUE;
final int Multiplier = 16807;
final int C = 0;
return (int) (( (long)Multiplier * seed + C ) % Modulus);
}
//生成count个随机整数
public static void generateRandomNums(int seed, int count){
int cur = seed;
for(int i=0;i<count;i++){
cur = myRandom(cur);
System.out.print(cur+" ");
if((i+1)%10 ==0){
System.out.println();
}
}
}
public static void main(String[] args) {
//以系统当前时间作为种子
long timeSeed = System.currentTimeMillis();
generateRandomNums((int)timeSeed,1000);
}
}
要点说明
- 计算时强制转为
long,防止整型溢出; - 种子不同,随机序列不同;相同种子得到完全相同随机序列;
- 每行输出 10 个数字,方便查看。
动手动脑 2:方法重载代码观察分析
题目
观察MethodOverload.java代码,分析程序特殊之处,理解方法重载。
源代码
public class MethodOverload {
public static void main(String[] args) {
System.out.println("The square of integer 7 is " + square(7));
System.out.println("\nThe square of double 7.5 is " + square(7.5));
}
public static int square(int x) {
return x * x;
}
public static double square(double y) {
return y * y;
}
}
运行输出
The square of integer 7 is 49
The square of double 7.5 is 56.25
重载知识点总结
- 构成重载条件:
- 方法名字完全相同
- 参数列表不同(参数个数、参数类型、参数顺序至少一项不同)
- ⚠️返回值类型不作为重载判断依据,只修改返回值会直接编译报错。
- 编译器根据传入实参类型自动匹配调用哪个方法。
- 拓展:
System.out.println()就是典型的大量重载,支持 int、double、String、boolean 等多种参数。
思考题:仅修改返回值,方法名、参数列表不变,能构成重载吗?
答案:不能,编译报错。
动手动脑 3:递归求阶乘 & int 溢出 BUG
题目
编写递归求 n! 程序,观察 n 增大后结果出现负数 bug,分析原因,使用 BigInteger 解决大整数阶乘。
数学公式:
(\begin{cases}
1! = 1 \
n! = n \times (n-1)!
\end{cases})版本 1 int 递归阶乘(存在溢出 bug CalculateN.java)
public class CalculateN {
public static int factorial(int n){
if(n ==1){
return 1;
}
return n * factorial(n-1);
}
public static void main(String[] args) {
for(int i=1;i<=20;i++){
System.out.println(i+"! = "+ factorial(i));
}
}
}
BUG 现象
n 超过 12,输出结果出现负数、异常数字。
根源
int 是 32 位有符号整数,最大值Integer.MAX_VALUE = 2147483647;阶乘增长极快,13! 就超过 int 上限,二进制溢出,符号位被篡改。
版本 2 BigInteger 大整数阶乘 BigFactorial.java
import java.math.BigInteger;
public class BigFactorial {
public static BigInteger calculateN2(int n) {
if(n==1 || n==0){
return BigInteger.valueOf(1);
}
return BigInteger.valueOf(n).multiply(calculateN2(n-1));
}
public static void main(String[] args) {
for(int i =1; i<=50;i++){
System.out.println(i+"! = "+ calculateN2(i));
}
}
}
BigInteger 没有固定位数限制,不能直接使用
*运算符,调用.multiply()完成乘法。
递归 vs 递推(循环实现阶乘)
//递推:循环从前向后计算
public static long factIter(int n){
long res = 1;
for(int i=2;i<=n;i++){
res *=i;
}
return res;
}
- 递归:大事化小,先递降到终止条件,再回溯计算;代码简洁,但 n 过大会栈溢出。
- 递推(循环):由基础值向后逐步计算,性能更好。
动手动脑 4:浮点数相等比较陷阱
题目
分析下面代码输出,思考浮点数如何正确比较相等。
public class FloatCompareTest {
public static void main(String[] args) {
double i = 0.0001;
double j = 0.00010000000000000001;
System.out.println(i==j); //输出true
}
}
原因
计算机二进制存储 double 浮点数,部分十进制小数无法精确表达,存在舍入误差。直接使用==判断相等是错误写法。
✅正确比较方案:判断差值绝对值小于极小误差阈值,如1e-10
if(Math.abs(i-j) < 1e-10){
System.out.println("两个浮点数近似相等");
}else{
System.out.println("不相等");
}
课后实验:小学四则运算程序(阶段 1 + 阶段 2)
需求
阶段 1:生成 30 道小学四则运算题目
阶段 2 扩展:
- 题目避免重复;减法不出现负数;乘法结果不能四位数;除法必须整除;
- 答题交互,结束统计错题数量、正确率;
- 倒计时,超时未完成算作错题;
- 全部功能封装为方法。
阶段 1 基础代码 ArithmeticTest.java
import java.util.Random;
public class ArithmeticTest {
//生成一道四则运算题目
public static String generateOneQuestion(){
Random rand = new Random();
int op1 = rand.nextInt(100)+1;
int op2 = rand.nextInt(100)+1;
//运算符 +-*/
String[] ops = {"+","-","*","/"};
String op = ops[rand.nextInt(4)];
return op1 + op + op2;
}
//生成count道题目
public static void printQuestions(int count){
for(int i=0;i<count;i++){
System.out.println((i+1)+". "+generateOneQuestion());
}
}
public static void main(String[] args) {
printQuestions(30);
}
}
阶段 2 关键方法设计思路
generateValidQuestion():生成合规题目- 减法:若 op1 < op2 交换操作数,保证结果不为负;
- 乘法:循环生成直到
op1*op2 <1000,避免 4 位数; - 除法:循环生成,保证
op1 % op2 ==0实现整除; - 使用集合保存已出题,防止题目重复。
startAnswer():答题交互,读取用户输入,比对标准答案,统计错题。countDownTimer():记录开始时间,实现倒计时,判断是否超时。showResult(int wrongNum,int total,int timeUsed)输出统计信息:总题数、错题、正确率、超时提示。
控制台版本结合 Scanner,也可开发 GUI 窗口版本。
课程知识点小结
- 方法的意义:实现程序模块化,封装重复逻辑,降低代码复杂度,便于维护和团队分工。
- Java 方法语法:
访问修饰符 [static] 返回值类型 方法名(参数列表){ return 值; } - 静态方法:
static修饰,支持类名.方法名()调用;JDK5 + 支持静态导入import static java.lang.Math.*; - 可变参数
double ... values,必须放在参数列表末尾,方法内部当做数组使用。 - 方法重载:方法名相同、参数列表不同;返回值类型不能作为重载判断条件。
- 递归:方法自己调用自己;必须设置终止条件,不断缩小问题规模;注意栈溢出风险。
- 数值坑:int、long 存在固定位数溢出问题;超大整数使用
BigInteger;浮点数禁止直接使用==比较。 - 学习习惯:收集整理常用代码片段,建立个人代码仓库,提升编程效率。

浙公网安备 33010602011771号