java常用API-BigDecimal
概述
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。
一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。 所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
常用构造函数
| 构造器 | 说明 |
|---|---|
| public BigDecimal(double val) 注意:不推荐使用这个 | 将double转换为BigDecimal |
| public BigDecimal(String val) | 将String转为BigDecimal |
- 参数类型为double的构造方法的结果又一定的不可预知性,
new BigDecimal(0.001);的时候它实际上等于0.001000000000000000020816681711721685132943093776702880859375,主要是0.001无法准确的表示为double - String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言, 通常建议优先使用String构造方法。
- 当double必须用作BigDecimal的源时,请使用static valueOf(double)方法。可以将double转换为BigDecimal
double x=0.001;
double y=0.021;
System.out.println(x+y);//直接加减会出现结果失真的问题
BigDecimal bigde=new BigDecimal("0.001");
BigDecimal bigde1=new BigDecimal("0.021");
//不建议直接传入一个double类型的值,这样加减可能还是会出现结果失真
BigDecimal bigde=new BigDecimal(0.001);
BigDecimal bigde1=new BigDecimal(0.021);
System.out.println(bigde3);
//0.001000000000000000020816681711721685132943093776702880859375
常用的方法
| 方法名 | 说明 |
|---|---|
| public static BigDecimal valueof(double val) | 转换一个double成BigDecimal |
| public BigDecimal add(BigDecimal b) | 加法 |
| public BigDecimal subtract(BigDecimal b) | 减法 |
| public BigDecimal multiply(BigDecimal b) | 乘法 |
| public BigDecimal divide( BigDecimal b) | 除法 |
| public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式) | 除法、可以控制精确到小数几位 |
| public double doublevalue() | 将BigDecimal转换为double |
基本使用
package 常用API2;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
public class mathDemo {
public static void main(String[] args) {
Random random=new Random();
int i = random.nextInt(10);
System.out.println(i);
double x=0.001;
double y=0.021;
System.out.println(x+y);//直接加减会出现结果失真的问题
BigDecimal bigde=new BigDecimal("0.001");
BigDecimal bigde1=new BigDecimal("0.021");
//不建议直接传入一个double类型的值,这样加减可能还是会出现结果失真
BigDecimal bigde3=new BigDecimal(0.001);
// BigDecimal bigde1=new BigDecimal(0.021);
System.out.println(bigde3);
//0.001000000000000000020816681711721685132943093776702880859375
//加法
BigDecimal add = bigde.add(bigde1);
System.out.println(add);//0.022
//减法
BigDecimal subtract = bigde.subtract(bigde1);
System.out.println(subtract); //-0.020
//乘法
BigDecimal multiply = bigde.multiply(bigde1);
System.out.println(multiply);//0.000021
//除法
BigDecimal divide = bigde.divide(bigde);
System.out.println(divide); //1
//保留3位小数,并且想上取整
BigDecimal divides = bigde.divide(bigde, 3, RoundingMode.CEILING);
System.out.println(divides); //1.000
//通过valueOf 将double 转位BigDecimal
BigDecimal bigDecimal = BigDecimal.valueOf(x);
System.out.println(bigDecimal); //0.001
//通过 doubleValue 将BigDecimal 转位double类型
double v = bigDecimal.doubleValue();
System.out.println(v); //0.001
}
}
BigDecimal大小比较
java中对BigDecimal比较大小一般用的是bigdemical的compareTo方法
int i1 = bigde.compareTo(bigde1);
System.out.println(i1); //-1
比较规则:
int i1 = bigdemical.compareTo(bigdemical2);
i1 = -1,表示bigdemical小于bigdemical2;
i1= 0,表示bigdemical等于bigdemical2;
i1= 1,表示bigdemical大于bigdemical2;
一般出现的异常
出现在除法中
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
通过BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,就会抛这个异常
解决办法:divide方法设置精确的小数点
总结
- 在需要精确的小数计算时再使用BigDecimal,BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDecimal。
- 一般尽量使用参数类型为String的构造函数,避免计算出现错误达不到预期的值。
- BigDecimal都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。