Math 类
在 Java 中,数学运算类
Math是在java.lang包中,不需要额外导入即可使用,是一个用于执行基本数学运算的工具类。它包含了许多用于执行常见数学计算的静态方法,这些方法可以直接通过类名Math调用,无需创建类的实例。
常用方法
基本数学运算:
min()参数类型两个相同类型的参数(例如两个整数、两个浮点数等)
max()参数类型两个相同类型的参数
floor()参数类型double或float,返回值类型double或float,表示不大于参数的最大整数值
ceil()参数类型double或float,返回值类型double或float,表示不小于参数的最小整数值
round()参数类型double或float,返回值类型long或int,表示四舍五入后的整数值
sqrt()参数类型double,返回值类型double,表示参数的平方根
abs()参数类型int,long,float,double,返回值类型与参数类型相同,表示参数的绝对值
三角函数:
sin()参数类型double,返回值类型double,返回角度的正弦值。
cos()参数类型double,返回值类型double,返回角度的余弦值。
tan()参数类型double,返回值类型double,返回角度的正切值。
对数函数:
log()参数类型double,返回值类型double,返回参数的自然对数。
log10()参数类型double,返回值类型double,返回参数的以 10 为底的对数。
取整和舍入:
round()参数类型float,返回值类型int,返回最接近参数的整数,四舍五入。
round()参数类型double,返回值类型long,返回最接近参数的整数,四舍五入。
常数:
PI表示圆周率 π。
E表示自然对数的底数 e。
示例
java
public class MathExample {
public static void main(String[] args) {
// 计算绝对值
int absValue = Math.abs(-10);
System.out.println("Absolute value: " + absValue);
// 计算平方根
double sqrtValue = Math.sqrt(25);
System.out.println("Square root: " + sqrtValue);
// 计算 2 的 3 次方
double powValue = Math.pow(2, 3);
System.out.println("Power: " + powValue);
// 求两个数中的最大值和最小值
double maxNum = Math.max(10.5, 20.7);
double minNum = Math.min(10.5, 20.7);
System.out.println("Max: " + maxNum + ", Min: " + minNum);
// 计算正弦值和余弦值
double sinValue = Math.sin(Math.PI / 2);
double cosValue = Math.cos(Math.PI);
System.out.println("Sin(π/2): " + sinValue + ", Cos(π): " + cosValue);
// 计算自然对数和以 10 为底的对数
double logValue = Math.log(Math.E); // Math.log(Math.E) 应为 1
double log10Value = Math.log10(100); // Math.log10(100) 应为 2
System.out.println("Natural log(e): " + logValue + ", Base-10 log(100): " + log10Value);
}
}
random()方法
Math.random() 用于生成一个范围在 [0.0, 1.0) 内的随机双精度浮点数。
java
double randomValue = Math.random();
使用 Math.random() 生成指定范围的随机数
生成
[0.0, 1.0)之间的随机数
javadouble randomValue = Math.random();将
[0.0, 1.0)的随机数映射到[min, max)范围内
首先,计算
[0.0, 1.0)范围内的随机数对应到[min, max)范围内的数值
javadouble randomInRange = min + randomValue * (max - min);在这里,
randomValue * (max- min)将[0.0, 1.0)的随机数映射到[0.0, max-min)的范围内,加上min则将其映射到[min, max)范围内。将
randomInRange转换为整数(如果需要)
javaint randomInt = (int) Math.floor(randomInRange); // 使用 Math.floor() 向下取整,确保落在整数范围内。
注意:
包含边界问题 :如果要生成的随机整数范围是
[min, max],则在计算随机数时应使用(max - min + 1),而不是(max - min)。这是因为Math.random()生成的随机数范围是[0.0, 1.0)。向下取整 :使用
(int) Math.floor(randomValue)来确保随机数被正确地转换为整数。
案例 :生成的随机整数落在 [15, 30] 范围内,包括 15 和 30。
java
public class Main {
public static void main(String[] args) {
// 生成 [15, 30] 范围内的随机整数
int randomInt = generateRandomIntInRange(15, 30);
System.out.println("Random integer between 15 and 30 (inclusive): " + randomInt);
}
// 生成指定范围内的随机整数,包括边界值
public static int generateRandomIntInRange(int min, int max) {
// min 和 max 为 inclusive 的范围
return (int) (min + Math.random() * (max - min + 1));
}
}
Random 类
在 Java 中,生成随机数也可以使用 Random 类。例如:
java
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random random = new Random();
double randomValue = random.nextDouble(); // 生成 [0, 1) 之间的随机小数
System.out.println("Random value between 0 and 1: " + randomValue);
// 生成 [10, 30) 之间的随机整数
int randomInt = random.nextInt(20) + 10; // nextInt生成[0,20), 故+10
System.out.println("Random integer between 10 and 29: " + randomInt);
}
}
nextDouble()用于生成一个范围在[0.0, 1.0)内的随机双精度浮点数。nextInt(int bound)用于生成一个范围在[0, bound)内的随机整数。nextBoolean():随机生成一个boolean值,即true或false。nextLong():生成一个长整型随机数。nextFloat():生成一个范围在[0.0, 1.0)内的随机单精度浮点数。
随机数种子
在 Random 类的构造函数中可以传入一个种子(seed),种子决定了随机数的起始状态。如果使用相同的种子,那么每次生成的随机数序列将会相同。例如:
java
Random randomWithSeed = new Random(123); // 使用种子为 123 的 Random 实例
int randomInt1 = randomWithSeed.nextInt(100);
int randomInt2 = randomWithSeed.nextInt(100);
System.out.println(randomInt1); // 生成的随机数1
System.out.println(randomInt2); // 生成的随机数2
//输出的结果相同
如果希望每次得到不同的随机数序列,可以使用不同的种子来初始化 Random 类的实例。一种常见的做法是使用系统当前时间作为种子,因为时间在不同的时刻通常是不同的,这样可以在一定程度上保证每次运行生成的随机数序列都不同。
java
Random random = new Random(System.currentTimeMillis()); // 使用当前时间作为种子
int randomInt1 = random.nextInt(100);
int randomInt2 = random.nextInt(100);
System.out.println(randomInt1); // 输出随机数1
System.out.println(randomInt2); // 输出随机数2
//输出的随机数不同
为什么要有随机数种子?
-
可复现性: 在需要对程序进行调试或者测试时,使用相同的种子可以确保每次生成的随机数序列是相同的,从而方便排查问题。
-
模拟随机性: 虽然计算机生成的随机数实际上是伪随机数,但通过使用种子,可以使得随机数序列表现出与真实随机数类似的随机性特征,满足各种随机性要求。
-
实验设计: 在科学实验或者模拟中,有时需要控制随机因素,确保每次实验都在相同的初始条件下进行,这时候可以通过固定种子来实现这一点。
"计算机生成的随机数实际上是伪随机数"这句话的含义是指,虽然计算机能够生成看似随机的数值序列,但这些数值实际上是通过确定性算法计算得出的,而非真正意义上的完全随机。这种由确定性算法生成的数列称为伪随机数序列。
为什么计算机在生成随机数时是伪随机的?
计算机在生成随机数时,使用的是伪随机数生成器(PRNG,Pseudo-Random Number Generator)。这些生成器实际上是确定性算法,它们接收一个种子作为输入,然后根据该种子计算出一个数值序列。由于算法是确定性的,相同的种子将会导致生成完全相同的随机数序列。
伪随机的好处:
重现性: 使用相同的种子可以重现相同的随机数序列,这在调试和测试中非常有用,因为可以确保问题能够被复现和修复。
周期性: 伪随机数生成器的数列有限,当达到一定长度后会开始重复。因此,长期使用时可能会出现周期性,需要定期更换种子来避免。
随机性特征: 尽管是伪随机数,但合理的伪随机数生成器能够模拟出许多真实随机数的统计特性,例如均匀分布、正态分布等,这使得它们在模拟和仿真中有广泛的应用。
综上所述,计算机生成的随机数虽然不是真正的随机数,但通过合适的算法和种子管理,能够满足大多数实际应用的随机性需求。