BigInteger
在 Java 中,由 CPU 原生提供的整型最大范围是 64 位 long
型整数。使用 long
型整数可以直接通过 CPU 指令进行计算,速度非常快。如果我们使用的整数范围超过了 long
型就只能用软件来模拟一个大整数。java.math.BigInteger
就是用来表示任意大小的整数。BigInteger
内部用一个 int[]
数组来模拟一个非常大的整数:
1 | BigInteger bi = new BigInteger("1234567890"); |
使用 BigInteger` 做运算的时候,只能使用实例方法,例如:
1 | BigInteger i1 = new BigInteger("1234567890"); |
和 long
型整数运算比,BigInteger
不会有范围限制,但缺点是速度比较慢。也可以把 BigInteger
转换成 long
型:
1 | BigInteger i = new BigInteger("123456789000"); |
使用 longValueExact()
方法时,如果超出了 long
型的范围,会抛出 ArithmeticException
。
BigInteger
和 Integer
、Long
一样,也是不可变类,并且也继承自 Number
类。因为 Number
定义了转换为基本类型的几个方法:
- 转换为
byte
:byteValue()
- 转换为
short
:shortValue()
- 转换为
int
:intValue()
- 转换为
long
:longValue()
- 转换为
float
:floatValue()
- 转换为
double
:doubleValue()
因此,通过上述方法,可以把 BigInteger
转换成基本类型。如果 BigInteger
表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用intValueExact()
、longValueExact()
等方法,在转换时如果超出范围,将直接抛出ArithmeticException
异常。
如果 BigInteger
的值甚至超过了float
的最大范围(3.4x1038),那么返回的float是什么呢?
1 | public class Test{ |
BigDecimal
和 BigInteger
类似,BigDecimal
可以表示一个任意大小且精度完全准确的浮点数,常用于财务计算。如果查看 BigDecimal
的源码,可以发现,实际上一个 BigDecimal
是通过一个 BigInteger
和一个 scale
来表示的,即 BigInteger
表示一个完整的整数,而 scale
表示小数位数:
1 | public class BigDecimal extends Number implements Comparable<BigDecimal> { |
BigDecimal
也是从 Number
继承的,也是不可变对象。
通过 BigDecimal
的 stripTrailingZeros()
方法,可以将一个 BigDecimal
格式化为一个相等的,但去掉了末尾0的 BigDecimal
:
1 | BigDecimal d1 = new BigDecimal("123.4500"); |
如果一个 BigDecimal
的 scale()
返回负数,例如,-2
,表示这个数是个整数,并且末尾有2个0。
可以对一个 BigDecimal
设置它的 scale
,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:
1 | public class Main { |
对BigDecimal
做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断:
1 | BigDecimal d1 = new BigDecimal("123.456"); |
在比较两个 BigDecimal
的值是否相等时,要特别注意,使用 equals()
方法不但要求两个 BigDecimal
的值相等,还要求它们的 scale()
相等:
1 | BigDecimal d1 = new BigDecimal("123.456"); |
必须使用 compareTo()
方法来比较,它根据两个值的大小分别返回负数、正数和0
,分别表示小于、大于和等于。