`
liudeh_009
  • 浏览: 239430 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

BigDecimal在实际项目的应用及遇到的问题

    博客分类:
  • JDK
阅读更多

      我们都知道,java中对大小数,高精度的计算都会用到BigDecimal.但是在实际应用中,运用BigDecimal还是会遇到一些问题.下面说一下我在项目中怎么样BigDecimal和遇到的一些问题. 

 

       1. 对商品的价格进行格式化,比如所有商品的价格保留两位小数

      

    /**
     * 
     * @param bd  商品的价格
     * @param num 保留几位小数,如num = 2
     * @return
     */
    public static String formatPrice(BigDecimal bd,int num){
        if(bd == null || num < 0){
            return null;
        }
        bd = bd.setScale(num, BigDecimal.ROUND_HALF_UP);
        return bd + "";
    }

       其中BigDecimal.ROUND_HALF_UP表示采用"四舍五入"的模式处理价格

 

  2. 将商品的价格由元转为分,便于前端分隔展现

   

    /**
     * 元转换为分
     * @param bd 商品的价格
     * @return
     */
    public static String yuanToCent(BigDecimal bd){
        if(bd == null){
            return null;
        }
        bd = bd.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_EVEN);
        return bd + "";
    }

       其中setScale(0, BigDecimal.ROUND_HALF_EVEN)表示采用"四舍五入"的模式处理价格,并且结果不保留小数.

 

  3. 获取缓存命中率

     

   
   /**
    * 缓存命中率
    * @return
    */
   public static String getHitRate(){
       BigDecimal a = new BigDecimal(cacheCount.longValue()*100);
       BigDecimal b = new BigDecimal(sumCount.longValue());
       if(sumCount.longValue() > 0){
           return "%" + (a.divide(b, 2, BigDecimal.ROUND_HALF_EVEN)); 
       }
       return "0";
   }

 

  4. BigDecimal中对于等于"0"的判断

          在 BigDecimal中,new BigDecimal("0")与new BigDecimal("0.0"),new BigDecimal(0)与new BigDecimal("0.0")都是不等的.但是本质上,它们都是"0".怎么对是否等于"0"进行判断?将BigDecimal类型的值通过调用doubleValue()方法转换为double类型进行比较或通过上面的方法yuanToCent转换一下比较就能解决这个问题.

 

    5.  用BigDecimal进行除法计算时抛出java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result异常.

       比如用new BigDecimal(30).divide(new BigDecimal(7))就会抛这个异常,异常原因:BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,就会抛这个异常.

      解决办法:给divide设置精确的小数点位数或"舍入"模式,如

            new BigDecimal(30).divide(new             BigDecimal(7),BigDecimal.ROUND_HALF_UP).setScale(2,BigDecimal.ROUND_HALF_UP)或

                  new BigDecimal(30).divide(new BigDecimal(7),2,BigDecimal.ROUND_HALF_UP)

     建议采用第二种方式,因为第二种方式的结果精度更高

      

    另外,要注意BigDecimal跟String一样,是不可改变的,比如BigDecimal对象执行setScale(), add()等操作都会返回一个新的BigDecimal.

 

 

5
3
分享到:
评论
8 楼 hellostory 2013-03-29  
liudeh_009 写道
hellostory 写道
liudeh_009 写道
hellostory 写道
引用
  4. BigDecimal中对于等于"0"的判断


System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0.0")));

PS:前台打印BigDecimal数据时,若有小数点,则小数点后面可能会出现很多个0,你怎么处理的?

setScale方法可以设置包含小数点的位数


这我知道,但有一个问题:比如后台需要精度达到6个小数点,如果你设置精度为6位小数,那么前台显示时,你会发现“5.67”仍然会显示“5.670000”


如果只是想把后面没有意义的0去掉,把结果转成double类型输出就可以了


所有就得多写一个FormBean,或多个字段等
7 楼 liudeh_009 2013-03-29  
hellostory 写道
liudeh_009 写道
hellostory 写道
引用
  4. BigDecimal中对于等于"0"的判断


System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0.0")));

PS:前台打印BigDecimal数据时,若有小数点,则小数点后面可能会出现很多个0,你怎么处理的?

setScale方法可以设置包含小数点的位数


这我知道,但有一个问题:比如后台需要精度达到6个小数点,如果你设置精度为6位小数,那么前台显示时,你会发现“5.67”仍然会显示“5.670000”


如果只是想把后面没有意义的0去掉,把结果转成double类型输出就可以了
6 楼 hellostory 2013-03-28  
liudeh_009 写道
hellostory 写道
引用
  4. BigDecimal中对于等于"0"的判断


System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0.0")));

PS:前台打印BigDecimal数据时,若有小数点,则小数点后面可能会出现很多个0,你怎么处理的?

setScale方法可以设置包含小数点的位数


这我知道,但有一个问题:比如后台需要精度达到6个小数点,如果你设置精度为6位小数,那么前台显示时,你会发现“5.67”仍然会显示“5.670000”

5 楼 liudeh_009 2013-03-28  
hellostory 写道
引用
  4. BigDecimal中对于等于"0"的判断


System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0.0")));

PS:前台打印BigDecimal数据时,若有小数点,则小数点后面可能会出现很多个0,你怎么处理的?

setScale方法可以设置包含小数点的位数
4 楼 liudeh_009 2013-03-28  
java_林 写道
第4条没
new BigDecimal("0.0"),new BigDecimal(0)

不等是指业务上还是程序上?compareTo方法呢?

程序上的,我以前不知道可以用compareTo,现在发现用compareTo比较更简单,刚才查了一下,发现compareTo方法不需要两个BigDecimal值具有相同的精度就可以比较大小
3 楼 java_林 2013-03-28  
第4条没
new BigDecimal("0.0"),new BigDecimal(0)

不等是指业务上还是程序上?compareTo方法呢?
2 楼 hellostory 2013-03-28  
引用
  4. BigDecimal中对于等于"0"的判断


System.out.println(new BigDecimal("0").compareTo(new BigDecimal("0.0")));

PS:前台打印BigDecimal数据时,若有小数点,则小数点后面可能会出现很多个0,你怎么处理的?
1 楼 ooo456mmm 2013-03-27  
还要注意一点:
在构造BigDecimal的时候,尽量使用“”将数据引起来(特别是小数),否则会出现计算不准确的问题
在做除法的时候,new BigDecimal(30).divide(new BigDecimal(7),2,BigDecimal.ROUND_HALF_UP),这种精度高。

相关推荐

Global site tag (gtag.js) - Google Analytics