BigDecimal类型详解

目录

1.BigDecimal介绍: 

2.BigDecimal构造方法

3.BigDecilmal计算

4.java BigDecimal比较大小

5.关于BigDecimal格式化

6.总结


1.BigDecimal介绍: 

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

为什么不建议采用第一种构造方法呢?来看例子

public static void main(String[] args)
    {
        BigDecimal bigDecimal = new BigDecimal(2);
        BigDecimal bDouble = new BigDecimal(2.3);
        BigDecimal bString = new BigDecimal("2.3");
        System.out.println("bigDecimal=" + bigDecimal);
        System.out.println("bDouble=" + bDouble);
        System.out.println("bString=" + bString);
    }

bDouble结果会有精度的问题
为什么会出现这种情况呢?

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

        2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。

 

当double必须用作BigDecimal的源时,请使用Double.toString(double)转成String,然后使用String构造方法,或使用BigDecimal的静态方法valueOf
public static void main(String[] args)
    {
        BigDecimal bDouble1 = BigDecimal.valueOf(2.3);
        BigDecimal bDouble2 = new BigDecimal(Double.toString(2.3));

        System.out.println("bDouble1=" + bDouble1);
        System.out.println("bDouble2=" + bDouble2);
        
    }

3.BigDecilmal计算

BigDecimal add(BigDecimal val) //BigDecimal 加法

BigDecimal subtract (BigDecimal val) //BigDecimal 减法

BigDecimal multiply (BigDecimal val)  //BigDecimal 乘法

BigDecimal divide (BigDecimal val,RoundingMode mode)  除法

具体使用计算: 


 (1) 加:   a.add(b);

 (2) 减:   a.subtract(b);

 (3) 乘:   a.multiply(b);

 (4) 除:   a.divide(b,2);//2为精度取值
除法细解:
  //注意以下相除会抛出异常,原因: 通过BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,就会抛异常 
  BigDecimal divideBg = a.divide(b);  
 //解决方法是:设置精确度;就是给divide设置精确的小数点
  divide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)  
 //其中的第二个参数表示的是:保留小数点之后多少位 

异常:BigDecimal不整除抛出的异常,请设置精确度!
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1278)
at main.Main.main(Main.java:41)

下面我们来看看除法的详细用法:
   divide(BigDecimal divisor, int scale, introundingMode)


(5)BigDecimal的setScale方法

BigDecimal.setScale()

方法用于格式化小数点

表示保留一位小数,默认用四舍五入方式   setScale(1)

直接删除多余的小数位,如2.35会变成2.3 setScale(1,BigDecimal.ROUND_DOWN)

进位处理,2.35变成2.4  setScale(1,BigDecimal.ROUND_UP)

四舍五入,2.35变成2.4  setScale(1,BigDecimal.ROUND_HALF_UP)

四舍五入,2.35变成2.3,如果是5则向下舍setScaler(1,BigDecimal.ROUND_HALF_DOWN)

 
注意点一

scale指的是你小数点后的位数。
scale()就是BigDecimal类中的方法。如

BigDecimal b = new BigDecimal("123.456");

b.scale()返回的就是3

注意点二

roundingMode是小数的保留模式。它们都是BigDecimal中的常量字段,

有很多种,如
BigDecimal.ROUND_HALF_UP表示的就是4舍5入

注意点三

divide(BigDecimal divisor, int scale, introundingMode)的意思是说:
我用一个BigDecimal对象除以divisor后的结果,并且要求这个结果保留有scale个小数位,roundingMode表示的就是保留模式是什么,是四舍五入啊还是其它的


BigDecimal aa = new  BigDecimal(135.95 ); 

BigDecimal bb=new  BigDecimal("100" ); 

BigDecimal result=aa.multiply(bb);  //做加法

java中BigDecimal类型的可以转换到double类型: 

  用 变量.doubleValue();函数  即可将 BigDecimal 类型数据 转化为 double类型!

4.java BigDecimal比较大小

可以通过BigDecimal的compareTo方法来进行比较。
返回的结果是int类型,-1表示小于,0是等于,1是大于。

看下面这个例子:
BigDecimal a = new BigDecimal("1.00");
BigDecmial b = new BigDecimal(1);

想比较一下a和b的大小,一般都会用equals

System.out.println(a.equals(b));
但是输出结果是:false
原因是:BigDecimal比较时,不仅比较值,而且还比较精度?


if(a.compareTo(b)==0) 结果是true

比较大小可以用 a.compareTo(b)
返回值    -1 小于   0 等于    1 大于

//前提为a、b均不能为null
if(a.compareTo(b) == -1){
    System.out.println("a小于b");
}
 
if(a.compareTo(b) == 0){
    System.out.println("a等于b");
}
 
if(a.compareTo(b) == 1){
    System.out.println("a大于b");
}
 
if(a.compareTo(b) > -1){
    System.out.println("a大于等于b");
}
 
if(a.compareTo(b) < 1){
    System.out.println("a小于等于b");
}

 BigDecimal取其中最大、最小值、绝对值、相反数:


  a.max (b) //比较取最大值

  a.min(b) //比较取最小值

  a.abs()//取最绝对值

  a.negate()//取相反数

下面是注意: 

BigDecimal枚举常量用法摘要  :

CEILING  
          向正无限大方向舍入的舍入模式。
DOWN  
          向零方向舍入的舍入模式。
FLOOR  
          向负无限大方向舍入的舍入模式。
HALF_DOWN  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
HALF_EVEN  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
HALF_UP  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
UNNECESSARY  
          用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
UP  
          远离零方向舍入的舍入模式。

5.关于BigDecimal格式化

public String formatValue(Object value){
        String content = null;
        if (value == null) {
             content = "";
         } else {
             if(value instanceof BigDecimal){
                 //conver to fortmat String
                 NumberFormat nf = NumberFormat.getInstance();
                 nf.setMinimumFractionDigits(2);
                 nf.setMaximumFractionDigits(2);
                 content = nf.format(value); 
             }else{
                 content = String.valueOf(value);
             }
         }
        return content;
    }

//使用这样一个方法可以达到格式化的效果,其中value instanceof BigDecimal,表示的是字符类型是BigDecimal类型的时候执行,
//这里的NumberFormat就表示字符类型,下面的两句代码就表示小数点后面的精确位数。

这里还要提到NumberFormat的其他两个类型:

getCurrencyInstance(): 返回当前默认 环境的货币格式

CurrencyInstance(): 返回指定语言 环境的数字格式,一般是百分比格式

6.总结

   (1)商业计算使用BigDecimal。

        (2)尽量使用参数类型为String的构造函数。

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

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

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值