【Java 开发案例】大写金额转小写金额

223 阅读3分钟

一、完整代码

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

/**
 * 大写金额转小写
 */
public class MoneyUtil {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("贰拾叁元整", "贰拾叁万元整", "壹仟万元", "九千亿", "八十元伍角叁分捌厘", "四万万元");
        for (String o : list) {
            System.out.println(o + ":\t" + rmbBigPlusToSmall(o));
        }
    }

    /**
     * 中文中简写的汉字金额 经常使用
     */
    private static String[] NUMBER_CN = new String[]{"一", "二", "三", "四", "五", "六", "七", "八", "九", "两", "廿", "卅", "○"};
    /**
     * 中文中繁写的汉字金额 经常使用
     */
    private static String[] NUMBER_TRADITIONAL = new String[]{"壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "俩", "廿", "卅", "零"};
    /**
     * 与汉字相应的转化的数字
     */
    private static Long[] NUMBER = new Long[]{1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 2L, 2L, 3L, 0L};

    /**
     * 倍数关键词 简写 注意:一定要由大到小
     */
    private static String[] UNIT_CN = new String[]{"亿", "万", "千", "百", "十"};
    /**
     * 倍数关键词 繁写
     */
    private static String[] UNIT_TRADITIONAL = new String[]{"億", "萬", "仟", "佰", "拾"};

    /**
     * 与倍数关键词对应的倍数
     */
    private static Long[] toMult = new Long[]{100000000L, 10000L, 1000L, 100L, 10L};

    /**
     * 大写金额转化为小写数字,只处理到元,不带有单位
     *
     * @param money 大写的金额,不带有单位 例如:1.二十一万 2.六五四三 3 贰拾
     * @return 转化后的数字字符结果
     */
    public static String rmbBigToSmall(String money) {
        if (money == null || "".equals(money.trim().replaceAll(" ", ""))) {
            return "0";
        }
        //处理大写金额的元、整
        money = money.replace("元", "").replace("整", "");
        long number = 0L;
        //遍历倍数的中文词遍历的时候一定要注意 选取的倍数词为最后一个倍数词,此次遍历为第一次遍历
        for (int i = 0; i < UNIT_CN.length; i++) {
            int index = money.lastIndexOf(UNIT_CN[i]) == -1 ? money.lastIndexOf(UNIT_TRADITIONAL[i]) : money.lastIndexOf(UNIT_CN[i]);
            if (index >= 0) {
                String storeMult = money.substring(0, index);
                money = money.substring(index + 1);
                //对于 十九万 这样的特殊的十的情况进行特殊处理
                if (storeMult.length() <= 0 && toMult[i].intValue() == 10) {
                    number = number + toMult[i];
                } else {
                    number = number + (toMult[i] * getPrexNum(storeMult));
                }
            }
        }
        // 个位数的处理
        number = number + getNumByBig(money);
        return Long.toString(number);
    }

    /**
     * 金额大写转小写,不带有单位 (支持精确到角分毫厘的四位有效数字)
     * <pre>
     *     最大单位为 亿
     *     最小单位为 厘
     * </pre>
     *
     * @param moneyStr 大写金额字符串
     * @return 小写float类型数据
     */
    public static String rmbBigPlusToSmall(String moneyStr) {
        BigDecimal s = new BigDecimal(rmbBigToSmall(moneyStr));
        BigDecimal min = new BigDecimal(String.valueOf(getMinoNum(moneyStr)));
        return s.add(min).toString();
    }

    /**
     * 辅助类,第二次循环
     * 此循环一般处理的都是倍数前面的数字,例如十九万,在这里就处理十九
     *
     * @param storeMult 倍数前面的前缀词
     * @return
     */
    private static Long getPrexNum(String storeMult) {
        long result = 0L;
        for (int i = 0; i < UNIT_CN.length; i++) {
            int index = storeMult.lastIndexOf(UNIT_CN[i]) == -1 ? storeMult.lastIndexOf(UNIT_TRADITIONAL[i]) : storeMult.lastIndexOf(UNIT_CN[i]);
            if (index >= 0) {
                String storeMult2 = storeMult.substring(0, index);
                storeMult = storeMult.substring(index + 1);
                if (storeMult2.length() <= 0 && toMult[i].intValue() == 10) {
                    result = result + toMult[i];
                } else {
                    result += getNumByBig(storeMult2) * toMult[i];
                }
            }
        }
        if (storeMult != null && storeMult.length() > 0) {
            result = result + getNumByBig(storeMult);
        }
        return result;
    }

    /**
     * 辅助类,大写的中文数字 转化为小写的阿拉伯数字
     *
     * @param big
     * @return
     */
    private static Long getNumByBig(String big) {
        long result = 0L;
        for (int j = 0; j < NUMBER_CN.length; j++) {
            big = big.replaceAll(NUMBER_CN[j], NUMBER[j].toString());
            big = big.replaceAll(NUMBER_TRADITIONAL[j], NUMBER[j].toString());
        }
        try {
            result = Long.parseLong(big);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 处理小时后面的四位数( *.0213 角-分-毫-厘)
     *
     * @param cnNum 中文大写金额
     * @return 小数金额
     */
    private static float getMinoNum(String cnNum) {
        List<String> list = Arrays.asList("角", "分", "毫", "厘");
        char[] cArr = cnNum.toCharArray();
        float result = 0F;
        for (int i = 0; i < cArr.length; i++) {
            for (String unit : list) {
                if (String.valueOf(cArr[i]).equals(unit)) {
                    result += getNumByBig(String.valueOf(cArr[i - 1])) * switchNum(unit);
                }
            }
        }
        return result;
    }

    private static float switchNum(String unit) {
        switch (unit) {
            case "角":
                return 0.1F;
            case "分":
                return 0.01F;
            case "毫":
                return 0.001F;
            case "厘":
                return 0.0001F;
            default:
                return 1F;
        }
    }
}

二、结果展示

注意:结果最多是四位有效数字。

贰拾叁元整:	23.0
贰拾叁万元整:	230000.0
壹仟万元:	10000000.0
九千亿:	900000000000.0
八十元伍角叁分捌厘:	80.5308
四万万元:	400000000.0