1.简介

 float和double类型的主要设计目标是为了科学计算和工程计算。它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。但是,商业计算往往要求结果精确,这时候BigDecimal就登场了。

2.实例化BigDecimal

构造方法

1.public BigDecimal(double val)    将double表示形式转换为BigDecimal *不建议使用

2.public BigDecimal(int val)  将int表示形式转换成BigDecimal

3.public BigDecimal(String val)  将String表示形式转换成BigDecimal

 BigDecimal bigDecimalDouble=new BigDecimal(3.3);
 BigDecimal bigDecimalInt=new BigDecimal(3);
 BigDecimal bigDecimalString=new BigDecimal(\"3.3\");

运行结果:

\"\"

为什么会出现这种情况?

    JDK的描述:1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

那么我们应该怎么办?

    可以先使用Double.toString(double)转成String,然后使用String构造方法

BigDecimal bigDecimalDouble=new BigDecimal(Double.toString(3.3));

3.BigDecimal的四则运算

对于常用的加减乘除BigDecimal有着相应的成员方法

public BigDecimal add(BigDecimal value);                        //加法

public BigDecimal subtract(BigDecimal value);                   //减法 

public BigDecimal multiply(BigDecimal value);                   //乘法

public BigDecimal divide(BigDecimal value);                     //除法

用法如下:

        BigDecimal a = new BigDecimal(\"6.6\");
        BigDecimal b = new BigDecimal(\"3.3\");

        System.out.println(\"a+b=\"+a.add(b));
        System.out.println(\"a-b=\"+a.subtract(b));
        System.out.println(\"a*b=\"+a.multiply(b));
        System.out.println(\"a/b=\"+a.divide(b));

这里有一点需要注意的是除法运算divide.

 BigDecimal除法可能出现不能整除的情况,比如 6.6/2.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

其实divide方法有可以传三个参数

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 
第一参数表示除数, 第二个参数表示小数点后保留位数,
第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种
ROUND_CEILING    //向正无穷方向舍入

ROUND_DOWN    //向零方向舍入

ROUND_FLOOR    //向负无穷方向舍入

ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5

ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

ROUND_HALF_UP    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式

ROUND_UP    //向远离0的方向舍入

需要对BigDecimal进行截断和四舍五入可用setScale方法


        BigDecimal a = new BigDecimal(\"3.1415926\");

        a = a.setScale(2, RoundingMode.HALF_UP);    //保留2位小数,且四舍五入
        System.out.println(a);
    

       每次加减乘除的时候最终都返回一个新的BigDecimal对象,因为BigDecimal是不可变的,在进行每一次运算时,都会产生一个新的对象。

        BigDecimal a = new BigDecimal(\"4.4\");
        BigDecimal b = new BigDecimal(\"2.2\");
        a.add(b);

        System.out.println(a);  //输出6.6 原来的a不变

汇总

1.创建时尽可能使用String类型的构造函数;

2.加法:add(BigDecimal value);   减法:subtract(BigDecimal value); 

   乘法:multiply(BigDecimal value);  除法:divide(BigDecimal value);

3.BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要       保存操作后的值。

4.我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意。

收藏 打印