大数值

引言: 大数值

大数值

先来看一个例子吧:

1
2
System.out.println(Long.MAX_VALUE);//9223372036854775807
System.out.println(Long.MAX_VALUE+5);//-9223372036854775804 已经崩溃了

long是最大的整型了,但是我们遇到比再大一点的数怎么办?

这时候就引入了大数值两个类BigIntegerBigDecimal

这两个类并非是一个数,是模拟出来的数,在类的内部使用了数组(BigInteger使用了int[])来模拟任意大小的数,前者是整数,后者是浮点数

BigInteger

BigInteger可以表示任意大小的整数

1
2
3
4
System.out.println(Long.MAX_VALUE);//9223372036854775807
System.out.println(Long.MAX_VALUE+5);//-9223372036854775804 已经崩溃了
BigInteger big = new BigInteger(String.valueOf(Long.MAX_VALUE));
System.out.println(big.add(new BigInteger("5")));//9223372036854775812 依然ok

但是BigInteger的加减乘除只可以使用方法来运算,而且运算对象只能是相同的类型

1
2
3
BigInteger big1 = new BigInteger(String.valueOf(Long.MAX_VALUE));
BigInteger big2 = new BigInteger(String.valueOf(Long.MIN_VALUE));
System.out.println(big1.add(big2));//-1

转换

转换成基本类型,例如转换为long

1
2
3
4
5
6
7
8
public long longValue()
public long longValueExact()
/*两个方法都可以将大数值转换为 long 型
不同的是
如果大数值的数值大小超过long的范围,
第一个方法不会报错,但是转化后的数据不正确。
第二个方法会报出异常
*/

如下

1
2
3
4
BigInteger big1 = new BigInteger(String.valueOf(Long.MAX_VALUE));
BigInteger big2 = new BigInteger(String.valueOf(Long.MAX_VALUE));
long l1 = big1.add(big2).longValue();//值是 -2
long l2 = big1.add(big2).longValueExact();//ArithmeticException: BigInteger out of long range

同样转换 int float double short byte都有对应的方法

如果BigInteger的值甚至超过了float的最大范围(3.4x10^38),那么返回的float是什么呢

1
2
3
BigInteger n = new BigInteger("999999").pow(99);
float f = n.floatValue();
System.out.println(f);//Infinity

BigDecimal

如果查看BigDecimal的源码,可以发现,实际上一个BigDecimal是通过一个BigInteger和一个scale来表示的,即BigInteger表示一个完整的整数,而scale表示小数位数:

1
2
3
4
public class BigDecimal extends Number implements Comparable<BigDecimal> {
private final BigInteger intVal;
private final int scale;
}

基本方法

1
2
3
4
5
6
7
8
9
10
public int scale()
//返回小数点后数字个数,如果是一个整数则会返回负数,例如:-2,代表数字末尾有2个0 例如 3400

public BigDecimal setScale(int newScale,
int roundingMode)
//按设置的newScale个数,对应的roundingMode方法来截断大数值
//常见的截断方法:RoundingMode.HALF_UP 四舍五入、RoundingMode.DOWN 直接截断

public BigDecimal stripTrailingZeros()
//去除末尾多余的 0 ,例如3.1400 -> 3.14

除此之外还有加减乘除方法,其中除法要注意,有可能出现除不尽的状况,要注意添加截断方法

1
2
3
4
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,因为除不尽

BigDecimal可以做除法同时求余数divideAndRemainder()

1
2
3
4
5
6
7
8
BigDecimal n = new BigDecimal("12.345");
BigDecimal m = new BigDecimal("0.12");
BigDecimal[] dr = n.divideAndRemainder(m);
/*
数组的共两个:第一个是商第二个是余数
*/
System.out.println(dr[0]); // 102
System.out.println(dr[1]); // 0.105

比较

1
2
3
4
5
6
7
equals()
/* equals方法比较时,会比较scale()的值
所以 3.14和3.1400使用equals方法比较时,大小是不同的
*/

compareTo()
//这个方法根据两个值的大小返回正数负数0,表示大于小于和等于

所以比较两个BigDecimal的时候,使用compareTo比较

廖雪峰官方网站
官方API