package com.ruoyi.common.utils; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.NumberFormat; import java.text.ParseException; import java.util.Arrays; import java.util.List; import java.util.Locale; /** * 字符串工具类 * * @author ruoyi */ public class DecimalUtils { private static final List CN_NUMBERS = Arrays.asList("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"); private static final List CN_UNITS = Arrays.asList("", "拾", "佰", "仟"); private static final List CN_BIG_UNITS = Arrays.asList("", "万", "亿", "兆"); private static final String CN_NEGATIVE = "负"; private static final String CN_INTEGER = "整"; private static final String CN_FULL = "圆"; private static final String CN_DECIMAL_UNIT = "角分"; private static final int MAXIMUM_NUMBER = 999999999; /** * 将金额数字转换为中文大写 * @param amount 金额数字,支持最大到999999999.99 * @return 中文大写金额字符串 */ public static String bigDecimalToChinese(BigDecimal amount) { if (amount == null) { throw new IllegalArgumentException("金额不能为空"); } // 检查金额范围 if (amount.abs().compareTo(new BigDecimal(MAXIMUM_NUMBER + ".99")) > 0) { throw new IllegalArgumentException("金额超出最大范围(999999999.99)"); } StringBuilder result = new StringBuilder(); // 处理负数 if (amount.compareTo(BigDecimal.ZERO) < 0) { result.append(CN_NEGATIVE); amount = amount.abs(); } // 转换为字符串处理 String amountStr = amount.setScale(2, BigDecimal.ROUND_HALF_UP).toString(); String[] parts = amountStr.split("\\."); String integerPart = parts[0]; String decimalPart = parts.length > 1 ? parts[1] : ""; // 处理整数部分 boolean hasInteger = !"0".equals(integerPart); if (hasInteger) { result.append(convertIntegerPart(integerPart)).append(CN_FULL); } // 处理小数部分 String decimalStr = convertDecimalPart(decimalPart); if (!decimalStr.isEmpty()) { // 如果没有整数部分且有小部分,则不显示"零圆" if (!hasInteger && decimalStr.charAt(0) != CN_NUMBERS.get(0).charAt(0)) { result.append(decimalStr); } else { // 如果有整数部分或小数部分以零开头,则正常拼接 if (!hasInteger) { result.append(CN_NUMBERS.get(0)).append(CN_FULL); } result.append(decimalStr); } } else { // 如果没有小数部分,添加"整" result.append(CN_INTEGER); } return result.toString(); } private static String convertIntegerPart(String integerPart) { StringBuilder sb = new StringBuilder(); int length = integerPart.length(); int zeroCount = 0; // 连续零的个数 for (int i = 0; i < length; i++) { int digit = Character.getNumericValue(integerPart.charAt(i)); int pos = length - i - 1; // 当前位数 int unitPos = pos % 4; // 单位位置(个十百千) int bigUnitPos = pos / 4; // 大单位位置(万,亿) if (digit == 0) { zeroCount++; } else { if (zeroCount > 0) { sb.append(CN_NUMBERS.get(0)); zeroCount = 0; } sb.append(CN_NUMBERS.get(digit)).append(CN_UNITS.get(unitPos)); } // 添加大单位(万,亿) if (unitPos == 0 && bigUnitPos > 0) { if (zeroCount < 4) { // 如果当前段不全为零 sb.append(CN_BIG_UNITS.get(bigUnitPos)); } zeroCount = 0; } } // 处理全零的情况 if (sb.length() == 0) { return CN_NUMBERS.get(0); } return sb.toString(); } private static String convertDecimalPart(String decimalPart) { StringBuilder sb = new StringBuilder(); boolean hasNonZero = false; for (int i = 0; i < decimalPart.length() && i < CN_DECIMAL_UNIT.length(); i++) { int digit = Character.getNumericValue(decimalPart.charAt(i)); if (digit != 0) { sb.append(CN_NUMBERS.get(digit)).append(CN_DECIMAL_UNIT.charAt(i)); hasNonZero = true; } else if (hasNonZero || (i > 0 && sb.length() > 0)) { // 如果前面已经有非零数字,或者不是第一位,可以添加零 sb.append(CN_NUMBERS.get(0)); } } // 去除末尾的零 while (sb.length() > 0 && sb.charAt(sb.length() - 1) == CN_NUMBERS.get(0).charAt(0)) { sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } //默认除法运算精度 private static final int DEF_DIV_SCALE = 10; /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static BigDecimal add(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.add(b2); } /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @param scale 保留scale 位小数 * @return 两个参数的和 */ public static String add(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.add(b2).setScale(scale, RoundingMode.HALF_UP).toString(); } /** * 提供精确的减法运算 * * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精确的减法运算。 * * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static BigDecimal sub(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.subtract(b2); } /** * 提供精确的减法运算 * * @param v1 被减数 * @param v2 减数 * @param scale 保留scale 位小数 * @return 两个参数的差 */ public static String sub(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString(); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static double mul(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static BigDecimal mul(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.multiply(b2); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @param scale 保留scale 位小数 * @return 两个参数的积 */ public static double mul(double v1, double v2, int scale) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return round(b1.multiply(b2).doubleValue(), scale); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @param scale 保留scale 位小数 * @return 两个参数的积 */ public static String mul(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.multiply(b2).setScale(scale, RoundingMode.HALF_UP).toString(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后10位,以后的数字四舍五入 * * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入 * * @param v1 被除数 * @param v2 除数 * @param scale 表示表示需要精确到小数点以后几位。 * @return 两个参数的商 */ public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入 * * @param v1 被除数 * @param v2 除数 * @param scale 表示需要精确到小数点以后几位 * @return 两个参数的商 */ public static String div(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v1); return b1.divide(b2, scale, RoundingMode.HALF_UP).toString(); } /** * 提供精确的小数位四舍五入处理 * * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); return b.setScale(scale, RoundingMode.HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理 * * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static String round(String v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(v); return b.setScale(scale, RoundingMode.HALF_UP).toString(); } /** * 取余数 * * @param v1 被除数 * @param v2 除数 * @param scale 小数点后保留几位 * @return 余数 */ public static String remainder(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.remainder(b2).setScale(scale, RoundingMode.HALF_UP).toString(); } /** * 取余数 BigDecimal * * @param v1 被除数 * @param v2 除数 * @param scale 小数点后保留几位 * @return 余数 */ public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } return v1.remainder(v2).setScale(scale, RoundingMode.HALF_UP); } /** * 比较大小 * * @param v1 被比较数 * @param v2 比较数 * @return 如果v1 大于v2 则 返回true 否则false */ public static boolean compare(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); int bj = b1.compareTo(b2); boolean res; res = bj > 0; return res; } /** * 将数字格式化为千分位 * * @param number * @return 字符串 */ public static String convert(BigDecimal number) { if (null == number || number.compareTo(BigDecimal.ZERO) == 0) { return ""; } NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.ENGLISH); // 设置最大分数位数,这里设置为0表示不使用分数 numberFormat.setMaximumFractionDigits(2); // 设置最小整数位数,这里设置为2表示整数部分至少2位 //numberFormat.setMinimumIntegerDigits(2); // 设置grouping used属性为false,表示不使用千分位分隔符 numberFormat.setGroupingUsed(true); return numberFormat.format(number); } /** * 将千分位数字字符串格式化为 BigDecimal * @param formattedNumber * @return 字符串 */ public static BigDecimal convert(String formattedNumber) { if (StringUtils.isEmpty(formattedNumber)) { return BigDecimal.ZERO; } try { NumberFormat format = NumberFormat.getInstance(Locale.US); Number number = format.parse(formattedNumber); BigDecimal bigDecimal = new BigDecimal(number.toString()); return bigDecimal; } catch (ParseException e) { e.printStackTrace(); return BigDecimal.ZERO; } } public static boolean isZero_s(BigDecimal b) { return null == b || b.compareTo(BigDecimal.ZERO) == 0; } /** * 将是0的处理成空 * @param number * @return BigDecimal */ public static String zeroToNull(BigDecimal number) { if(number.compareTo(BigDecimal.ZERO) == 0){ return null; }else{ return number.toString(); } } }