自定义大数工具类,除法保留位数,多除数,有效数字

124 阅读3分钟

简述

最近有一个奇葩的需求,要求对数字做一些处理,大致是两种情况:

  • 1.计算结果大于1时保留n为小数,当结果小于1时保留n位有效数字
  • 2.计算结果大于1时保留整数位,小于1时,保留有效数字

实现效果

在这里插入图片描述

System.out.println("============连乘/连除/连加/连减==============");
System.out.println("2 x 5 x 8 x 10 = " + BigDecimalUtils.multiply(2, 5, 8, 10));
System.out.println("800/8/5/1 = " + BigDecimalUtils.divide(800, 8, 5, 1));
System.out.println("10/3 保留3位小数为: " + BigDecimalUtils.divide(10, 3, 3));
System.out.println("2 + 5 + 8 + 10 = " + BigDecimalUtils.add(2, 5, 8, 10));
System.out.println("2 - 5 - 8 - 10 = " + BigDecimalUtils.subtract(2, 5, 8, 10));
System.out.println("============精度大于一保留n位数或转整数,小于1时保留有效数字==============");
System.out.println("大于1保留三位小数 1.66665555=>" + BigDecimalUtils.setEffectiveNumber(1.66665555, 3));
System.out.println("小于1保留三位有效数字  0.00666655=>" + BigDecimalUtils.setEffectiveNumber(0.00666655, 3));
System.out.println("转整数位 1.66665555=>" + BigDecimalUtils.setEffectiveNumber(1.66665555, true));
System.out.println("0.00666655=>" + BigDecimalUtils.setEffectiveNumber(0.00666655, true));

实现代码

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

/**
 * @author longzipeng
 * 大数工具类
 */
public class BigDecimalUtils {

    // 默认大数保留6位小数
    public static final int DEFAULT_SCALE = 6;

    // 默认大数除法 结果规则 四舍五入 向下舍入
    public static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_DOWN;
    // 默认保留n位有效数字
    public static final int DEFAULT_PRECISION = 2;
    // 大数一百、一千、一万
    public static final BigDecimal ONE_HUNDRED = new BigDecimal("100");
    public static final BigDecimal ONE_THOUSAND = new BigDecimal("1000");
    public static final BigDecimal TEN_THOUSAND = new BigDecimal("10000");


    /**
     * 通用大数比较大小
     */
    public static int compareTo(Object number1, Object number2) {
        return castToBigDecimal(number1).compareTo(castToBigDecimal(number2));
    }

    /**
     * 通用大数判断相等
     */
    public static boolean equal(Object number1, Object number2) {
        return castToBigDecimal(number1).compareTo(castToBigDecimal(number2)) == 0;
    }

