Skip to content

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不会丢失精度,使用浮点或者双精度会丢失精度。

如有转载或 CV 的请标注本站原文地址