通常我们需要精确计算的时候会选择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