BigInteger与BigDecimal
BigInteger
在Java中,由CPU原生提供的整型最大范围是64位long
型整数。使用long
型整数可以直接通过CPU指令进行计算,速度非常快。
如果我们使用的整数范围超过了long
型怎么办?这个时候,就只能用软件来模拟一个大整数。java.math.BigInteger
就是用来表示任意大小的整数。BigInteger
内部用一个int[]
数组来模拟一个非常大的整数:
BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000
对BigInteger
做运算的时候,只能使用实例方法,例如,加法运算:
BigInteger i1 = new BigInteger("1234567890");
BigInteger i2 = new BigInteger("12345678901234567890");
BigInteger sum = i1.add(i2); // 12345678902469135780
和long
型整数运算比,BigInteger
不会有范围限制,但缺点是速度比较慢。
也可以把BigInteger
转换成long
型:
BigInteger i = new BigInteger("123456789000");
System.out.println(i.longValue()); // 123456789000
System.out.println(i.multiply(i).longValueExact()); // java.lang.ArithmeticException: BigInteger out of long range
BigInteger
和Integer
、Long
一样,也是不可变类,并且也继承自Number
类。因为Number
定义了转换为基本类型的几个方法:
- 转换为
byte
:byteValue()
- 转换为
short
:shortValue()
- 转换为
int
:intValue()
- 转换为
long
:longValue()
- 转换为
float
:floatValue()
- 转换为
double
:doubleValue()
BigInteger num1 = new BigInteger("123456789123123123");
BigInteger num2 = new BigInteger("987654321321321321",10);
BigInteger num3 = new BigInteger("10010101", 2);
System.out.println(num1);
System.out.println(num2);
System.out.println(num3.toString());
//BigInteger的四则运算 必须使用BigInteger自带的方法
System.out.println(num1.add(num2)); //加法 num1 + num2
System.out.println(num1.subtract(num2)); //减法 num1 - num2
System.out.println(num1.multiply(num2)); //乘法 num1 * num2
System.out.println(num1.divide(num2)); //除法 num1 / num2 整除的结果 无小数
System.out.println(num1.subtract(num2).abs()); //绝对值
可以把BigInteger
转换成基本类型。如果BigInteger
表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用intValueExact()
、longValueExact()
等方法
BigInteger
用于表示任意大小的整数;
BigInteger
是不变类,并且继承自Number
;
将BigInteger
转换成基本类型时可使用longValueExact()
等方法保证结果准确。
BigDecimal
和BigInteger
类似,BigDecimal
可以表示一个任意大小且精度完全准确的浮点数。
BigDecimal bd = new BigDecimal("123.4567");
System.out.println(bd.multiply(bd)); // 15241.55677489
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
通过BigDecimal
的stripTrailingZeros()
方法,可以将一个BigDecimal
格式化为一个相等的,但去掉了末尾0的BigDecimal
:
BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();
System.out.println(d1.scale()); // 4
System.out.println(d2.scale()); // 2,因为去掉了00
BigDecimal d3 = new BigDecimal("1234500");
BigDecimal d4 = d3.stripTrailingZeros();
System.out.println(d3.scale()); // 0
System.out.println(d4.scale()); // -2
如果一个BigDecimal
的scale()
返回负数,例如,-2
,表示这个数是个整数,并且末尾有2个0。
可以对一个BigDecimal
设置它的scale
,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断
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);
}
}
无论是BigInteger还是BigDecimal,它们的本质其实就是数组
后续的四则运算其是都是基于数组进行的四则运算
1234 - [1,2,3,4]
6543 - [6,5,4,3]
[1,2,3,4]
+[6,5,4,3]
[7,7,7,7]
所以计算效率不是特别的高,甚至很慢
BigDecimal num1 = new BigDecimal("12.13414");
BigDecimal num2 = new BigDecimal("39.1200");
BigDecimal num3 = new BigDecimal("123.00");
BigDecimal num4 = new BigDecimal("100");
BigDecimal num5 = new BigDecimal("50.00");
System.out.println(num1.add(num2));
System.out.println(num1.subtract(num2));
System.out.println(num1.multiply(num2));
System.out.println(num4.divide(num5)); //能除尽
//如果除不尽 需要制定截止位置scale 保留方式:四舍五入
BigDecimal
也是从Number
继承的,也是不可变对象。
**BigDecimal
用于表示精确的小数,**
比较BigDecimal
的值是否相等,必须使用compareTo()
而不能使用equals()
。