通常我们需要精确计算的时候会选择java.math.BigDecimal来进行计算。这篇博客主要介绍BigDecimal的方法和使用,主要分为三部分:BigDecimal介绍,为什么更精确;BigDecimal的方法。
介绍
Java中基础的小数的数据类型为float和double,他们在计算机底层是通过二进制分别表示指数和尾数来进行存储时,故造成存储时失去准确性。比如输入下面代码:
System.out.println(0.8-0.1);
结果为0.7000000000001。而BigDecimal使用十进制(BigInteger)+ 小数点位置(scale)来表示,更准确
奇奇怪怪的对不对,可以参见Java的BigDecimal如何解决浮点数精度问题这篇,比较详细解释浮点数的存储,以及如何转换成BigDecimal,写的很好。当然,如果你只是想要使用BigDecimal,可以记住结论然后我们开始看下一部分。
BigDecimal方法
一下内容均翻译理解自官方文档:https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html,其中的参数名为scale的都是指小数点位数。
1、构造函数:BigDecimal的构造函数多达16个,这里就不都翻译了,只说常用方法和注意事项,以下皆是如此。常见的构造方法为,很多人喜欢通过double构造,这样无法保证精度,所以最好使用字符串的形式进行构造。究其原因,BigDecimal在通过double构造时,会将double变量转换成IEEE 754类型,精度就已经损失了。
BigDecimal(String val);
BigDecimal BigDecimal(double d); //不允许使用,精度不能保证
除此之外,构造函数的参数还可以是char[]、int、long、BigInteger类型的变量,其中char[]还可为其指定范围实例如下,输出bD结果为2345。
String str = "1234567";
char[] chars = str.toCharArray();
BigDecimal bD = new BigDecimal(chars, 1,4);
2、赋值及实例
static BigDecimal valueOf(double val)
static BigDecimal valueOf(long val)
static BigDecimal valueOf(long unscaledVal, int scale)//指定小数点位数
举例及结果:
BigDecimal bD = BigDecimal.valueOf(12345679,2);//结果为123456.79
3、基本数学操作,加减乘除等,返回值都是BigDecimal,如下表,再次说明scale表示小数点位数。roundingMode表示四舍五入的方式,可以直接写数字或者RoundingMode枚举类型,舍入模式请参考:BigDecimal使用。
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) | 除与取余,返回BigDecimal数组,两个元素,0为商,1为余数,scale与原值一致 |
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 |