BigDecimal的使用

这次在APP开发中我遇到了精确计算问题.比如服务器给我一个百分比,我根据这个比例计算出价格,送到服务器.比如:2100.05 * 0.2计算的结果并不是420.01,而是420.010000000005.在《Java解惑》这本书中有2.00 - 1.10不是0.9而是0.899999999999999.原因是1.1 这个数字不能被精确表示成为一个double,因此它被表示成为最接近它的double值。二进制浮点对于货币计算是非常不适合的,因为它不可能将0.1——或者10的其它任何次负幂——精确表示为一个长度有限的二进制小数.也就是计算机不认识十分之一,就像我们10进制不认识三分之一一样.书中给出了其中的一些解决方法,比如尽量将将单位缩小,将”元”换成分,避免有float或者double类型的计算.可是正如我碰到的这个问题是没有办法避免的(关键是需求经理不让改),那就只能使用BigDecimal来进行计算.下面就具体说一说BigDecimal的使用方式.


BigDecimal进行四则运算

使用BigDecimal,首先就需要构造一个BigDecimal.
比如我们计算2.00 + 1.10

BigDecimal bstr1 = new BigDecimal(“2.00”);
BigDecimal bstr2 = new BigDecimal(“1.10”);
BigDecimal bstr3 = null;
//表示两者相加:
bstr3 = bstr1.add(bstr2);
在这里推荐使用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用它的参数的“精确”值来创建一个实例:new BigDecimal(.1)将返回一个表示0.100000000000000055511151231257827021181583404541015625 的BigDecimal.
如果我们想再次赋值给一个int,long,float,double.使用对应的方法即可,如:
float f1;
int i1;
f1 = bstr3.floatValue();
i1 = bstr3.intValue();
//表示两者相减:
bstr3 = bstr1.subtract(bstr2);
//表示两者相乘:
bstr3 = bstr1.multiply(bstr2);
//表示两者相除:
bstr3 = bstr1.divide(bstr2);
在除法这边需要注意一点,当不能整除的时候会抛出异常
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
这个时候我们需要设置精度
bstr3 = bstr1.divide(bstr2, 2, RoundingMode.HALF_UP);
后面这个RoundingMode.HALF_UP表示四舍五入,可以不用加但是最好是加上,不然还是会出现一下计算上的问题.
CEILING 向正无限大方向舍入的舍入模式
DOWN 向零方向舍入的舍入模式
FLOOR 向负无限大方向舍入的舍入模式
HALF_DOWN 向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入
HALF_EVEN 向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入
HALF_UP 向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入
UNNECESSARY 用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入
UP 远离零方向舍入的舍入模式.
大家可以自行看看下面这边表达是计算的是什么?
bstr3 = bstr1.subtract(bstr2).divide(bstr2,2)

我们还可以使用BigDecimal来比较大小.例如,我们比较bstr1和bstr2
bstr1.compareTo(bstr2);
当bstr1 > bstr2时返回1
当bstr1 < bstr2时返回-1
当bstr1 = bstr2时返回0

小结一下:
BigDecimal的构造器有
创建一个具有参数所指定整数值的对象。
BigDecimal(int)
创建一个具有参数所指定双精度值的对象。
BigDecimal(long)
创建一个具有参数所指定以字符串表示的数值的对象
BigDecimal(double)
创建一个具有参数所指定长整数值的对象。
BigDecimal(String)

方法描述
BigDecimal对象中的值相加,然后返回这个对象。
add(BigDecimal)
BigDecimal对象中的值相减,然后返回这个对象。
subtract(BigDecimal)
BigDecimal对象中的值相乘,然后返回这个对象。
multiply(BigDecimal)
BigDecimal对象中的值相除,然后返回这个对象。
divide(BigDecimal)

将BigDecimal对象中的值以整数返回。
intValue()
将BigDecimal对象中的值以长整数返回。
longValue()
将BigDecimal对象中的值以双精度数返回。
doubleValue()
将BigDecimal对象中的值以单精度数返回。
floatValue()
将BigDecimal对象的数值转换成字符串。
toString()

BigDecimal进行四舍五入

上面介绍过在两个BigDecimal相除时可以设置精度,并且进行设置舍入的方式.
而加减乘却没有相应的方法,所以我们需要调用另一个方法setScale()

保留2位小数进行四舍五入.
bstr3.setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal.ROUND_HALF_UP有多种常量和上面的一致.
setScale(2)表示保留两位位小数,默认用四舍五入方式
setScale(2,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如1.188会变成1.18
setScale(2,BigDecimal.ROUND_UP)进1处理,1.181变成1.19
setScale(2,BigDecimal.ROUND_HALF_UP)四舍五入,1.188变成1.19
setScaler(2,BigDecimal.ROUND_HALF_DOWN)应该叫五舍六入,1.355变成1.35,1.356变成1.36
常用是这几个,不过舍入的模式总共八种其他的有需要的可以了解一下.

补充

补充一个格式化的方法NumberFormat.
//建立货币格式化引用
NumberFormat formatCurrency = NumberFormat.getCurrencyInstance();
//建立百分比格式化引用
NumberFormat formatpPercent = NumberFormat.getPercentInstance();

formatCurrency.format(“0.02”)
这样虽然代码中没有提示错误,但是运行时会报:Caused by: java.lang.IllegalArgumentException: Bad class: class java.lang.String
所以参数不要用String,可以是BigDecimal类型的.
formatCurrency.format(200)
结果是
¥200

参考文章:
http://www.cnblogs.com/linjiqin/p/3413894.html
http://blog.csdn.net/daryl715/article/details/1604174
http://www.bdqn.cn/news/201311/11834.shtml
《java解惑》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值