Java封装数值处理工具类

package com.it.utils.poi.excel;

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

/**
 * @remark: 数值操作工具类
 * @author: 狠穿
 * @createTime: 2024-05-14 17:10
 * @remark: 工具类基于原生JDK实现,不依赖任何第三方框架
 **/
public class NumberUtil {

    public static final int ZERO = 0;

    public static final int ONE = 1;

    public static final int TEN = 10;

    public static final int HUNDRED = 100;

    public static final int THOUSAND = 1000;

    public static final int TEN_THOUSAND = 10000;

    private static final int DEFAULT_SCALE = 2;

    private static final String NUMERIC_REGEX = "^-?\\d+(\\.\\d+)?$";

    private static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_UP;

    private NumberUtil() {
    }

    /**
     * 精确的加法计算
     *
     * @param a 被加数
     * @param b 加数
     * @return 两数之和
     */
    public static Double add(Double a, Double b) {
        if (a == null || b == null) {
            throw new ArithmeticException("运算异常,四则运算时出现非法数值!");
        }
        return new BigDecimal(String.valueOf(a)).add(new BigDecimal(String.valueOf(b))).doubleValue();
    }

    /**
     * 尝试进行加法运算
     *
     * @param a 加数
     * @param b 被加数
     * @return 两数之和 当加数或被加数中存在null值,则视null为0,使用需谨慎
     */
    public static Double tryAdd(Double a, Double b) {
        a = (a == null ? ZERO : a);
        b = (b == null ? ZERO : b);
        return add(a, b);
    }

    /**
     * 精确的减法计算
     *
     * @param a 被减数
     * @param b 被加数
     * @return 两数之差
     */
    public static Double subtract(Double a, Double b) {
        if (a == null || b == null) {
            throw new ArithmeticException("运算异常,四则运算时出现空值!");
        }
        return new BigDecimal(String.valueOf(a)).subtract(new BigDecimal(String.valueOf(b))).doubleValue();
    }

    /**
     * 精确的乘法计算
     *
     * @param a 被乘数
     * @param b 乘数
     * @return 两数之积
     */
    public static Double multiply(Double a, Double b) {
        if (a == null || b == null) {
            throw new ArithmeticException("运算异常,四则运算时出现空值!");
        }
        return new BigDecimal(String.valueOf(a)).multiply(new BigDecimal(String.valueOf(b))).doubleValue();
    }

    /**
     * 精确的除法计算,使用默认精度和默认舍入模式
     *
     * @param a 被除数
     * @param b 除数
     * @return 两数之商
     */
    public static Double divide(Double a, Double b) {
        return divide(a, b, DEFAULT_SCALE, DEFAULT_ROUNDING_MODE).doubleValue();
    }

    /**
     * 精确的除法计算,使用自定义精度和默认舍入模式
     *
     * @param a 被除数
     * @param b 除数
     * @return 两数之商
     */
    public static Double divide(Double a, Double b, int scale) {
        return divide(a, b, scale, DEFAULT_ROUNDING_MODE);
    }

    /**
     * 精确的除法计算,使用自定义精度和自定义舍入模式
     *
     * @param a 被除数
     * @param b 除数
     * @return 两数之商
     */
    public static Double divide(Double a, Double b, int scale, RoundingMode roundingMode) {
        if (a == null || b == null) {
            throw new ArithmeticException("运算异常,四则运算时出现空值!");
        }
        if (b == ZERO) {
            throw new ArithmeticException("除法运算时,分母不可为零!");
        }
        if (scale < 0) {
            throw new IllegalArgumentException("参数异常,精度不可为负数!");
        }
        if (roundingMode == null) {
            throw new IllegalArgumentException("参数异常,舍入模式不可为空!");
        }
        return new BigDecimal(String.valueOf(a)).divide(new BigDecimal(String.valueOf(b)), scale, roundingMode).doubleValue();
    }

    /**
     * 求大精度数值的n次幂
     *
     * @param val 常数
     * @param n   指数
     * @return
     */
    public static BigDecimal pow(BigDecimal val, int n) {
        if (val == null) {
            throw new IllegalArgumentException("参数异常,指数函数中常数不可为null");
        }
        return val.pow(n);
    }