    /**
     * 通用大数除法
     *
     * @param number1 运算的数1
     * @param number2 运算的数2
     * @return
     */
    public static BigDecimal divide(Object number1, Object number2) {
        BigDecimal b1 = castToBigDecimal(number1);
        BigDecimal b2 = castToBigDecimal(number2);
        return divide(b1, b2, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
    }

    // 重载大数方法除法
    public static BigDecimal divide(Object number1, Object number2, int scale) {
        BigDecimal b1 = castToBigDecimal(number1);
        BigDecimal b2 = castToBigDecimal(number2);
        return divide(b1, b2, scale, DEFAULT_ROUNDING_MODE);
    }

    // 如果结果为0 则返回0
    public static BigDecimal divide(Object number1, Object number2, int scale, RoundingMode roundingMode) {
        if (number2 == null || equal(number2, BigDecimal.ZERO)) {
            return BigDecimal.ZERO;
        }
        BigDecimal b1 = castToBigDecimal(number1);
        BigDecimal b2 = castToBigDecimal(number2);
        return b1.divide(b2, scale, roundingMode);
    }

    public static BigDecimal divide(Object number1, Object number2, RoundingMode roundingMode) {
        BigDecimal b1 = castToBigDecimal(number1);
        BigDecimal b2 = castToBigDecimal(number2);
        return divide(b1, b2, DEFAULT_SCALE, roundingMode);
    }

    /**
     * number1 除n个数
     *
     * @param number1
     * @param numbers
     * @return
     */
    public static BigDecimal divide(Object number1, Object... numbers) {
        BigDecimal b1 = castToBigDecimal(number1);
        if (numbers.length > 0) {
            for (Object number : numbers) {
                b1 = divide(b1, number, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE);
            }
        }
        return b1;
    }

    /**
     * 通用大数乘法
     *
     * @param number1
     * @param number2
     * @return
     */
    public static BigDecimal multiply(Object number1, Object number2) {
        BigDecimal b1 = castToBigDecimal(number1);
        BigDecimal b2 = castToBigDecimal(number2);
        return b1.multiply(b2);
    }

    /**
     * 重载 n个数相乘
     *
     * @param numbers
     * @return
     */
    public static BigDecimal multiply(Object... numbers) {
        BigDecimal ans = null;
        if (numbers.length > 0) {
            ans = castToBigDecimal(numbers[0]);
            if (numbers.length > 1) { // 循环相乘
                for (int i = 1; i < numbers.length; i++) {
                    ans = multiply(ans, numbers[i]);
                }
            }
        }
        return ans;
    }


    /**
     * n个数相加
     *
     * @param numbers
     * @return
     */
    public static BigDecimal add(Object... numbers) {
        BigDecimal ans = null;
        if (numbers.length > 0) {
            ans = castToBigDecimal(numbers[0]);
            if (numbers.length > 1) { // 循环相乘
                for (int i = 1; i < numbers.length; i++) {
                    ans = ans.add(castToBigDecimal(numbers[i]));
                }
            }
        }
        return ans;
    }

    /**
     * n个数相减
     *
     * @param numbers
     * @return
     */
    public static BigDecimal subtract(Object... numbers) {
        BigDecimal ans = null;
        if (numbers.length > 0) {
            ans = castToBigDecimal(numbers[0]);
            if (numbers.length > 1) { // 循环相乘
                for (int i = 1; i < numbers.length; i++) {
                    ans = ans.subtract(castToBigDecimal(numbers[i]));
                }
            }
        }
        return ans;
    }

    /**
     * 默认向下取整
     *
     * @param number
     * @return
     */
    public static Integer castToInteger(BigDecimal number) {
        return number.setScale(0, BigDecimal.ROUND_DOWN).intValue();
    }


    /**
     * 将对象转化为大数
     *
     * @param obj
     * @return
     */
    public static BigDecimal castToBigDecimal(Object obj) {
        if (obj == null) {
            return BigDecimal.ZERO;
        } else {
            return obj instanceof BigDecimal ? (BigDecimal) obj : new BigDecimal(obj.toString());
        }
    }

    /**
     * 获取大数的小数位数
     *
     * @param b
     * @return
     */
    public static Integer getDecimalPlaces(BigDecimal b) {
        if (b != null) {
            // 判断如果为整数则直接返回0   过滤掉   xxx.000000的情况
            if (equal(new BigDecimal(b.intValue()), b)) {
                return 0;
            }
            // 否则进行位数判断
            String str = b.toString();
            int index = str.indexOf(".");
            if (index == -1) {
                return 0;
            }
            return str.substring(index + 1).length();
        }
        return null;
    }

    /**
     * 保留n位小数
     *
     * @param b            大数
     * @param scale        保留几位小数
     * @param roundingMode 保留小数的规则
     * @return
     */
    public static BigDecimal setScala(BigDecimal b, int scale, RoundingMode roundingMode) {
        return b.setScale(scale, roundingMode);
    }

    public static BigDecimal setScala(BigDecimal b, int scale) {
        return b.setScale(scale, DEFAULT_ROUNDING_MODE);
    }

    public static BigDecimal setScala(BigDecimal b) {
        return b.setScale(DEFAULT_SCALE);
    }

    /**
     * 保留n位有效数字
     * 1.如果为整数或者一位小数则直接返回,
     * 2.多位小数,且前两位小数有值则保留两位小数。没值则保留两位有效数字
     *
     * @param b
     * @param precision 有效数字精度
     * @param isCastInt 是否保留整数
     * @return
     */
    public static BigDecimal setEffectiveNumber(Object b, int precision, boolean isCastInt) {
        if (b == null) {
            return null;
        }
        BigDecimal bBig = castToBigDecimal(b);
        // 需要转换为int,那么大于1的话就转换为Int
        if (isCastInt && bBig.compareTo(BigDecimal.ONE) > 0) {
            return new BigDecimal(bBig.intValue());
        }

        // 获取小数位数
        Integer decimalPlaces = getDecimalPlaces(bBig);
        if (decimalPlaces != null) {
            // 为整数返回整数部分 将 xx.000转换为xx
            if (equal(decimalPlaces, Integer.valueOf(0))) {
                return new BigDecimal(bBig.intValue());
            }
            // 一位小数则直接返回
            if (decimalPlaces.equals(Integer.valueOf("1"))) {
                return bBig;
            }
            // 值大于0时 保留两位数字
            if (bBig.compareTo(BigDecimal.ONE) > 0) {
                return setScala(bBig, precision);
            } else { // 小于0时,保留precision位有效数字
                return bBig.round(new MathContext(precision, RoundingMode.HALF_UP));
            }
        }
        return null;
    }

    public static BigDecimal setEffectiveNumber(Object b, boolean isCastInt) {
        return setEffectiveNumber(b, DEFAULT_PRECISION, isCastInt);
    }

    /**
     * 默认保留2位有效数字
     */
    public static BigDecimal setEffectiveNumber(Object b, int precision) {
        return setEffectiveNumber(b, precision, false);
    }

    public static BigDecimal setEffectiveNumber(Object b) {
        return setEffectiveNumber(b, DEFAULT_PRECISION, false);
    }

}