BigDecimal精度计算
介绍
用于进行精确计算
BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。
加:add()
减:subtract()
乘:multiply()
除:divide()
例子:
java
String a = "9999.9999";
int b = 9999;
double c = 9999.9999;
char d = 99;
// 不同类型转为BigDecimal
BigDecimal ma = new BigDecimal(a);
BigDecimal mb = new BigDecimal(b);
BigDecimal mc = new BigDecimal(c);
BigDecimal md = new BigDecimal(d);
System.out.println("ma:"+ma.toString());
System.out.println("mb:"+mb.toString());
System.out.println("mc:"+mc.toString());
System.out.println("md:"+md.toString());
// 加
BigDecimal add = ma.add(mb);
System.out.println("加法:"+add);
// 减
BigDecimal sub = ma.subtract(mb);
System.out.println("减法:"+sub);
// 乘
BigDecimal mul = mb.multiply(md);
System.out.println("乘法:"+mul);
// 除
BigDecimal div = mb.divide(md);
System.out.println("除法:"+div);
mc = mc.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("四舍五入:"+mc);
mc = mc.negate();
System.out.println("负数:"+mc);
运行结果如下:
ma: 9999.9999
mb: 9999
mc: 9999.999900000000707223080098628997802734375
md: 99
加法:19998.9999
减法:0.9999
乘法:989901
除法:101
四舍五入:10000.00
负数:-10000.00
银行家算法
在进行金额计算时,为了保证计算的精度,我们推荐使用银行家算法
概念
银行家算法:四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一
实现
java
java
package com.zb.misszb.core.money;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class HalfEvenRound implements IMoneyDiscount{
/**
* 计算折扣接口(银行家算法)
*
* @param original 原价
* @param discount 折扣率
* @return
*/
@Override
public BigDecimal discount(BigDecimal original, BigDecimal discount) {
BigDecimal actualMoney = original.multiply(discount);
// HALF_EVEN表示银行家算法
BigDecimal finalMoney = actualMoney.setScale(2, RoundingMode.HALF_EVEN);
return finalMoney;
}
}
js
自己封装(我项目里用的这个)
js
/**
* 封装的加、减、乘、除函数
*/
function accAdd(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (Math.round(num1 * baseNum) + Math.round(num2 * baseNum)) / baseNum;
}
function accSubtract(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (Math.round(num1 * baseNum) - Math.round(num2 * baseNum)) / baseNum;
}
function accMultiply(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (Math.round(num1 * baseNum) * Math.round(num2 * baseNum)) / baseNum / baseNum;
}
function accDivide(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (Math.round(num1 * baseNum) / Math.round(num2 * baseNum)) / baseNum / baseNum;
}
使用mathjs
js
import * as math from 'mathjs'
/**
* 获取金额折扣价
* @param original 金额
* @param discount 折扣率
* @returns {number}
*/
function getDiscount(original, discount) {
return math.round(math.multiply(original, discount)*100)/100
}
说明
第一、new BigDecimal为什么要传入Sting?
BigDecimal构造器传参时使用String不会丢失精度,使用浮点或者双精度会丢失精度。