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));
}
}
Java封装数值处理工具类
最新推荐文章于 2024-08-16 23:08:28 发布