这篇文章主要介绍了如何使用BigDecimal实现Java开发商业计算,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
前言
今天群里一个初级开发者问为什么测试人员测出来他写的价格计算模块有计算偏差的问题,他检查了半天也没找出问题。这里小胖哥要提醒你,商业计算请务必使用BigDecimal,浮点做商业运算是不精确的。因为计算机无法使用二进制小数来精确描述我们程序中的十进制小数。《Effective Java》在第48条也推荐“使用BigDecimal来做精确运算”。今天我们就来总结归纳其相关的知识点。
BigDecimal
BigDecimal表示不可变的任意精度带符号十进制数。它由两部分组成:
intVal - 未校正精度的整数,类型为BigInteger
Scale - 一个32位整数,表示小数点右边的位数
例如,BigDecimal 3.14的未校正值为314,缩放为2。我们使用BigDecimal进行高精度算术运算。我们还将它用于需要控制比例和舍入行为的计算。如果你的计算是商业计算请务必使用计算精确的BigDecimal 。
构造BigDecimal实例
我们可以从String,character 数组,int,long和BigInteger创建一个BigDecimal对象:
@Test public void theValueMatches() { BigDecimal bdFromString = new BigDecimal("0.12"); BigDecimal bdFromCharArray = new BigDecimal(new char[]{'3', '.', '1', '4', '1', '5'}); BigDecimal bdlFromInt = new BigDecimal(42); BigDecimal bdFromLong = new BigDecimal(123412345678901L); BigInteger bigInteger = BigInteger.probablePrime(100, new Random()); BigDecimal bdFromBigInteger = new BigDecimal(bigInteger); assertEquals("0.12", bdFromString.toString()); assertEquals("3.1415", bdFromCharArray.toString()); assertEquals("42", bdlFromInt.toString()); assertEquals("123412345678901", bdFromLong.toString()); assertEquals(bigInteger.toString(), bdFromBigInteger.toString()); }
我们还可以从double创建BigDecimal:
@Test public void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() { BigDecimal bdFromDouble = new BigDecimal(0.1d); assertNotEquals("0.1", bdFromDouble.toString()); }
我们发现在这种情况下,结果与预期的结果不同(即0.1)。这是因为:这个转换结果是double的二进制浮点值的精确十进制表示,其值得结果不是我们可以预测的.我们应该使用String构造函数而不是double构造函数。另外,我们可以使用valueOf静态方法将double转换为BigDecimal 或者直接使用其未校正数加小数位数 :
@Test public void whenBigDecimalCreatedUsingValueOf_thenValueMatches() { BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d); BigDecimal bigFromLong=BigDecimal.valueOf(1,1); assertEquals("0.1", bdFromDouble.toString()); assertEquals("0.1", bigFromLong.toString()); }
在转换为BigDecimal之前,此方法将double转换为其String表示形式。此外,它可以重用对象实例。因此,我们应该优先使用valueOf方法来构造函数。
常用API
方法名
对应方法相关用法解释
abs()
绝对值,scale不变
add(BigDecimal augend)
加,scale为augend和原值scale的较大值
subtract(BigDecimal augend)
减,scale为augend和原值scale的较大值
multiply(BigDecimal multiplicand)
乘,scale为augend和原值scale的和
divide(BigDecimal divisor)
除,原值/divisor,如果不能除尽会抛出异常,scale与原值一致
divide(BigDecimal divisor, int roundingMode)
除,指定舍入方式,scale与原值一致
divide(BigDecimal divisor, int scale, int roundingMode)
除,指定舍入方式和scale
remainder(BigDecimal divisor)
取余,scale与原值一致
divideAndRemainder(BigDecimal divisor)
除法运算后返回一个数组存放除尽和余数 如 23/3 返回 {7,2}
divideToIntegralValue(BigDecimal divisor)
除,只保留整数部分,但scale仍与原值一致
max(BigDecimal val)
较大值,返回原值与val中的较大值,与结果的scale一致
min(BigDecimal val)
较小值,与结果的scale一致
movePointLeft(int n)
小数点左移,scale为原值scale+n
movePointRight(int n)
小数点右移,scale为原值scale+n
negate()
取反,scale不变
pow(int n)
幂,原值^n,原值的n次幂
scaleByPowerOfTen(int n)
相当于小数点右移n位,原值*10^n
BigDecimal操作
BigDecimal上的操作就像其他Number类(Integer,Long,Double等)一样,BigDecimal提供算术和比较操作的操作。它还提供了缩放操作,舍入和格式转换的操作。它不会使算术运算符(+ - /*)或逻辑运算符(>
提取属性
精度,小数位数和符号:
@Test public void whenGettingAttributes_thenExpectedResult() { BigDecimal bd = new BigDecimal("-12345.6789"); assertEquals(9, bd.precision()); assertEquals(4, bd.scale()); assertEquals(-1, bd.signum()); }
比较大小
我们使用compareTo方法比较两个BigDecimal的值:
@Test public void whenComparingBigDecimals_thenExpectedResult() { BigDecimal bd1 = new BigDecimal("1.0"); BigDecimal bd2 = new BigDecimal("1.00"); BigDecimal bd3 = new BigDecimal("2.0"); assertTrue(bd1.compareTo(bd3) 0); assertTrue(bd1.compareTo(bd2) == 0); assertTrue(bd1.compareTo(bd3) = 0); assertTrue(bd1.compareTo(bd3) != 0); }
上面的方法在比较时忽略了小数位。如果你既要比较精度又要比较小数位数那么请使用equals方法:
@Test public void whenEqualsCalled_thenSizeAndScaleMatched() { BigDecimal bd1 = new BigDecimal("1.0"); BigDecimal bd2 = new BigDecimal("1.00"); assertFalse(bd1.equals(bd2)); }
四则运算
BigDecimal 提供了以下四则运算的方法:
a上一篇:Java集合系列之ArrayList源码分析下一篇:分享Spring的下载组件 热门搜索:
用vbs实现防止计算机使用
Android计算器实现
java实现telnet
企业微信如何使用
Java开发
相关文章
如何使用BigDecimal实现Java开发商业计算
2021-09-10阅读(10928)评论(0)推荐()这篇文章主要介绍了如何使用BigDecimal实现Java开发商业计算,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可...
Java BigDecimal使用及基本运算(推荐)
2021-10-18阅读(4074)评论(0)推荐()Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。这篇文章主要介绍了Java BigDecimal使...
浅谈java中BigDecimal类的简单用法
2021-10-07阅读(9139)评论(0)推荐()这篇文章主要介绍了浅谈java中BigDecimal类的简单用法,在开发时,如果我们需要精确计算的结果,必须使用BigDecimal类来操作。感兴趣的话可以了解...
使用BigDecimal进行精确运算(实现加减乘除运算)
2021-10-12阅读(7714)评论(0)推荐()这篇文章主要介绍了如何使用BigDecimal进行精确运算,最后提供了一个工具类,该工具类提供加,减,乘,除运算
Java使用BigDecimal进行高精度计算的示例代码
2021-10-18阅读(4076)评论(0)推荐()本篇文章主要介绍了Java使用BigDecimal进行高精度计算的示例代码,具有一定的参考价值,有兴趣的可以了解一下
Java中使用BigDecimal进行精确运算
2021-10-14阅读(9805)评论(0)推荐()这篇文章主要介绍了Java中使用BigDecimal进行精确运算的方法,非常不错,需要的朋友参考下
Java中使用BigDecimal进行浮点数运算
2021-10-12阅读(7529)评论(0)推荐()这篇文章主要介绍了Java中使用BigDecimal进行浮点数运算,需要的朋友可以参考下
取消
有人回复时邮件通知我
提交评论
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。