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)。这些生成器实际上是确定性算法,它们接收一个种子作为输入,然后根据该种子计算出一个数值序列。由于算法是确定性的,相同的种子将会导致生成完全相同的随机数序列。
伪随机的好处:
重现性: 使用相同的种子可以重现相同的随机数序列,这在调试和测试中非常有用,因为可以确保问题能够被复现和修复。
周期性: 伪随机数生成器的数列有限,当达到一定长度后会开始重复。因此,长期使用时可能会出现周期性,需要定期更换种子来避免。
随机性特征: 尽管是伪随机数,但合理的伪随机数生成器能够模拟出许多真实随机数的统计特性,例如均匀分布、正态分布等,这使得它们在模拟和仿真中有广泛的应用。
综上所述,计算机生成的随机数虽然不是真正的随机数,但通过合适的算法和种子管理,能够满足大多数实际应用的随机性需求。