All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feingto.cloud.kit.MathKit Maven / Gradle / Ivy

There is a newer version: 2.5.2.RELEASE
Show newest version
package com.feingto.cloud.kit;

import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Objects;

/**
 * 计算工具类,提供精确的浮点数运算
 *
 * @author longfei
 */
public class MathKit {
    /**
     * 保留小数点后位数
     */
    public static final int DEF_DIV_SCALE = 2;

    /**
     * 提供精确的加法运算
     *
     * @param decimals List
     * @return 求和
     */
    public static BigDecimal add(BigDecimal... decimals) {
        BigDecimal result = BigDecimal.ZERO;
        for (BigDecimal decimal : decimals) {
            result = result.add(decimal);
        }
        return result;
    }

    /**
     * 提供精确的减法运算
     *
     * @param data     被减数
     * @param decimals 减数集合
     * @return 求差
     */
    public static BigDecimal sub(BigDecimal data, BigDecimal... decimals) {
        return data.subtract(add(decimals));
    }

    /**
     * 提供精确的乘法运算
     *
     * @param decimals List
     * @return 求积
     */
    public static BigDecimal mul(BigDecimal... decimals) {
        BigDecimal result = BigDecimal.ONE;
        for (BigDecimal decimal : decimals) {
            result = result.multiply(decimal);
        }
        return result;
    }

    /**
     * 提供(相对)精确的除法运算,精确到小数点后6位后的数字四舍五入
     *
     * @param dividend 被除数
     * @param divisors 除数集合
     * @return 求商
     */
    public static BigDecimal div(BigDecimal dividend, BigDecimal... divisors) {
        return div(dividend, DEF_DIV_SCALE, divisors);
    }

    /**
     * 提供(相对)精确的除法运算,精确到小数点后 scale 位后的数字四舍五入
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    表示表示需要精确到小数点后几位
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal dividend, BigDecimal divisor, int scale) {
        Assert.state(scale >= 0, "The scale must be a positive integer or zero");
        return div(dividend, scale, divisor);
    }

    /**
     * 提供(相对)精确的除法运算,精确到小数点后 scale 位后的数字四舍五入
     *
     * @param dividend 被除数
     * @param divisors 除数数组
     * @param scale    表示表示需要精确到小数点后几位
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal dividend, BigDecimal[] divisors, int scale) {
        Assert.state(scale >= 0, "The scale must be a positive integer or zero");
        return div(dividend, scale, divisors);
    }

    /**
     * 提供(相对)精确的除法运算,精确到小数点后 scale 位后的数字四舍五入
     *
     * @param dividend 被除数
     * @param scale    表示表示需要精确到小数点后几位
     * @param divisors 除数集合
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal dividend, int scale, BigDecimal... divisors) {
        Assert.state(scale >= 0, "The scale must be a positive integer or zero");
        return dividend.divide(mul(divisors), scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param data  需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static BigDecimal round(BigDecimal data, int scale) {
        Assert.state(scale >= 0, "The scale must be a positive integer or zero");
        return data.divide(BigDecimal.ONE, scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 转换为BigDecimal
     *
     * @param obj Object
     * @return BigDecimal
     */
    public static BigDecimal toBig(Object obj) {
        if (Objects.isNull(obj) || obj.toString().equals("") || obj.toString().equals("NaN")) {
            return BigDecimal.ZERO;
        }

        return new BigDecimal(obj.toString());
    }

    /**
     * 计算百分比
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return String
     */
    public static String getPercent(Object dividend, Object divisor) {
        if (Objects.isNull(divisor) || Objects.isNull(dividend)) {
            return "";
        }

        NumberFormat percent = NumberFormat.getPercentInstance();
        // 建立百分比格式化引用
        percent.setMaximumFractionDigits(2);
        BigDecimal a = toBig(dividend);
        BigDecimal b = toBig(divisor);
        if (a.equals(toBig(0)) || b.equals(toBig(0)) || a.equals(toBig(0.0)) || b.equals(toBig(0.0))) {
            return "0.00%";
        }

        BigDecimal c = a.divide(b, 4, BigDecimal.ROUND_DOWN);
        return percent.format(c);
    }

    /**
     * 计算比例
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return String
     */
    public static String divideNumber(Object dividend, Object divisor) {
        if (Objects.isNull(divisor) || Objects.isNull(dividend)) {
            return "";
        }

        BigDecimal a = toBig(dividend);
        BigDecimal b = toBig(divisor);
        if (a.equals(toBig(0)) || b.equals(toBig(0))) {
            return "0";
        }

        BigDecimal c = a.divide(b, 2, BigDecimal.ROUND_DOWN);
        return c.toString();
    }

    /**
     * 取两个数的平均值,四舍五入
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @return int
     */
    public static int averageNumber(Object dividend, Object divisor) {
        if (Objects.isNull(divisor) || Objects.isNull(dividend)) {
            return 0;
        }

        BigDecimal a = toBig(dividend);
        BigDecimal b = toBig(divisor);
        if (a.equals(toBig(0)) || b.equals(toBig(0))) {
            return 0;
        }

        BigDecimal c = a.divide(b, 0, BigDecimal.ROUND_HALF_UP);
        return c.intValue();
    }

    public static void main(String[] args) {
        System.out.println("加法运算:" + round(add(new BigDecimal("10.345"), new BigDecimal("3.333")), 1));
        System.out.println("乘法运算:" + round(mul(new BigDecimal("10.345"), new BigDecimal("3.333")), 1));
        System.out.println("除法运算:" + div(new BigDecimal("10.345"), 3, new BigDecimal("3.333")));
        System.out.println("减法运算:" + round(sub(new BigDecimal("10.345"), new BigDecimal("3.333")), 3));
        System.out.println(divideNumber("1", "3"));
        System.out.println(getPercent("1", "3"));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy