一、随机数生成相关实验
动手动脑1:纯随机数发生器实现
问题要求:
编写一个方法,使用线性同余算法生成指定数目(比如1000个)的随机整数。
算法参数:
- Modulus = 2³¹ - 1 = int.MaxValue
- Multiplier = 7⁵ = 16807
- C = 0
实现代码:
public class LinearCongruentialGenerator {private static final long MODULUS = 2147483647L; // 2^31 - 1private static final long MULTIPLIER = 16807L;private long seed;public LinearCongruentialGenerator(long seed) {this.seed = seed;}public int nextInt() {seed = (MULTIPLIER * seed) % MODULUS;return (int) seed;}// 生成指定数量的随机整数public static int[] generateRandomNumbers(int count, long seed) {LinearCongruentialGenerator generator = new LinearCongruentialGenerator(seed);int[] numbers = new int[count];for (int i = 0; i < count; i++) {numbers[i] = generator.nextInt();}return numbers;}
}
学习要点:
- 理解伪随机数生成原理
- 掌握线性同余算法的实现
- 学会建立个人代码仓库,积累实用工具类
二、可变参数方法
动手动脑2:可变参数方法的特点
示例代码分析:
public class VariableArgumentsTest {public static double max(double... values) {double largest = Double.MIN_VALUE;for (double v : values) {if (v > largest) largest = v;}return largest;}public static void main(String[] args) {System.out.println("Max: " + max(1, 11, 300, 2, 3));}
}
可变参数特点总结:
- 位置要求:只能出现在方法参数列表的最后
- 语法格式:"..."位于变量类型和变量名之间,前后有无空格均可
- 实现机制:编译器为可变参数隐含创建数组
- 访问方式:在方法体中以数组形式访问可变参数
三、方法重载
动手动脑3:方法重载特性分析
示例代码:
public class MethodOverload {public static void main(String[] args) {System.out.println("The square of integer 7 is " + square(7));System.out.println("The 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;}
}
方法重载要点:
-
必要条件:
- 方法名相同
- 参数类型不同,或参数个数不同,或参数类型的顺序不同
-
非判断条件:方法的返回值类型
-
实践练习:
- 查看JDK中System.out.println()方法的重载形式
- 发现println方法有多个重载版本,分别处理不同数据类型
四、递归与递推
动手动脑4:n!的递归与递推实现对比
递归实现:
public class RecursionExample {// 递归方式计算阶乘public static long factorialRecursive(int n) {if (n == 0 || n == 1) {return 1; // 递归结束条件}return n * factorialRecursive(n - 1); // 自己调用自己}
}
递推实现:
public class IterationExample {// 递推方式计算阶乘public static long factorialIterative(int n) {long result = 1;for (int i = 1; i <= n; i++) {result *= i; // 从前到后逐步计算}return result;}
}
递归编程模式总结:
- 递归头:函数开头必须判断递归结束条件
- 递归体:至少有一句"自己调用自己"
- 控制变量:必须有控制递归终结的参数变量
递归 vs 递推对比:
特性 | 递归 | 递推 |
---|---|---|
执行方向 | 由后至前再回来 | 从前到后 |
实现方式 | 函数自我调用 | 循环语句 |
内存使用 | 栈空间消耗大 | 栈空间消耗小 |
代码可读性 | 更符合数学思维 | 更直观易懂 |
五、大数字与浮点数处理
动手动脑5:大整数阶乘计算
问题现象:
使用int或long类型计算较大数的阶乘时会出现负数结果
问题根源:
- int类型:32位,最大值2,147,483,647
- long类型:64位,最大值9,223,372,036,854,775,807
- 数值超出范围时发生二进制截断
解决方案:使用BigInteger类
import java.math.BigInteger;public class BigNumberExample {public static BigInteger calculateBigFactorial(int n) {if (n == 0 || n == 1) {return BigInteger.valueOf(1);}return BigInteger.valueOf(n).multiply(calculateBigFactorial(n - 1));}
}
动手动脑6:浮点数精度比较
问题代码:
double i = 0.0001;
double j = 0.00010000000000000001;
System.out.println(i == j); // 输出:true
正确比较方法:
// 比较两个浮点数的差值是否在允许范围内
public static boolean doubleEquals(double a, double b, double epsilon) {return Math.abs(a - b) < epsilon;
}// 使用示例
if (doubleEquals(i, j, 1e-10)) {System.out.println("在精度范围内相等");
} else {System.out.println("不相等");
}
六、课后实验项目
实验项目:四则运算题目生成器
阶段1要求:
花二十分钟写一个能自动生成30道小学四则运算题目的"软件"
基础实现思路:
public class ArithmeticGenerator {private Random random = new Random();public void generateQuestions(int count) {for (int i = 0; i < count; i++) {int num1 = random.nextInt(100);int num2 = random.nextInt(100);char operator = getRandomOperator();System.out.println((i+1) + ". " + num1 + " " + operator + " " + num2 + " = ");}}private char getRandomOperator() {char[] operators = {'+', '-', '×', '÷'};return operators[random.nextInt(operators.length)];}
}
阶段2进阶要求:
-
题目质量:
- 避免重复题目
- 减法不允许出现负数
- 乘法结果不允许出现四位数
- 除法必须整除不允许出现小数
-
功能扩展:
- 实现在线实时答题
- 统计显示错题数和正确率
- 增加倒计时功能
方法设计建议:
public class AdvancedArithmeticTest {// 检查题目是否重复public static boolean isDuplicate(String question, Set<String> existingQuestions) {return existingQuestions.contains(question);}// 验证减法结果非负public static boolean isValidSubtraction(int a, int b) {return a >= b;}// 验证乘法结果不超过四位数public static boolean isValidMultiplication(int a, int b) {return a * b < 10000;}// 验证除法可以整除public static boolean isValidDivision(int a, int b) {return b != 0 && a % b == 0;}
}
七、学习总结与最佳实践
代码仓库建设
- 分类整理:按功能模块分类存储代码片段
- 注释完善:为每个方法添加详细的使用说明
- 测试用例:为重要方法编写测试代码
- 文档配套:建立配套的使用文档和示例
开发效率提升
- 避免重复造轮子:充分利用已有代码资源
- 方法设计原则:单一职责、参数验证、异常处理
- 递归使用场景:树形结构、分治算法、动态规划
- 大数处理:金融计算、科学运算等场景使用BigDecimal/BigInteger
问题解决思路
- 理解问题本质:如整数溢出、浮点精度等根本原因
- 选择合适的工具:根据需求选择递归或递推实现
- 边界条件处理:特别注意递归结束条件和数值边界
- 性能与可读性平衡:在保证正确性的前提下优化代码
附录:完整代码示例
完整的四则运算题目生成器
import java.util.*;public class CompleteArithmeticGenerator {private Random random = new Random();private Set<String> generatedQuestions = new HashSet<>();public void generateAdvancedQuestions(int count) {generatedQuestions.clear();for (int i = 0; i < count; i++) {String question = generateValidQuestion();System.out.println((i+1) + ". " + question);}}private String generateValidQuestion() {String question;do {int num1 = random.nextInt(100) + 1;int num2 = random.nextInt(100) + 1;char operator = getRandomOperator();// 根据运算符进行验证switch (operator) {case '-':if (!isValidSubtraction(num1, num2)) {// 确保被减数大于等于减数int temp = num1;num1 = Math.max(num1, num2);num2 = Math.min(temp, num2);}break;case '×':if (!isValidMultiplication(num1, num2)) {// 调整数值使乘积不超过四位数num1 = random.nextInt(100) + 1;num2 = random.nextInt(100) + 1;continue;}break;case '÷':if (!isValidDivision(num1, num2)) {// 调整数值使能够整除num2 = random.nextInt(20) + 1;num1 = num2 * (random.nextInt(50) + 1);}break;}question = num1 + " " + operator + " " + num2 + " = ";} while (generatedQuestions.contains(question));generatedQuestions.add(question);return question;}private char getRandomOperator() {char[] operators = {'+', '-', '×', '÷'};return operators[random.nextInt(operators.length)];}private boolean isValidSubtraction(int a, int b) {return a >= b;}private boolean isValidMultiplication(int a, int b) {return a * b < 10000;}private boolean isValidDivision(int a, int b) {return b != 0 && a % b == 0;}public static void main(String[] args) {CompleteArithmeticGenerator generator = new CompleteArithmeticGenerator();generator.generateAdvancedQuestions(30);}
}