java常用API-BigDecimal

104 阅读3分钟

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
  1. 参数类型为double的构造方法的结果又一定的不可预知性,new BigDecimal(0.001);的时候它实际上等于0.001000000000000000020816681711721685132943093776702880859375,主要是0.001无法准确的表示为double
  2. String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言, 通常建议优先使用String构造方法。
  3. 当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方法设置精确的小数点

总结

  1. 在需要精确的小数计算时再使用BigDecimal,BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDecimal。
  2. 一般尽量使用参数类型为String的构造函数,避免计算出现错误达不到预期的值。
  3. BigDecimal都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。