由于业务需要将中文的数字转换成阿拉伯数字,写个工具类来实现。
【思路】
中文数字一般包含“零一二三四五六七八九”这样的“数”,以及“个、十、百、千、万、亿”这样的“单位”。
我们可以采用分而治之的方法将一个中文数字通过单位拆分成两个更小的数字,直到拆分到只包含“数”。按“单位”拆分后,前面的部分乘以单位对应的阿拉伯数字倍数,加上后面部分的倍数即可得到最后的阿拉伯数字值。
例如,“一百二十三”可以按如下方式拆分:
拆分后,1乘以100、二乘以10,三乘以1,即可得到最后的结果:123。
程序上还需要解决其他问题
传入的中文情况比较复杂,拆分后需要处理各种情况,如:“一”、“十”、“一十”、“十一”、“一十二”等等;
需要处理“零”的问题,如:“一百零二”与“一百二”结果不同。
【代码】
代码采用递归实现:
import top.haohaoge.utils.CommonValidate; // 用于验证字符串是否为空,包括""和null
import exception.ServerException;
import java.util.HashMap;
import java.util.Map;
public class ChineseNumUtils {
private static final Map<String, Long> NUM_STRS = new HashMap<>();
private static final Map<String, Long> UNIT_STRS = new HashMap<>();
private static final String[] UNITS = new String[]{"亿", "万", "千", "佰", "十"};
static {
NUM_STRS.put("零", 0L);
NUM_STRS.put("一", 1L);
NUM_STRS.put("二", 2L);
NUM_STRS.put("三", 3L);
NUM_STRS.put("四", 4L);
NUM_STRS.put("五", 5L);
NUM_STRS.put("六", 6L);
NUM_STRS.put("七", 7L);
NUM_STRS.put("八", 8L);
NUM_STRS.put("九", 9L);
UNIT_STRS.put("个", 1L);
UNIT_STRS.put("十", 10L);
UNIT_STRS.put("佰", 100L);
UNIT_STRS.put("千", 1000L);
UNIT_STRS.put("万", 10000L);
UNIT_STRS.put("亿", 100000000L);
}
/**
* @description 字符串中的数字转int。里面用的string2Long(strNum)转换,调用注意传入的字符串数字不要越界
* @author zh
* @created 2022/1/25
* @param strNum
* @return {@link java.lang.Integer}
* @throws
*/
public static Integer string2Int(String strNum) {
return string2Long(strNum).intValue();
}
public static Long string2Long(String strNum) {
Long num;
// 尝试按数字转换。比如传来的是"10",直接转换成10
num = getNumFromString(strNum);
if (num == null) {
// getNumFromString()只能处理数字,有中文则调用下面这个方法
// 按数字转换失败,按中文数字转换。比如传来的是"十",转换成10
num = chineseNumber2Long(strNum);
}
return num;
}
public static Long chineseNumber2Long(String chineseNumber) {
// 如果还有需要处理的字符,在入口这里处理
chineseNumber = chineseNumber.replaceAll("百", "佰");
return chineseNumber2Long(chineseNumber, 0);
}
public static Long chineseNumber2Long(String chineseNumber, int pos) {
String unit;
if (pos > UNITS.length) {
throw new ServerException("数字转换失败");
} if (pos == UNITS.length) {
unit = "个";
} else {
unit = UNITS[pos];
}
Long unitValue = UNIT_STRS.get(unit);
unitValue = unitValue == null ? 1 : unitValue;
String[] subNumberStr = chineseNumber.split(unit);
Long result;
Long intNum;
Long decNum;
if (subNumberStr.length == 0) {
// 只存在这个单位
intNum = 1L;
decNum = 0L;
} else if (subNumberStr.length == 1) {
if (chineseNumber.indexOf(unit) == -1) {
// 不存在unit
intNum = 0L;
if (subNumberStr[0].length() == 1) {
if (NUM_STRS.get(subNumberStr[0]) == null) {
decNum = chineseNumber2Long(subNumberStr[0], pos + 1);
} else {
decNum = NUM_STRS.get(subNumberStr[0]);
}
} else {
decNum = chineseNumber2Long(subNumberStr[0], pos + 1);
}
} else {
// 存在unit
intNum = chineseNumber2Long(subNumberStr[0], pos + 1);
decNum = 0L;
}
} else if (subNumberStr.length == 2) {
if (CommonValidate.isEmpty(subNumberStr[0])) {
intNum = 1L;
} else {
intNum = CommonValidate.isEmpty(subNumberStr[0]) ? 1 : chineseNumber2Long(subNumberStr[0], pos + 1);
}
if (CommonValidate.isEmpty(subNumberStr[1])) {
decNum = 0L;
} else {
if (subNumberStr[1].indexOf("零") == 0) {
// 包含 零,如 三百零一
subNumberStr[1] = subNumberStr[1].substring(1);
} else {
// 不包含 零,如 三百一
if (pos < UNITS.length - 1) {
subNumberStr[1] = subNumberStr[1] + UNITS[pos + 1];
}
}
decNum = chineseNumber2Long(subNumberStr[1], pos + 1);
}
} else {
throw new RuntimeException("error");
}
result = intNum * unitValue + decNum;
return result;
}
public static Long getNumFromString(String str) {
if (str == null || "".equals(str)) {
return null;
}
str = str.trim();
String result = "";
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) >= 48 && str.charAt(i) <= 57) {
result += str.charAt(i);
}
}
if ("".equals(result)) {
return null;
}
return Long.valueOf(result);
}
// 测试
public static void main(String[] args) {
testNum();
}
private static void testNum() {
testPrintChineseNum("零", 0L);
testPrintChineseNum("一", 1L);
testPrintChineseNum("十", 10L);
testPrintChineseNum("百", 100L);
testPrintChineseNum("一十", 10L);
testPrintChineseNum("十一", 11L);
testPrintChineseNum("一十二", 12L);
testPrintChineseNum("一佰", 100L);
testPrintChineseNum("百零一", 101L);
testPrintChineseNum("一佰零一", 101L);
testPrintChineseNum("一佰一", 110L);
testPrintChineseNum("佰一", 110L);
testPrintChineseNum("佰一十", 110L);
testPrintChineseNum("一万", 10000L);
testPrintChineseNum("一万二", 12000L);
testPrintChineseNum("一万二千", 12000L);
testPrintChineseNum("一万二千三百", 12300L);
testPrintChineseNum("一万零三百", 10300L);
testPrintChineseNum("一万零四十", 10040L);
testPrintChineseNum("一万零五", 10005L);
testPrintChineseNum("一亿九千八佰万", 198000000L);
testPrintChineseNum("一亿九千八佰七十六万五千四佰三十二", 198765432L);
testPrintChineseNum("九千八佰七十六万五千四佰三十二亿九千八佰七十六万五千四佰三十二", 9876543298765432L);
testPrintChineseNum("十万亿", 10000000000000L);
testPrintChineseNum("九十万亿", 90000000000000L);
testPrintChineseNum("九十万亿零一", 90000000000001L);
}
private static void testPrintChineseNum(String str, Long num) {
System.out.print(str);
System.out.print("====");
Long strValue = string2Long(str);
System.out.print(strValue);
if (!num.equals(strValue)) {
System.out.println("=========error");
}
System.out.println();
}
}