    /**
     * 判断某个对象是否可转换成数值
     *
     * @param number 数值对象
     * @return 能否被转换成数值类型
     */
    public static boolean isNumber(Object number) {
        if (number == null) {
            return false;
        }
        try {
            Double.parseDouble(String.valueOf(number));
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }


    /**
     * 将任意类型尝试转换成大精度浮点数
     *
     * @param val 待转换的对象
     * @return 转换成功返回对应的大精度浮点数, 转换失败返回null
     */
    public static BigDecimal toBigDecimal(Object val) {
        return isNumber(val) ? new BigDecimal(val.toString().trim()) : null;
    }

    /**
     * 将字符串尝试转换成数值,无法转换成数值时使用默认值
     *
     * @param val        带转换的字符串
     * @param defaultVal 默认值
     * @return 当字符串能转换成数值时则返回对应的大精度浮点,否则返回默认值
     */
    public static BigDecimal parseNumber(String val, BigDecimal defaultVal) {
        if (isNumber(val)) {
            return toBigDecimal(val);
        }
        return defaultVal;
    }

    /**
     * 判断两个大精度数值是否相等
     *
     * @param a 数值a
     * @param b 数值b
     * @return 是否相等
     */
    public static boolean isEquals(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) {
            throw new IllegalArgumentException("参数异常,待比较的数据中存在空值!");
        }
        return a.compareTo(b) == 0;
    }

    /**
     * 判断某个大精度数值是否大于另一个大精度数值
     *
     * @param a 数值a
     * @param b 数值b
     * @return 是否大于
     */
    public static boolean isGreaterThan(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) {
            throw new IllegalArgumentException("参数异常,待比较的数据中存在空值!");
        }
        return a.compareTo(b) > 0;
    }

    /**
     * 判断某个大精度数值是否大于或者等于另一个大精度数值
     *
     * @param a 数值a
     * @param b 数值b
     * @return 是否大于或者等于
     */
    public static boolean isGreaterThanOrEquals(BigDecimal a, BigDecimal b) {
        // return isGreaterThan(a,b) || isEquals(a,b);
        if (a == null || b == null) {
            throw new IllegalArgumentException("参数异常,待比较的数据中存在空值!");
        }
        return a.compareTo(b) >= 0;
    }

    /**
     * 判断某个大精度数值是否小于另一个大精度数值
     *
     * @param a 数值a
     * @param b 数值b
     * @return 是否小于
     */
    public static boolean isLessThan(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) {
            throw new IllegalArgumentException("参数异常,待比较的数据中存在空值!");
        }
        return a.compareTo(b) < 0;
    }

    /**
     * 判断某个大精度数值是否小于或者等于另一个大精度数值
     *
     * @param a 数值a
     * @param b 数值b
     * @return 是否小于或者等于
     */
    public static boolean isLessThanOrEquals(BigDecimal a, BigDecimal b) {
        // return isLessThan(a,b) || isEquals(a,b);
        if (a == null || b == null) {
            throw new IllegalArgumentException("参数异常,待比较的数据中存在空值!");
        }
        return a.compareTo(b) <= 0;
    }

    /**
     * 计算某个数值的有效位数
     * 有效位数的定义:从第一个非0的数字开始,到最后一位结束,算有效位数;其中,对于科学计数法而言,有效位数只看E左侧的内容,规则同常规数值一致
     * 例如:
     *  0.0120    有3位有效数字,分别是1、2、0
     *  3500     有4位有效数字,分别是3、5、0、0
     *  1.23E+5   有3位有效数字,分别是1、2、3
     *  0.650E-2  有三位有效数字,分别是6、5、0
     */
    public static int getTheNumberOfSignificantDigits(String num){
        if(!NumberUtil.isNumber(num)){
            throw new IllegalArgumentException("num is not a legal number");
        }
        if(num.contains("E")){
            num = num.substring(0,num.indexOf("E"));
        }
        if(num.contains(".")){
            num = num.replace(".","");
        }
        char[] chars = num.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char ch = chars[i];
            if(ch != '0'){
                return num.substring(i).length();
            }
        }
        return 0;
    }

    /**
     * 对某个数保留N位有效数字
     * @param val 待处理的字符串
     * @param precision 有效数字位数
     * @return
     * @remark 该方法默认使用四舍五入舍入模式,基于原生JDK提供的API实现
     */
    public static String retainSignificantDigits(String val,int precision){
        if(!isNumber(val)){
            throw new IllegalArgumentException("valStr is not a legal number!");
        }
        if(precision < 1){
            throw new IllegalArgumentException("precision must greater than zero!");
        }
        return new BigDecimal(val).round(new MathContext(precision,RoundingMode.HALF_UP)).toString();
    }


    public static void main(String[] args) {
        System.out.println(retainSignificantDigits("10.01",2));
    }


}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值