java中关于货币金额的计算

BigDecimal的由来

由于互联网金额的高发达和高统一性,关于货币的金额基本都是精确到分,因此double在货币计算中可以说用武之地比较小,java提供了一个非常强大的货币金额计算工具:BigDecimal

BigDecimal的基本使用

==如果需要进行精确计算,务必将对应数字转化为String来构造BigDecimal==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static void main(String[] args) {
double a = 10.1234;
double b = 5.3134;
BigDecimal bigDecimalA = new BigDecimal(String.valueOf(a));
BigDecimal bigDecimalB = new BigDecimal(String.valueOf(b));
/**
* 使用BigDecimal做加法运算
*/
double addValue = bigDecimalA.add(bigDecimalB).doubleValue();

/**
* 使用BigDecimal做减法运算
*/
double subtractValue = bigDecimalA.subtract(bigDecimalB).doubleValue();

/**
* 使用BigDecimal做乘法运算
*/
double multiplyValue = bigDecimalA.multiply(bigDecimalB).doubleValue();
/**
* 使用BigDecimal做除法运算
*/
int scale = 2;//保留2位小数
double divideValue = bigDecimalA.divide(bigDecimalB, scale, BigDecimal.ROUND_HALF_UP).doubleValue();

/**
* 使用BigDecimal的加减乘除进行复杂运算
*/
int num = new BigDecimal("2019.1027")
.divide(new BigDecimal("4.10"), scale, BigDecimal.ROUND_HALF_UP)
.multiply(new BigDecimal("1024"))
.add(new BigDecimal("1234")).intValue();
}

BigDecimal计算结果精度的控制

  • ROUND_UP 舍入远离零的舍入模式:在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。

  • ROUND_DOWN 接近零的舍入模式:在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。

  • ROUND_CEILING 接近正无穷大的舍入模式:如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;如果为负,则舍入模式与ROUND_DOWN相同。

  • ROUND_FLOOR 接近负无穷大的舍入模式:如果BigDecimal 为负,则舍入行为ROUND_DOWN相同;反之亦然。

  • ROUND_HALF_UP 四舍五入:向最接近的数字舍入,如果为5及以上则同样进一;5以下舍弃。

  • ROUND_HALF_DOWN 五舍六入:向最接近的数字舍入,如果为6及以上则进一,6以下舍弃。

  • ROUND_HALF_EVEN 向“最接近的”数字舍入:如果与两个相邻数字的距离相等,则向相邻的偶数舍入: 如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。示例: 保留小数点后1位,则:1.15 -> 1.2;1.25 ->1.2

  • ROUND_UNNECESSARY 断言请求的操作具有精确的结果,因此不需要舍入:如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

    在以上的精确控制中,比较常用的是ROUND_HALF_UPROUND_HALF_EVEN ;互联网计算精度最最常用的是ROUND_HALF_EVEN

double数据的常用格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static void main(String[] args) {
//格式化
double num = 1834234847.2345;

/**
* 将dobule数据进行正常的转化为String
*/
String value = NumberFormat.getNumberInstance().format(num);

/**
* 将dobule数据进行正常的转化为int,小数会进行四舍五入,然后转化为String
*/
value = NumberFormat.getIntegerInstance().format(num);

/**
* 设置小数部分的范围后然后转化为String-可使用于转化格式为货币
*/
NumberFormat currency = NumberFormat.getCurrencyInstance();
//设置数的小数部分所允许的最小位数(如果不足后面补0)
currency.setMinimumFractionDigits(2);
//设置数的小数部分所允许的最大位数(如果超过会四舍五入)
currency.setMaximumFractionDigits(4);
value = currency.format(num);
/**
* 设置格式为%分比格式
*/
NumberFormat percent = NumberFormat.getPercentInstance();
//设置数的小数部分所允许的最小位数(如果不足后面补0)
percent.setMinimumFractionDigits(2);
//设置数的小数部分所允许的最大位数(如果超过会四舍五入)
percent.setMaximumFractionDigits(3);
value = percent.format(num);
}
0%