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底层的一些实现细节,导致出现错误,需要多加注意。