package com.chenwc.tools; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; /** * 中文大写数字转换为阿拉伯数字 * * @author chenwc * @date 2023/3/2 22:55 */ public class ChineseToArabicNumerals { /** * 汉字数字到阿拉伯数字的映射关系 */ private static final HashMap<Character, Long> numMap = new HashMap<Character, Long>() {{ put('零', 0L); put('一', 1L); put('二', 2L); put('三', 3L); put('四', 4L); put('五', 5L); put('六', 6L); put('七', 7L); put('八', 8L); put('九', 9L); put('十', 10L); put('廿', 20L); put('卅', 30L); put('百', 100L); put('千', 1000L); put('万', 10_000L); put('亿', 100_000_000L); put('壹', 1L); put('贰', 2L); put('叁', 3L); put('肆', 4L); put('伍', 5L); put('陆', 6L); put('柒', 7L); put('捌', 8L); put('玖', 9L); put('拾', 10L); put('佰', 100L); put('仟', 1000L); }}; /** * 获取映射关系的键 */ private final static List<Character> keyList = new ArrayList<Character>(){{ addAll(numMap.keySet()); }}; /** * 中文大写数字转换为阿拉伯数字,示例:壹佰零壹--->101;廿二--->22;二十万五百亿三千零八万一千零卅五--->20050030081035 * * @param num 中文大写数字 * @return 阿拉伯数字 */ public static long transChineseNum(String num) { if (num == null || num.length() == 0) return 0L; //特殊情况 :例如 二零一二 一九八七 这种类似年份的数字 long result; if ((result = transChineseNumYears(num)) != -1) { return result; } result = 0; //使用栈 Stack<Long> s = new Stack<>(); for (int i = 0; i < num.length(); i++) { if (numMap.containsKey(num.charAt(i))) { long curNum = numMap.get(num.charAt(i)); //若栈为空或者当前字符所代表的的数字小于栈顶数字,直接入栈 if (s.isEmpty() || curNum < s.peek()) { s.push(curNum); } else { int temp = 0; // 当前字符所代表的的数字小于栈顶数字,依次弹出栈顶元素, // 直至栈顶数字大于当前数字,将弹出的数字相加后乘与当前数字,再将结果入栈 while (!s.isEmpty() && s.peek() < curNum) { temp += s.pop(); } temp = (temp == 0 ? 1 : temp); s.push(temp * curNum); } } else { throw new RuntimeException("字符【" + num.charAt(i) + "】不在值转换范围" + keyList + "内!"); } } //转换结束,把栈内所有数值相加得出最后结果 while (!s.isEmpty()) { result += s.pop(); } return result; } /** * 中文大写数字转换为阿拉伯数字,特殊情况转换:例如 二零一二,一九八七 这种类似年份的数字 * * @param num 中文大写数字 * @return 阿拉伯数字 */ private static long transChineseNumYears(String num) { for (char c : num.toCharArray()) { if (numMap.containsKey(c)) { if (numMap.get(c) >= 10L) { return -1; } } else { throw new RuntimeException("字符【" + c + "】不在值转换范围" + keyList + "内!"); } } long result = 0; long unit = 1; //把字符串逐个字符进行进位相乘相加 for (int i = num.length() - 1; i >= 0; i--) { result += numMap.get(num.charAt(i)) * unit; unit *= 10; } return result; } }