1、BigInteger
我们知道java中long类型可以提供最大范围整数,但是超过了怎么半
java.math.BigInteger就是用来表示任意大小的整数
看下面:
BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000
BigInteger和Integer、Long一样,也是不可变类,并且也继承自Number类。因为Number定义了转换为基本类型的几个方法:
转换为byte:byteValue()
转换为short:shortValue()
转换为int:intValue()
转换为long:longValue()
转换为float:floatValue()
转换为double:doubleValue()
2、BigDecimal
老生常谈的问题就是,几乎所有编程语言都会有浮点数精度问题,是因为计算机采用二进制的原因,浮点数无法用二进制数精确表示。举个例子:
3 二进制表示11 没问题
0.5 二进制表示0.1 没问题
0.6 二进制表示0.1001 1001 1001 1001 ……
为什么会这样?
下面具体计算一下0.6的小数表示过程,遵循 乘2取整、顺序排列
0.6 * 2 = 1.2 ——————- 1
0.2 * 2 = 0.4 ——————- 0
0.4 * 2 = 0.8 ——————- 0
0.8 * 2 = 1.6 ——————- 1
0.6 * 2 = 1.2 ——————- 1
…………
可以发现在该计算中已经出现了循环,0.6用二进制表示为 0.1001 1001 1001 1001 ……
Java中为了解决这个问题,和BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数。
BigDecimal bd = new BigDecimal("123.4567");
System.out.println(bd.multiply(bd)); // 15241.55677489 db的平方
BigDecimal用scale()表示小数位数,例如:
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("1234500");
System.out.println(d1.scale()); // 2,两位小数
System.out.println(d2.scale()); // 4
System.out.println(d3.scale()); // 0
这里可以对浮点数进行截断或者四舍五入
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
public static void main(String[] args) {
BigDecimal d1 = new BigDecimal("123.456789");
BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568
BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截断,123.4567
System.out.println(d2);
System.out.println(d3);
}
}
对BigDecimal做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断:
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("23.456789");
BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入
BigDecimal d4 = d1.divide(d2); // 报错:ArithmeticException,因为除不尽
在作比较时,用compareTo,不要用equals
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("123.45600");
System.out.println(d1.equals(d2)); // false,因为scale不同
System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2
System.out.println(d1.compareTo(d2)); // 0
3、Math
基本用法
// 绝对值
Math.abs(-100); // 100
Math.abs(-7.8); // 7.8
// 最大值或者最小值
Math.max(100, 99); // 100
Math.min(1.2, 2.3); // 1.2
// 计算指数
Math.pow(2, 10); // 2的10次方=1024
// 计算平方根
Math.sqrt(2); // 1.414...
// 计算e的指数
Math.exp(2); // 7.389...
// 计算e的对数
Math.log(4); // 1.386...
// 计算以10为底的对数
Math.log10(100); // 2
// 三角函数
Math.sin(3.14); // 0.00159...
Math.cos(3.14); // -0.9999...
Math.tan(3.14); // -0.0015...
Math.asin(1.0); // 1.57079...
Math.acos(1.0); // 0.0
// 数学常量
double pi = Math.PI; // 3.14159...
double e = Math.E; // 2.7182818...
Math.sin(Math.PI / 6); // sin(π/6) = 0.5
// 四舍五入得到一个整数
Math.round(1.52) // 2
另外,Math里面有一个随机函数
Math.random(); // 0.53907... 每次都不一样,左开右闭
下面例子可以,生成一个区间在[MIN, MAX)的随机数,可以借助Math.random()实现,计算如下:
public class Main {
public static void main(String[] args) {
double x = Math.random(); // x的范围是[0,1)
double min = 10;
double max = 50;
double y = x * (max - min) + min; // y的范围是[10,50)
long n = (long) y; // n的范围是[10,50)的整数
System.out.println(y);
System.out.println(n);
}
}
4、Random
Random用来创建伪随机数。所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的
Random r = new Random();
r.nextInt(); // 2071575453,每次都不一样
r.nextInt(10); // 5,生成一个[0,10)之间的int
r.nextLong(); // 8811649292570369305,每次都不一样
r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
r.nextDouble(); // 0.3716...生成一个[0,1)之间的double