数字转中文大写JAVA

一般在收据打印过程中,可能会要求展示中文大写金额,以下提供两种实现。

1正常代码逻辑处理

优点:易理解,好维护

缺点:代码较长

package com.test;

import java.math.BigDecimal;

public class NumberToChinese {
    private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    private static final String[] UNITS = {"", "拾", "佰", "仟"};
    private static final String[] BIG_UNITS = {"", "万", "亿", "兆"};

    public static String numberToChinese(double number) {
        boolean isNegative = number < 0;
        number = Math.abs(number);

        BigDecimal bigDecimal = new BigDecimal(String.valueOf(number));
        long integerPart = bigDecimal.longValue();
        int decimalPart = (bigDecimal.subtract(new BigDecimal(integerPart)).multiply(new BigDecimal(100))).intValue();

        if (integerPart == 0 && decimalPart == 0) {
            return isNegative ? "负零元整" : "零元整";
        }

        StringBuilder result = new StringBuilder();
        int unitIndex = 0;
        boolean zeroFlag = false;
        while (integerPart > 0) {
            long group = integerPart % 10000;
            if (group != 0) {
                if (zeroFlag) {
                    result.insert(0, "零");
                }
                result.insert(0, BIG_UNITS[unitIndex]);
                result.insert(0, groupToChinese(group));
                zeroFlag = false;
            } else {
                zeroFlag = true;
            }
            integerPart /= 10000;
            unitIndex++;
        }

        // 去除多余的零
        while (result.length() > 0 && result.charAt(0) == '零') {
            result.deleteCharAt(0);
        }

        // 如果小数部分为 0,直接添加“元整”
        if (decimalPart == 0) {
            // 避免出现“零元整”情况,这里判断结果最后是否是大单位,如果是直接加“整”
            if (result.length() > 0 && isBigUnit(result.charAt(result.length() - 1))) {
                result.append("整");
            } else if("零".equals(result.substring(result.length() - 1,result.length()))) {
                result.replace(result.length() - 1,result.length(),"").append("元整");
            }else{
                result.append("元整");
            }
        } else {
            result.append("元");
            String decimalStr = decimalToChinese(decimalPart);
            if (!decimalStr.isEmpty()) {
                result.append(decimalStr);
            }
        }


        if (isNegative) {
            result.insert(0, "负");
        }

        return result.toString();
    }

    private static String groupToChinese(long group) {
        StringBuilder groupResult = new StringBuilder();
        boolean zeroFlag = false;
        for (int i = 0; i < 4; i++) {
            int digit = (int) (group / (long) Math.pow(10, 3 - i) % 10);
            if (digit != 0) {
                if (zeroFlag) {
                    groupResult.append("零");
                }
                groupResult.append(NUMBERS[digit]).append(UNITS[3 - i]);
                zeroFlag = false;
            } else {
                zeroFlag = true;
            }
        }
        String result = groupResult.toString();
        if (result.endsWith("零")) {
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

    private static String decimalToChinese(int decimalPart) {
        StringBuilder decimalResult = new StringBuilder();
        int jiao = decimalPart / 10;
        int fen = decimalPart % 10;

        if (jiao != 0) {
            decimalResult.append(NUMBERS[jiao]).append("角");
        } else if (fen != 0) {
            decimalResult.append("零");
        }

        if (fen != 0) {
            decimalResult.append(NUMBERS[fen]).append("分");
        }

        return decimalResult.toString();
    }

    private static boolean isBigUnit(char c) {
        for (String unit : BIG_UNITS) {
            if (unit.length() > 0 && unit.charAt(0) == c) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        double positiveInteger = 510000.00;
        double positiveDecimal = 12345.67;
        double negativeInteger = -500000.00;
        double negativeDecimal = -12345.67;
        double zeroNumber = 0;
        double wan = 51111.00;

        String positiveIntegerChinese = numberToChinese(positiveInteger);
        String positiveDecimalChinese = numberToChinese(positiveDecimal);
        String negativeIntegerChinese = numberToChinese(negativeInteger);
        String negativeDecimalChinese = numberToChinese(negativeDecimal);
        String zeroChinese = numberToChinese(zeroNumber);
        String wanChinese = numberToChinese(wan);

        System.out.println("正整数金额转换结果: " + positiveIntegerChinese);
        System.out.println("正小数金额转换结果: " + positiveDecimalChinese);
        System.out.println("负整数金额转换结果: " + negativeIntegerChinese);
        System.out.println("负小数金额转换结果: " + negativeDecimalChinese);
        System.out.println("零金额转换结果: " + zeroChinese);
        System.out.println("wan转换结果: " + wanChinese);
    }
}

代码方法作用解释:

  1. 常量定义

    • NUMBERS:存储中文数字大写字符。
    • UNITS:存储整数部分每四位一组内的单位(个、十、百、千)。
    • BIG_UNITS:存储整数部分每四位一组的大单位(万、亿、兆)。
    • DECIMAL_UNIT:存储小数部分的单位(角、分)。
  2. numberToChinese 方法

    • 使用 BigDecimal 处理输入的数字,避免浮点数精度问题。
    • 分离整数部分和小数部分。
    • 处理整数部分,按每四位一组进行转换,并添加大单位。
    • 处理小数部分,根据小数位的值添加对应的中文大写和单位。
  3. groupToChinese 方法

    • 将每四位一组的数字转换为中文大写。
    • 处理连续零的情况,避免出现多余的零。

2使用正则

优点:代码片段短

缺点:使用了正则的贪婪符号,可能会造成代码回溯情况,严重可造成阻断风险

关于正则常见贪婪字符,点击查看

public static String digitUppercase(double n){
        String[] fraction = {"角", "分"};
        String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
        String[][] unit = {
  
  {"元", "万", "亿"},
                {"", "拾", "佰", "仟"}};

        String head = n < 0? "负": "";
        n = Math.abs(n);

        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            BigDecimal bd = BigDecimal.valueOf(n);
            bd = bd.setScale(2, bd.ROUND_HALF_EVEN);
            BigDecimal rs = bd.multiply(BigDecimal.valueOf(10)).multiply(BigDecimal.valueOf(Math.pow(10, i))).divideAndRemainder(new BigDecimal(10))[1];
            s+=(digit[(int)(Math.floor(rs.doubleValue()))]+ fraction[i]).replaceAll("(零.)+", "");
        }
        if(s.length()<1){
            s = "整";
        }
        int integerPart = (int)Math.floor(n);

        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p ="";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart%10]+unit[1][j] + p;
                integerPart = integerPart/10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值