数学和随机
本文为书籍《Java编程的逻辑》1和《剑指Java:核心原理与应用实践》2阅读笔记
6.1 Math类
JDK
中的数学相关类有java.lang.Math
类,包含了一些数学常量值,以及用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数等,其方法的参数和返回值类型一般为double
类型。
属性:
Modifier and Type | Field and Description |
---|---|
static double | E The double value that is closer than any other to e, the base of the natural logarithms. |
static double | PI The double value that is closer than any other to pi, the ratio of the circumference of a circle to its diameter. |
常用方法:
Modifier and Type | Method and Description |
---|---|
static double | abs(double a) Returns the absolute value of a double value. |
static float | abs(float a) Returns the absolute value of a float value. |
static int | abs(int a) Returns the absolute value of an int value. |
static long | abs(long a) Returns the absolute value of a long value. |
static double | acos(double a) Returns the arc cosine of a value; the returned angle is in the range 0.0 through pi. |
static int | addExact(int x, int y) Returns the sum of its arguments, throwing an exception if the result overflows an int . |
static long | addExact(long x, long y) Returns the sum of its arguments, throwing an exception if the result overflows a long . |
static double | asin(double a) Returns the arc sine of a value; the returned angle is in the range -pi/2 through pi/2. |
static double | atan(double a) Returns the arc tangent of a value; the returned angle is in the range -pi/2 through pi/2. |
static double | atan2(double y, double x) Returns the angle theta from the conversion of rectangular coordinates ( x , y ) to polar coordinates (r, theta). |
static double | cbrt(double a) Returns the cube root of a double value. |
static double | ceil(double a) Returns the smallest (closest to negative infinity) double value that is greater than or equal to the argument and is equal to a mathematical integer. |
static double | copySign(double magnitude, double sign) Returns the first floating-point argument with the sign of the second floating-point argument. |
static float | copySign(float magnitude, float sign) Returns the first floating-point argument with the sign of the second floating-point argument. |
static double | cos(double a) Returns the trigonometric cosine of an angle. |
static double | cosh(double x) Returns the hyperbolic cosine of a double value. |
static int | decrementExact(int a) Returns the argument decremented by one, throwing an exception if the result overflows an int . |
static long | decrementExact(long a) Returns the argument decremented by one, throwing an exception if the result overflows a long . |
static double | exp(double a) Returns Euler’s number e raised to the power of a double value. |
static double | expm1(double x) Returns ex -1. |
static double | floor(double a) Returns the largest (closest to positive infinity) double value that is less than or equal to the argument and is equal to a mathematical integer. |
static int | floorDiv(int x, int y) Returns the largest (closest to positive infinity) int value that is less than or equal to the algebraic quotient. |
static long | floorDiv(long x, long y) Returns the largest (closest to positive infinity) long value that is less than or equal to the algebraic quotient. |
static int | floorMod(int x, int y) Returns the floor modulus of the int arguments. |
static long | floorMod(long x, long y) Returns the floor modulus of the long arguments. |
static int | getExponent(double d) Returns the unbiased exponent used in the representation of a double . |
static int | getExponent(float f) Returns the unbiased exponent used in the representation of a float . |
static double | hypot(double x, double y) Returns sqrt(x2 +y2) without intermediate overflow or underflow. |
static double | IEEEremainder(double f1, double f2) Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard. |
static int | incrementExact(int a) Returns the argument incremented by one, throwing an exception if the result overflows an int . |
static long | incrementExact(long a) Returns the argument incremented by one, throwing an exception if the result overflows a long . |
static double | log(double a) Returns the natural logarithm (base e) of a double value. |
static double | log10(double a) Returns the base 10 logarithm of a double value. |
static double | log1p(double x) Returns the natural logarithm of the sum of the argument and 1. |
static double | max(double a, double b) Returns the greater of two double values. |
static float | max(float a, float b) Returns the greater of two float values. |
static int | max(int a, int b) Returns the greater of two int values. |
static long | max(long a, long b) Returns the greater of two long values. |
static double | min(double a, double b) Returns the smaller of two double values. |
static float | min(float a, float b) Returns the smaller of two float values. |
static int | min(int a, int b) Returns the smaller of two int values. |
static long | min(long a, long b) Returns the smaller of two long values. |
static int | multiplyExact(int x, int y) Returns the product of the arguments, throwing an exception if the result overflows an int . |
static long | multiplyExact(long x, long y) Returns the product of the arguments, throwing an exception if the result overflows a long . |
static int | negateExact(int a) Returns the negation of the argument, throwing an exception if the result overflows an int . |
static long | negateExact(long a) Returns the negation of the argument, throwing an exception if the result overflows a long . |
static double | nextAfter(double start, double direction) Returns the floating-point number adjacent to the first argument in the direction of the second argument. |
static float | nextAfter(float start, double direction) Returns the floating-point number adjacent to the first argument in the direction of the second argument. |
static double | nextDown(double d) Returns the floating-point value adjacent to d in the direction of negative infinity. |
static float | nextDown(float f) Returns the floating-point value adjacent to f in the direction of negative infinity. |
static double | nextUp(double d) Returns the floating-point value adjacent to d in the direction of positive infinity. |
static float | nextUp(float f) Returns the floating-point value adjacent to f in the direction of positive infinity. |
static double | pow(double a, double b) Returns the value of the first argument raised to the power of the second argument. |
static double | random() Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0 . |
static double | rint(double a) Returns the double value that is closest in value to the argument and is equal to a mathematical integer. |
static long | round(double a) Returns the closest long to the argument, with ties rounding to positive infinity. |
static int | round(float a) Returns the closest int to the argument, with ties rounding to positive infinity. |
static double | scalb(double d, int scaleFactor) Returns d × 2scaleFactor rounded as if performed by a single correctly rounded floating-point multiply to a member of the double value set. |
static float | scalb(float f, int scaleFactor) Returns f × 2scaleFactor rounded as if performed by a single correctly rounded floating-point multiply to a member of the float value set. |
static double | signum(double d) Returns the signum function of the argument; zero if the argument is zero, 1.0 if the argument is greater than zero, -1.0 if the argument is less than zero. |
static float | signum(float f) Returns the signum function of the argument; zero if the argument is zero, 1.0f if the argument is greater than zero, -1.0f if the argument is less than zero. |
static double | sin(double a) Returns the trigonometric sine of an angle. |
static double | sinh(double x) Returns the hyperbolic sine of a double value. |
static double | sqrt(double a) Returns the correctly rounded positive square root of a double value. |
static int | subtractExact(int x, int y) Returns the difference of the arguments, throwing an exception if the result overflows an int . |
static long | subtractExact(long x, long y) Returns the difference of the arguments, throwing an exception if the result overflows a long . |
static double | tan(double a) Returns the trigonometric tangent of an angle. |
static double | tanh(double x) Returns the hyperbolic tangent of a double value. |
static double | toDegrees(double angrad) Converts an angle measured in radians to an approximately equivalent angle measured in degrees. |
static int | toIntExact(long value) Returns the value of the long argument; throwing an exception if the value overflows an int . |
static double | toRadians(double angdeg) Converts an angle measured in degrees to an approximately equivalent angle measured in radians. |
static double | ulp(double d) Returns the size of an ulp of the argument. |
static float | ulp(float f) Returns the size of an ulp of the argument. |
6.2 BigInteger类
Integer
类作为int
的包装类,能存储的数值范围为
−
2
31
∼
2
31
−
1
-2^{31}\sim2^{31}-1
−231∼231−1,BigInteger
类的数值范围较Integer
类、Long
类的数值范围要大得多,可以支持任意精度的整数。BigInteger
类位于java.math
包下,和数值包装类一样,继承了Number
类。BigInteger
类是引用数据类型,但不是包装类,不支持自动装箱与拆箱,因此如果需要用它来表示整数,则需要通过指定的构造器来创建它的对象。例如,BigInteger(String val)
构造器可以将整数的十进制字符串表示形式转换为BigInteger
对象,如下所示。
BigInteger bVal = new BigInteger("1234567890");
BigInteger
类是引用数据类型,所以不支持直接使用
+
−
+-
+−等运算符进行算术运算,如果需要完成BigInteger
对象的计算,必须调用相应的方法来完成,如下表所示:
方法定义 | 描述 |
---|---|
BigInteger add(BigInteger val) | 加,返回 this 和 value 的和 |
BigInterger subtract(BigInteger val) | 减,返回 this 和 value 的差 |
BigInterger multiply(BigInteger val) | 乘,返回 this 和 value 的乘积 |
BigInterger divide(BigInteger val) | 除,结果只保留整数部分 |
BigInterger remainder(BigInteger val) | 获取 this % val 的结果 |
BigInterger max(BigInteger val) | 获取较大值 |
BigInterger min(BigInteger val) | 获取较小值 |
6.3 BigDecimal类
一般的Float
类和Double
类可以用来做一般的科学计算或工程计算,但在商业计算等对求数字精度要求比较高的场合中,就不能使用Float
类和Double
类,可以考虑使用BigDecimal
类。BigDecimal
类支持任何精度的定点数。同样BigDecimal
类不是包装类,故不支持自动装箱与拆箱,如果要用它表示数字,则只能通过对应的构造器来创建对象。
BigDecimal(String val)
:将数字的十进制字符串表示形式转换为BigDecimal
对象。BigDecimal(double val)
:将double
类转换为BigDecimal
类。
同样,要对BigDecimal
对象进行数学运算,也要调用相应的方法来完成,如下表所示。
方法定义 | 描述 |
---|---|
BigDecimal add(BigDecimal val) | 加,返回 this 和 value 的和 |
BigDecimal subtract(BigDecimal val) | 减,返回 this 和 value 的差 |
BigDecimal multiply(BigDecimal val) | 乘,返回 this 和 value 的乘积 |
BigDecimal divide(BigDecimal val, int roundingMode) | 除,如果不能除尽,则需要指定舍人的模式,否则会导致 ArithmeticException |
BigDecimal max(BigDecimal val) | 获取较大值 |
BigDecimal min(BigDecimal val) | 获取较小值 |
6.4 随机
1、Math.random
Java
中,对随机最基本的支持是Math
类中的静态方法random()
,它生成一个
0
∼
1
0\sim1
0∼1的随机数,类型为double
,包括
0
0
0但不包括
1
1
1。
2、java.util.Random
位于java.util
下的Random
类提供了更为丰富的随机方法,它的方法不是静态方法,使用前需要创建Random
实例。
public void nextBytes(byte[] bytes);
public int nextInt();
public int nextInt(int bound);
public int nextInt(int origin, int bound);
public long nextLong();
public long nextLong(long bound);
public long nextLong(long origin, long bound);
public float nextFloat();
public float nextFloat(float bound);
public float nextFloat(float origin, float bound);
public double nextDouble();
public double nextDouble(double bound);
public double nextDouble(double origin, double bound);
public boolean nextBoolean();
除了无参默认构造函数外,Random
类还有一个构造方法,可以接受一个long
类型的种子参数:
public Random(long seed)
种子决定了随机产生的序列,种子相同,产生的随机数序列就是相同的。
@Test
public void testSeed() {
long randomSeed = Double.valueOf(Math.random() * 1000000).longValue();
Random firstRandom = new Random(randomSeed);
Random secondRandom = new Random(randomSeed);
int[] firstRandomIntArray = new int[10];
int[] secondRandomIntArray = new int[10];
for (int i = 0; i < firstRandomIntArray.length; i++) {
firstRandomIntArray[i] = firstRandom.nextInt();
}
for (int i = 0; i < secondRandomIntArray.length; i++) {
secondRandomIntArray[i] = secondRandom.nextInt();
}
assertArrayEquals(firstRandomIntArray, secondRandomIntArray);
}
两个Random
类,他们的种子一样,得到的随机数也是一样。
除了在构造方法中指定种子,Random
类还有一个setter
实例方法:public void setSeed(long seed)
。其效果与在构造方法中指定种子是一样的。
为什么要指定种子呢?指定种子还是真正的随机吗?指定种子是为了实现可重复的随机。比如用于模拟测试程序中,模拟要求随机,但测试要求可重复。种子到底扮演了什么角色呢?随机到底是如何产生的呢?让我们看下随机的基本原理。
2、随机的基本原理
Random
产生的随机数不是真正的随机数,相反,它产生的随机数一般称为伪随机数。真正的随机数比较难以产生,计算机程序中的随机数一般都是伪随机数。伪随机数都是基于一个种子数的,然后每需要一个随机数,都是对当前种子进行一些数学运算,得到一个数,基于这个数得到需要的随机数和新的种子。数学运算是固定的,所以种子确定后,产生的随机数序列就是确定的,确定的数字序列当然不是真正的随机数,但种子不同,序列就不同,每个序列中数字的分布也都是比较随机和均匀的,所以称之为伪随机数。Random
的默认构造方法中没有传递种子,它会自动生成一个种子,这个种子数是一个真正的随机数,如下所示:
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
private static long seedUniquifier() {
// L'Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
for (;;) {
long current = seedUniquifier.get();
long next = current * 1181783497276652981L;
if (seedUniquifier.compareAndSet(current, next))
return next;
}
}
private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
种子是seedUniquifier()
与System.nanoTime()
按位异或的结果,System.nanoTime()
返回一个更高精度(纳秒)的当前时间。简单地说,就是返回当前seedUniquifier
(current
变量)与一个常数181783497276652981L
相乘的结果(next
变量),然后,设置seedUniquifier
的值为next
,使用循环和compareAndSet
都是为了确保在多线程的环境下不会有两次调用返回相同的值,保证随机性。
有了种子数之后,其他数是怎么生成的呢?我们来看一些代码:
public int nextInt() {
return next(32);
}
public long nextLong() {
// it's okay that the bottom word remains signed.
return ((long)(next(32)) << 32) + next(32);
}
public float nextFloat() {
return next(Float.PRECISION) * FLOAT_UNIT;
}
public boolean nextBoolean() {
return next(1) != 0;
}
它们都调用了next(int bits)
,生成指定位数的随机数,我们来看下它的代码:
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
简单地说,就是使用了如下公式:
nextseed = (oldseed * multiplier + addend) & mask;
旧的种子(oldseed
)乘以一个数(multiplier
),加上一个数addend
,然后取低
48
48
48位作为结果(mask
相与)。为什么采用这个方法?这个方法为什么可以产生随机数?这个方法的名称叫线性同余随机数生成器(linear congruential pseudorandom number generator
)。
我们需要知道的基本原理是:随机数基于一个种子,种子固定,随机数序列就固定,默认构造方法中,种子是一个真正的随机数。