BigDecimal带精度的运算

转自: http://www.360doc.com/content/10/1108/17/3715754_67678687.shtml


之前提到过在商业运算中要使用BigDecimal来进行相关的钱的运算(Java中使用BigDecimal进行浮点数高精度计算),可是实际使用中,简单的用BigDecimal还是出现了一些小问题。

Java代码
  1. BigDecimal a = new BigDecimal(998.01);   
  2. BigDecimal b=new BigDecimal("100");   
  3. System.out.println(a.multiply(b));   
  4.   
  5. BigDecimal aa = new BigDecimal(135.95);   
  6. BigDecimal bb=new BigDecimal("100");   
  7. System.out.println(aa.multiply(bb));   
  8.   
  9.   
  10. BigDecimal test = new BigDecimal(4.015);   
  11. BigDecimal test1 = new BigDecimal(100);   
  12. System.out.println(test.multiply(test1));  

输出结果为: 

  1. 99800.999999999999090505298227071762084960937500  
  2. 13594.99999999999886313162278383970260620117187500  
  3. 401.49999999999996802557689079549163579940795898437500   

出现这种情况的原因就是没有使用BigDecimal的精度。不罗嗦了,直接写上使用BigDecimal的带精度的运算。

比较简单,看代码:

BigDecimal aa = new BigDecimal(135.95);   

  1. BigDecimal bb=new BigDecimal("100");   
  2. BigDecimal result=aa.multiply(bb);   
  3. System.out.println(result.setScale(2,BigDecimal.ROUND_HALF_EVEN));  
BigDecimal aa = new BigDecimal(135.95);
BigDecimal bb=new BigDecimal("100");
BigDecimal result=aa.multiply(bb);
System.out.println(result.setScale(2,BigDecimal.ROUND_HALF_EVEN));

此时的输出结果为:13595.00  

最主要的是运用了:

Java代码
  1. result.setScale(2,BigDecimal.ROUND_HALF_EVEN)  

看一下BigDecimal的setScale的api

BigDecimal的API 写道
可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScale 和 round)返回 BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeft 和 movePointRight)返回从操作数创建的 BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。
 
Java代码
  1. setScale   
  2.   
  3. public BigDecimal setScale(int newScale,   
  4.                            int roundingMode)   
  5. 返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,   
  6. 以维护其总值。如果该操作减少标度,则非标度值必须被除(而不是乘),并且该值可以更改;在这种情况下,将指定的   
  7. 舍入模式应用到除法中。   
  8. 注意,由于 BigDecimal 对象是不可变的,此方法的调用不会 导致初始对象被修改,   
  9. 这与使用名为 setX 变异字段 X 方法的常规约定相反。相反,setScale 返回具有适当标度的对象;   
  10. 返回的对象不一定是新分配的。   
  11.   
  12. 相对于此遗留方法,应优先使用新的 setScale(int, RoundingMode) 方法。   
  13.   
  14. 参数:   
  15. newScale - 要返回的 BigDecimal 值的标度。   
  16. roundingMode - 要应用的舍入模式。   
  17. 返回:   
  18. 一个 BigDecimal,其标度为指定值,其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。  
setScale
public BigDecimal setScale(int newScale,int roundingMode)
返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,
以维护其总值。如果该操作减少标度,则非标度值必须被除(而不是乘),并且该值可以更改;在这种情况下,将指定的
舍入模式应用到除法中。
注意,由于 BigDecimal 对象是不可变的,此方法的调用不会 导致初始对象被修改,
这与使用名为 setX 变异字段 X 方法的常规约定相反。相反,setScale 返回具有适当标度的对象;
返回的对象不一定是新分配的。
相对于此遗留方法,应优先使用新的 setScale(int, RoundingMode) 方法。
参数:
newScale - 要返回的 BigDecimal 值的标度。
roundingMode - 要应用的舍入模式。
返回:
一个 BigDecimal,其标度为指定值,其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。

RoundingMode的API

 

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

 看完这些前面那个:

 Java代码

result.setScale(2,BigDecimal.ROUND_HALF_EVEN)  

   的意思就是,将这个BigDecimal小数点后保留2位,四舍五入的方式为向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

ok,记录完毕,看来以后要用bigDecimal还必须要用它这个scale的功能来保证精度,不然还是跟double一样会出现悲剧!



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值