文档章节

BigDecimal的使用

SunnyTime
 SunnyTime
发布于 2016/03/23 11:38
字数 1396
阅读 398
收藏 2

这次在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解惑》

© 著作权归作者所有

SunnyTime

SunnyTime

粉丝 6
博文 27
码字总数 17058
作品 0
静安
程序员
私信 提问
BigDecimal类的加/减/乘/除

对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。BigDecimal类的常用方法如...

easonwang
2012/01/02
0
0
BigDecimal类的加减乘除

BigDecimal类型(+ - * /)所用的属性 11.10 BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDe...

zkool
2012/12/18
0
0
计算金额 财务计算 精确运算 BigDecimal用法详解

一、简介 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效 位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算...

jerry__sun
2016/07/07
581
1
BigDecimal用法详解

一、简介 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算...

肖歌
2016/02/25
56
0
JavaSE|BigDecimal

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/darlingwood2013/article/details/83340508 JavaSE|BigDecimal 构造方法 成员方法 在运算的时候,float类型和...

叶晚林
2018/10/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

IT兄弟连 Java语法教程 编写Java源代码

现在我们来一步一步的编写第一个Java程序,鼎鼎大名的“HelloWorld”。 编写Java源代码 编写Java源代码可以使用任何无格式的文本编辑器,在Windows操作系统上可以使用记事本、Edit Plus等程序...

老码农的一亩三分地
13分钟前
2
0
JavaScript箭头函数中的this详解

前言 箭头函数极大地简化了this的取值规则。 普通函数与箭头函数 普通函数指的是用function定义的函数: var hello = function () {console.log("Hello, Fundebug!");} 箭头函数指的是用...

开元中国2015
24分钟前
2
0
ETL测试工具简介

ETL测试 ETL测试过程与其他测试过程类似,包括一些阶段。 确定业务需求 测试计划 设计测试用例和测试数据 测试执行和错误报告 总结报告 测试结束 ETL测试的类型 生产验证测试: 也称为表平衡...

python测试开发人工智能安全
36分钟前
1
0
OSChina 周四乱弹 —— 不能空腹吃早餐

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @for_ :#今日歌曲推荐# 很好听的钢琴曲,节奏简单,有一点伤感。分享Fabrizio Paterlini的单曲《Veloma》: 《Veloma》- Fabrizio Paterlini ...

小小编辑
今天
1K
13
探讨android更新UI的几种方法

作为IT新手,总以为只要有时间,有精力,什么东西都能做出来。这种念头我也有过,但很快就熄灭了,因为现实是残酷的,就算一开始的时间和精力非常充足,也会随着项目的推进而逐步消磨殆尽。我...

天王盖地虎626
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部