Java中BigDecimal类介绍及用法

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

BigInteger 也可以存放比较大的数, 和 BigDecimal 的区别是 :BigInteger 存放的是大的整数,而BigDecimal 存放大的小数。

1、BigDecimal构造方法

BigDecimal一共有4个构造方法:

  • BigDecimal(int) 创建一个具有参数所指定整数值的对象。
  • BigDecimal(double) 创建一个具有参数所指定双精度值的对象。(不建议采用)
  • BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
  • BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。

实例化方法:

  1. BigDecimal BigDecimal(double d); //不允许使用
  2. BigDecimal BigDecimal(String s); //常用,推荐使用
  3. static BigDecimal valueOf(double d); //常用,推荐使用

注意:

  • double 参数的构造方法,不允许使用,因为它不能精确的得到相应的值,值会变大;
  • String 构造方法是完全可预知的: 写入 new BigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的0.1; 因此,通常建议优先使用 String 构造方法;
  • 静态方法 valueOf(double val) 内部实现,仍是将 double 类型转为 String 类型; 这通常是将 double(或float)转化为 BigDecimal 的首选方法。

BigDecimal 类的 valueOf()方法源码:

1
2
3
public static BigDecimal valueOf(double val) {
    return new BigDecimal(Double.toString(val));
}

2、BigDecimal格式化

由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。 以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比 。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
BigDecimal bigLoanAmount = new BigDecimal("具体数值");   //创建BigDecimal对象
BigDecimal
bigInterestRate = new BigDecimal("具体数值");
  
BigDecimal bigInterest = bigLoanAmount.multiply(bigInterestRate);//BigDecimal运算
NumberFormat
currency = NumberFormat.getCurrencyInstance();    //建立货币格式化引用
  
NumberFormat percent = NumberFormat.getPercentInstance();     //建立百分比格式化用
  
percent.setMaximumFractionDigits(3);               //百分比小数点最多3位
  
//利用BigDecimal对象作为参数在format()中调用货币和百分比格式化
  
System.out.println("Loan amount:t" + currency.format(bigLoanAmount));
  
System.out.println("Interest rate:t" + percent.format(bigInterestRate));
  
System.out.println("Interest:t" + currency.format(bigInterest));

输出结果:

1
2
3
4
Loan amount:  ¥129,876,534,219,876,523.12
Interest rate: 8.765%
Interest: 
11,384,239,549,149,661.69

常见用法:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
初始化 BigDecimal a= new BigDecimal("1.35");
  
对数值取值:
1.a.setScale(1,BigDecimal.ROUND_DOWN);
  
取一位小数,直接删除后面多余位数,故取值1.3.
2.a.setScale(1,BigDecimal.ROUND_UP);
  
取一位小数,删除后面位数,进一位,故取值1.4.
3.a.setScale(1,BigDecimal.ROUND_HALF_UP);
  
取一位小数,四舍五入,故取值1.4.
4.a.setScale(1,BigDecimal.ROUND_HALF_DOWN);
  
取一位小数,五舍六入,故取值1.3.

3、BigDecimal加减乘除运算

对于常用的加,减,乘,除,BigDecimal类提供了相应的成员方法 :

  • public BigDecimal add(BigDecimal value); //加法
  • public BigDecimal subtract(BigDecimal value); //减法
  • public BigDecimal multiply(BigDecimal value); //乘法
  • public BigDecimal divide(BigDecimal value); //除法

用法如下:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
BigDecimal bignum1 = new BigDecimal("10");
BigDecimal bignum2 = new BigDecimal("5");
BigDecimal bignum3 = null;
 
//加法
bignum3 =  bignum1.add(bignum2); 
System.out.println("和 是:" + bignum3);
 
//减法
bignum3 = bignum1.subtract(bignum2);
System.out.println("差  是:" + bignum3);
 
//乘法
bignum3 = bignum1.multiply(bignum2);
System.out.println("积  是:" + bignum3);
 
//除法
bignum3 = bignum1.divide(bignum2);
System.out.println("商  是:" + bignum3);

注意:

BigDecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。

divide方法有可以传三个参数:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 第一参数表示除数, 第二个参数表示小数点后保留位数,第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种:

Java中BigDecimal类介绍及用法插图
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ROUND_CEILING
Rounding mode to round towards positive infinity.
向正无穷方向舍入
 
ROUND_DOWN
Rounding mode to round towards zero.
向零方向舍入
 
ROUND_FLOOR
Rounding mode to round towards negative infinity.
向负无穷方向舍入
 
ROUND_HALF_DOWN
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
 
ROUND_HALF_EVEN
Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN
 
ROUND_HALF_UP
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
 
ROUND_UNNECESSARY
Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.
计算结果是精确的,不需要舍入模式
 
ROUND_UP
Rounding mode to round away from zero.
向远离0的方向舍入

4、BigDecimal 比较大小

BigDecimal使用compareTo方法比较大小:

1
2
3
4
5
6
7
8
9
BigDecimal num1 = new BigDecimal("0");
BigDecimal num2 = new BigDecimal("1");
BigDecimal num3 = new BigDecimal("2");
 
BigDecimal num = new BigDecimal("1"); //用做比较的值
 
System.out.println(num1.compareTo(num));//小于 时,返回 -1
System.out.println(num2.compareTo(num));//等于 时,返回 0
System.out.println(num3.compareTo(num));//大于 时,返回 1

5、其他常用方法

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
/**
 * 求余数
 * 返回值为 (this % divisor) 的 BigDecimal
 */BigDecimal remainder(BigDecimal divisor);
 
/**
 * 求相反数
 * 返回值是 (-this) 的 BigDecimal
 */BigDecimal negate();
 
/**
 * 将此 BigDecimal 与指定的 BigDecimal 比较
 * 根据此方法,值相等但具有不同标度的两个 BigDecimal 对象(如,2.0 和 2.00)被认为是相等的;
 * 相对六个 boolean 比较运算符 (<, ==, >, >=, !=, <=) 中每一个运算符的各个方法,优先提供此方法;
 * 建议使用以下语句执行上述比较:(x.compareTo(y) <op> 0), 其中 <op> 是六个比较运算符之一;
 *
 * 指定者:接口 Comparable<BigDecimal> 中的 compareTo
 * 返回:当此 BigDecimal 在数字上小于、等于或大于 val 时,返回 -1、0 或 1
 */int compareTo(BigDecimal val);

发表评论

欢迎阅读『Java中BigDecimal类介绍及用法|Java、开发语言、框架算法|Nick Tan-梓潼Blog』