Java实现币种大写数额转为阿拉伯数字

一、不带数字的金额直接转成阿拉伯数字
项目需求要将中文大写数字转为阿拉伯数字
三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍万 ---------------> 33045020076050000

package test;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * @describe: 不带数字的金额直接转成阿拉伯数字
 * @author: 容若
 * @created: 2024-03-06 16:22
 */
public class ChineseToArabic {
    /**
     * 中文数字
     */
    private static char[] cnArr_a = new char [] {'零','一','二','三','四','五','六','七','八','九'};
    private static char[] cnArr_A = new char [] {'零','壹','贰','叁','肆','伍','陆','柒','捌','玖'};
    private static final String allChineseNum = "零一二三四五六七八九壹贰叁肆伍陆柒捌玖十拾百佰千仟万萬亿";

    /**
     * 中文单位
     */
    private static char[] unit_a = new char [] {'亿','万','千','百','十'};
    private static char[] unit_A = new char [] {'亿','萬','仟','佰','拾'};
    private static final String allChineseUnit = "十拾百佰千仟万萬亿";

    /**
     * 将汉字中的数字转换为阿拉伯数字
     * (例如:三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍)
     *
     * @param chineseNum;
     * @return long
     */
    public static BigDecimal chineseNumToArabicNum(String chineseNum) {
        try {
            // 最终返回的结果
            BigDecimal result = new BigDecimal(0);

            if (chineseNum == null || chineseNum.trim().length() == 0) {
                return result;
            }

            char firstUnit = chineseNum.charAt(0);
            char lastUnit = chineseNum.charAt(chineseNum.length() - 1);

            Boolean appendUnit = true;
            long lastUnitNum = 1;
            if (isCnUnit(firstUnit) && chineseNum.length() > 1) {
                // 两位数
                long firstNum = chnNameValue[chnUnitToValue(String.valueOf(firstUnit))].value;
                if (!isCnUnit(lastUnit) && chineseNum.length() == 2) {
                    long number = chnStringToNumber(String.valueOf(lastUnit));
                    result = result.add(BigDecimal.valueOf(firstNum).add(BigDecimal.valueOf(number)));
                    return result;
                } else if (isCnUnit(lastUnit)) {
                    ChnNameValue chnValue = chnNameValue[chnUnitToValue(String.valueOf(lastUnit))];
                    if (firstNum == 10 && chnValue.secUnit) {
                        chineseNum = "一" + chineseNum;
                    } else {
                        throw new NumberFormatException("中文数字异常");
                    }
                }
            }

            if (isCnUnit(lastUnit)) {
                chineseNum = chineseNum.substring(0, chineseNum.length() - 1);
                lastUnitNum = chnNameValue[chnUnitToValue(String.valueOf(lastUnit))].value;
                appendUnit = chnNameValue[chnUnitToValue(String.valueOf(lastUnit))].secUnit;
            }else if (chineseNum.length() == 1) {
                // 如果长度为1时
                int num = strToNum(chineseNum);
                if (num != -1) {
                    return BigDecimal.valueOf(num);
                } else {
                    return null;
                }
            }

            // 将小写中文数字转为大写中文数字
            for (int i = 0; i < cnArr_a.length; i++) {
                chineseNum = chineseNum.replaceAll(String.valueOf(cnArr_a[i]), String.valueOf(cnArr_A[i]));
            }
            // 将小写单位转为大写单位
            for (int i = 0; i < unit_a.length; i++) {
                chineseNum = chineseNum.replaceAll(String.valueOf(unit_a[i]), String.valueOf(unit_A[i]));
            }

            for (int i = 0; i < unit_A.length; i++) {
                if (chineseNum.trim().length() == 0) {
                    break;
                }
                String unitUpperCase = String.valueOf(unit_A[i]);
                String str = null;
                if (chineseNum.contains(unitUpperCase)) {
                    str = chineseNum.substring(0, chineseNum.lastIndexOf(unitUpperCase) + 1);
                }
                if (str != null && str.trim().length() > 0) {
                    // 下次循环截取的基础字符串
                    chineseNum = chineseNum.replaceAll(str, "");
                    // 单位基础值
                    long unitNum = chnNameValue[chnUnitToValue(unitUpperCase)].value;
                    String temp = str.substring(0, str.length() - 1);
                    long number = chnStringToNumber(temp);
                    result = result.add(BigDecimal.valueOf(number).multiply(BigDecimal.valueOf(unitNum)));
                }
                // 最后一次循环,被传入的数字没有处理完并且没有单位的个位数处理
                if (i + 1 == unit_a.length && !"".equals(chineseNum)) {
                    long number = chnStringToNumber(chineseNum);
                    if (!appendUnit) {
                        number = BigDecimal.valueOf(number).multiply(BigDecimal.valueOf(lastUnitNum)).longValue();
                    }
                    result = result.add(BigDecimal.valueOf(number));
                }
            }
            // 加上单位
            if (appendUnit && lastUnitNum > 1) {
                result = result.multiply(BigDecimal.valueOf(lastUnitNum));
            } else if (lastUnitNum > 0) {
                if (result.compareTo(BigDecimal.ZERO) == BigDecimal.ZERO.intValue()) {
                    result = BigDecimal.ONE;
                    result = result.multiply(BigDecimal.valueOf(lastUnitNum));
                }
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 返回中文数字汉字所对应的阿拉伯数字,若str不为中文数字,则返回-1
     *
     * @param string;
     * @return int
     */
    private static int strToNum(String string){
        for(int i = 0;i<cnArr_a.length;i++){
            if (Objects.equals(string,String.valueOf(cnArr_a[i])) || Objects.equals(string,String.valueOf(cnArr_A[i]))){
                return i;
            }
        }
        return -1;
    }

    /**
     * 判断传入的字符串是否全是汉字数字和单位
     *
     * @param chineseStr;
     * @return boolean
     */
    public static boolean isCnNumAll(String chineseStr){
        if (isBlank(chineseStr)){
            return true;
        }
        char [] charArray = chineseStr.toCharArray();
        for(char c : charArray){
            if (!allChineseNum.contains(String.valueOf(c))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串是空的
     *
     * @param cs
     * @return
     */
    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs != null && (strLen = cs.length()) != 0) {
            for (int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return false;
                }
            }
            return true;
        } else {
            return true;
        }
    }

    /**
     * 判断传入的字符是否是汉字数字和单位
     *
     * @param chineseChar;
     * @return boolean
     */
    public static boolean isCnNum(char chineseChar) {
        if (!allChineseNum.contains(String.valueOf(chineseChar))) {
            return false;
        }else{
            return true;
        }
    }

    /**
     * 判断是否是中文单位
     *
     * @param unitStr;
     * @return boolean
     */
    public static boolean isCnUnit(char unitStr) {
        if (!allChineseUnit.contains(String.valueOf(unitStr))) {
            return false;
        }else{
            return true;
        }
    }

    /**
     * 中文转换成阿拉伯数字,中文字符串除了包括0-9的中文汉字,还包括十,百,千,万等权位。
     * 此处是完成对这些权位的类型定义。
     * name是指这些权位的汉字字符串。
     * value是指权位多对应的数值的大小。诸如:十对应的值的大小为10,百对应为100等
     * secUnit若为true,代表该权位为节权位,即万,亿,万亿等
     */
    public static class ChnNameValue{
        String name;
        long value;
        Boolean secUnit;
        ChnNameValue(String name,long value,Boolean secUnit){
            this.name=name;
            this.value=value;
            this.secUnit=secUnit;
        }
    }

    static ChnNameValue chnNameValue[] = {
            new ChnNameValue("十",10,false),
            new ChnNameValue("拾",10,false),
            new ChnNameValue("百",100,false),
            new ChnNameValue("佰",100,false),
            new ChnNameValue("千",1000,false),
            new ChnNameValue("仟",1000,false),
            new ChnNameValue("万",10000,true),
            new ChnNameValue("萬",10000,true),
            new ChnNameValue("亿",100000000,true)
    };

    /**
     * 返回中文汉字权位在chnNameValue数组中所对应的索引号,若不为中文汉字权位,则返回-1
     *
     * @param str;
     * @return int
     */
    private static int chnUnitToValue(String str){
        for(int i=0;i<chnNameValue.length;i++){
            if(str.equals(chnNameValue[i].name)){
                return i;
            }
        }
        return -1;
    }

    /**
     * 返回中文数字字符串所对应的int类型的阿拉伯数字
     * (千亿/12位数)
     *
     * @param str;
     * @return long
     */
    private static long chnStringToNumber(String str){
        long returnNumber=0;
        long section=0;
        int index=0;
        long number=0;
        while (index<str.length()){
            // 从左向右依次获取对应中文数字,取不到返回-1
            int num = strToNum(str.substring(index,index+1));
            //若num>=0,代表该位置(pos),所对应的是数字不是权位。若小于0,则表示为权位
            if(num >= 0){
                number = num;
                index++;
                //pos是最后一位,直接将number加入到section中。
                if(index>=str.length()){
                    section += number;
                    returnNumber += section;
                    break;
                }
            }else{
                int chnNameValueIndex=chnUnitToValue(str.substring(index,index+1));

                if (chnNameValueIndex == -1) {
                    // 字符串存在除 数字和单位 以外的中文
                    throw new NumberFormatException("字符串存在除 <数字和单位> 以外的中文");
                }

                //chnNameValue[chnNameValueIndex].secUnit==true,表示该位置所对应的权位是节权位,
                if(chnNameValue[chnNameValueIndex].secUnit){
                    section = (section + number) * chnNameValue[chnNameValueIndex].value;
                    returnNumber += section;
                    section=0;
                }else{
                    section += number*chnNameValue[chnNameValueIndex].value;
                }
                index++;
                number=0;
                if(index>=str.length()){
                    returnNumber += section;
                    break;
                }
            }
        }
        return returnNumber;
    }

    public static void main(String[] args) {
        String str = "三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍万";
        String str1 = "三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍";
        String str2 = "三万叁仟零肆拾伍亿零柒仟陆佰零伍";
        String str3 = "三仟零肆十万";
        String str4 = "三万三千";
        String str5 = "三万零四十";
        String str6 = "三万叁仟零肆拾伍亿";
        String str7 = "叁仟贰佰肆拾伍万陆仟柒佰捌拾玖";
        String str8 = "十五";
        String str9 = "十万";
        String str10 = "十一万";
        String str11 = "九十一万";
        String str12 = "十亿";
        String str13 = "十五亿";
        String str14 = "一百";
        String str15 = "一百零一";
        String str16 = "一千";
        String str17 = "一千零一";
        String str18 = "一千零一十";


        System.out.println();
        System.out.println(">>> " + str + " : " + chineseNumToArabicNum(str));
        System.out.println(">>> " + str1 + " : " + chineseNumToArabicNum(str1));
        System.out.println(">>> " + str2 + " : " + chineseNumToArabicNum(str2));
        System.out.println(">>> " + str3 + " : " + chineseNumToArabicNum(str3));
        System.out.println(">>> " + str4 + " : " + chineseNumToArabicNum(str4));
        System.out.println(">>> " + str5 + " : " + chineseNumToArabicNum(str5));
        System.out.println(">>> " + str6 + " : " + chineseNumToArabicNum(str6));
        System.out.println(">>> " + str7 + " : " + chineseNumToArabicNum(str7));
        System.out.println(">>> " + str8 + " : " + chineseNumToArabicNum(str8));
        System.out.println(">>> " + str9 + " : " + chineseNumToArabicNum(str9));
        System.out.println(">>> " + str10 + " : " + chineseNumToArabicNum(str10));
        System.out.println(">>> " + str11 + " : " + chineseNumToArabicNum(str11));
        System.out.println(">>> " + str12 + " : " + chineseNumToArabicNum(str12));
        System.out.println(">>> " + str13 + " : " + chineseNumToArabicNum(str13));
        System.out.println(">>> " + str14 + " : " + chineseNumToArabicNum(str14));
        System.out.println(">>> " + str15 + " : " + chineseNumToArabicNum(str15));
        System.out.println(">>> " + str16 + " : " + chineseNumToArabicNum(str16));
        System.out.println(">>> " + str17 + " : " + chineseNumToArabicNum(str17));
        System.out.println(">>> " + str18 + " : " + chineseNumToArabicNum(str18));
    }

}

执行结果:

>>> 三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍万 : 33045020076050000
>>> 三万叁仟零肆拾伍亿零贰佰萬柒仟陆佰零伍 : 3304502007605
>>> 三万叁仟零肆拾伍亿零柒仟陆佰零伍 : 3304500007605
>>> 三仟零肆十万 : 30400000
>>> 三万三千 : 33000
>>> 三万零四十 : 30040
>>> 三万叁仟零肆拾伍亿 : 3304500000000
>>> 叁仟贰佰肆拾伍万陆仟柒佰捌拾玖 : 32456789
>>> 十五 : 15
>>> 十万 : 100000
>>> 十一万 : 110000
>>> 九十一万 : 910000
>>> 十亿 : 1000000000
>>> 十五亿 : 1500000000
>>> 一百 : 100
>>> 一百零一 : 101
>>> 一千 : 1000
>>> 一千零一 : 1001
>>> 一千零一十 : 1010

第二种方式:

package test;

import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Map;

/**
 * @author dcx
 * @description 中文金额转数字金额, 如 肆千零叁拾五亿圆 --> 403500000000
 * @date 2024年02月18日 16:48
 */
public class ChAmountToNumAmount {
    private static final Map<String, BigInteger> map_num = new HashMap<>();
    private static final Map<String, BigInteger> map_union = new HashMap<>();

    static {
        map_num.put("一", BigInteger.valueOf(1));
        map_num.put("二", BigInteger.valueOf(2));
        map_num.put("三", BigInteger.valueOf(3));
        map_num.put("四", BigInteger.valueOf(4));
        map_num.put("五", BigInteger.valueOf(5));
        map_num.put("六", BigInteger.valueOf(6));
        map_num.put("七", BigInteger.valueOf(7));
        map_num.put("八", BigInteger.valueOf(8));
        map_num.put("九", BigInteger.valueOf(9));


        map_num.put("壹", BigInteger.valueOf(1));
        map_num.put("贰", BigInteger.valueOf(2));
        map_num.put("叁", BigInteger.valueOf(3));
        map_num.put("肆", BigInteger.valueOf(4));
        map_num.put("伍", BigInteger.valueOf(5));
        map_num.put("陆", BigInteger.valueOf(6));
        map_num.put("柒", BigInteger.valueOf(7));
        map_num.put("捌", BigInteger.valueOf(8));
        map_num.put("玖", BigInteger.valueOf(9));

        map_union.put("十", BigInteger.valueOf(10));
        map_union.put("拾", BigInteger.valueOf(10));
        map_union.put("百", BigInteger.valueOf(100));
        map_union.put("佰", BigInteger.valueOf(100));
        map_union.put("千", BigInteger.valueOf(1000));
        map_union.put("仟", BigInteger.valueOf(1000));
        map_union.put("万", BigInteger.valueOf(10000));
        map_union.put("萬", BigInteger.valueOf(10000));
        map_union.put("亿", BigInteger.valueOf(100000000));
    }


    public static synchronized String toNumAmount(String str) {
        String result = getStr(str.replace("元", "").replace("圆", "").replace("整", "").replace("¥", ""));
        return "0".equals(result) ? str : result;
    }

    public static String getStr(String param) {
        String str = param.trim();
        if (str.matches("\\d*\\.?\\d*")) {
            //如果全为数子,或有小数点,则直接返回
            return str;
        }
        ArrayDeque<String> left = new ArrayDeque<>();
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char aChar = chars[i];
            if (i == 0 && (aChar == '十' || aChar == '拾')) {
                left.add("壹");
                left.add("拾");
            } else {
                left.add(String.valueOf(aChar));
            }
        }
        ArrayDeque<String> right = new ArrayDeque<>();
        while (!left.isEmpty()) {
            String item = left.pop();
            if (map_union.containsKey(item)) {
                String pop = right.pop();
                BigInteger multiply = BigInteger.valueOf(Long.parseLong(pop));
                if (!left.isEmpty() || !"万萬亿".contains(item)) {
                    multiply = multiply.multiply(map_union.get(item));
                    right.push(multiply.toString());
                } else {
                    right.push(multiply.toString());
                    right.push(item);
                }
            } else if (map_num.containsKey(item)) {
                right.push(map_num.get(item).toString());
            }
        }
        BigInteger multiply = BigInteger.ZERO;
        while (!right.isEmpty()) {
            String pop = right.pollLast();
            if (map_union.containsKey(pop)) {
                multiply = multiply.multiply(map_union.get(pop));
            } else {
                multiply = multiply.add(BigInteger.valueOf(Long.parseLong(pop)));
            }
        }
        return multiply.toString();
    }


    public static void main(String[] args) {
        System.out.println(toNumAmount("33.31 元"));
    }

}

二、带数字的金额,且有单位的币种转换
形如:贰佰万圆整、2000万元整、人民币50.0000万元整、美元150.0000万
需要识别为:

贰佰万圆整 ---------> 2000000人民币
2000万元整 ---------> 20000000人民币
人民币50.0000万元整 ---------> 500000人民币
美元150.0000---------> 1500000美元

代码为:

package test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @describe:
 * @author: 容若
 * @created: 2024-03-07 10:44
 */
public class StrMatch {
    public static void main(String[] args) {
        String str = "贰佰万圆整"; // 贰佰万圆整  2000万元整  人民币50.0000万元整 美元150.0000万

        System.out.println(strMatch(str) + getCurrency(str));
    }
    private static String strMatch(String str) {
        long number = getNumber(str);
        if (number > 0) {
            return String.valueOf(number);
        }
        String[] result = str.split("[元圆]");
        ChineseToArabic c = new ChineseToArabic();
        return String.valueOf(c.chineseNumToArabicNum(result[0]));
    }

    /**
     * 获取币种
     * @param str 注册资本字符串
     * @return
     */
    public static String getCurrency(String str) {
        boolean containsCNY = str.contains("人民币") || str.contains("RMB");
        boolean containsUSD = str.contains("美元") || str.contains("USD");
        boolean containsPound = str.contains("英镑");
        boolean containsHKD = str.contains("港币");
        boolean containsEuro = str.contains("欧元");
        if (containsCNY) {
            return "人民币";
        }
        if (containsUSD) {
            return "美元";
        }
        if (containsPound) {
            return "英镑";
        }
        if (containsHKD) {
            return "港币";
        }
        if (containsEuro) {
            return "欧元";
        }
        return "人民币";
    }

    /**
     * 带数字的金额直接转成阿拉伯数字 2000万元整 ---》 20000000人民币
     * @param str
     * @return
     */
    public static long getNumber(String str) {
        long intMillionValue = 0;
        Pattern pattern = Pattern.compile("(\\d+(\\.\\d+)?)万");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            String numberStr = matcher.group(1); // 提取出数字和小数点部分
            double number = Double.parseDouble(numberStr); // 将字符串转换为double
            double millionValue = number * 10000; // 将"万"单位转换为实际数值
            intMillionValue = Math.round(millionValue); // 四舍五入转换为整数
        }
        return intMillionValue;
    }
}

这个业务主要用于统一注册资本、资产等正式文本的标识,其他需求可酌情修改。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

容若只如初见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值