From 10503d632faf836326e2c389a5dec0bcd2bc944c Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 22 Apr 2021 03:23:25 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9Efix=20toNumber=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../core/convert/NumberChineseFormatter.java | 203 +++++++++++------- .../convert/NumberChineseFormatterTest.java | 18 +- 3 files changed, 144 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf36de7fe..ad071c948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.6.4 (2021-04-20) +# 5.6.4 (2021-04-22) ### 新特性 * 【core 】 DatePattern补充DateTimeFormatter(pr#308@Gitee) @@ -15,6 +15,7 @@ ### Bug修复 * 【db 】 修复SQL分页时未使用别名导致的错误,同时count时取消order by子句(issue#I3IJ8X@Gitee) * 【extra 】 修复Sftp.reconnectIfTimeout方法判断错误(issue#1524@Github) +* 【core 】 修复NumberChineseFormatter转数字问题(issue#I3IS3S@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java index 98b5584dd..8a92735be 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java @@ -17,32 +17,25 @@ import cn.hutool.core.util.StrUtil; public class NumberChineseFormatter { /** - * 简体中文形式 + * 中文形式,奇数位置是简体,偶数位置是记账繁体,0共用
+ * 使用混合数组提高效率和数组复用 **/ - private static final char[] SIMPLE_DIGITS = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'}; - /** - * 繁体中文形式 - **/ - private static final char[] TRADITIONAL_DIGITS = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'}; - - /** - * 简体中文单位 - **/ - private static final String[] SIMPLE_UNITS = {"", "十", "百", "千"}; - /** - * 繁体中文单位 - **/ - private static final String[] TRADITIONAL_UNITS = {"", "拾", "佰", "仟"}; + private static final char[] DIGITS = {'零', '一', '壹', '二', '贰', '三', '叁', '四', '肆', '五', '伍', + '六', '陆', '七', '柒', '八', '捌', '九', '玖'}; /** * 汉字转阿拉伯数字的 */ - private static final ChineseNameValue[] CHINESE_NAME_VALUE = { - new ChineseNameValue("十", 10, false), - new ChineseNameValue("百", 100, false), - new ChineseNameValue("千", 1000, false), - new ChineseNameValue("万", 10000, true), - new ChineseNameValue("亿", 100000000, true), + private static final ChineseUnit[] CHINESE_NAME_VALUE = { + new ChineseUnit(' ', 1, false), + new ChineseUnit('十', 10, false), + new ChineseUnit('拾', 10, false), + new ChineseUnit('百', 100, false), + new ChineseUnit('佰', 100, false), + new ChineseUnit('千', 1000, false), + new ChineseUnit('仟', 1000, false), + new ChineseUnit('万', 10000, true), + new ChineseUnit('亿', 100000000, true), }; @@ -66,8 +59,6 @@ public class NumberChineseFormatter { * @return 中文 */ public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) { - final char[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS; - if (amount > 99999999999999.99 || amount < -99999999999999.99) { throw new IllegalArgumentException("Number support only: (-99999999999999.99 ~ 99999999999999.99)!"); } @@ -98,7 +89,7 @@ public class NumberChineseFormatter { StringBuilder chineseStr = new StringBuilder(); for (int i = 0; i < numParts; i++) { - String partChinese = toChinese(parts[i], isUseTraditional); + final String partChinese = toChinese(parts[i], isUseTraditional); if (i % 2 == 0) { beforeWanIsZero = StrUtil.isEmpty(partChinese); } @@ -127,7 +118,7 @@ public class NumberChineseFormatter { // 整数部分为 0, 则表达为"零" if (StrUtil.EMPTY.equals(chineseStr.toString())) { - chineseStr = new StringBuilder(String.valueOf(numArray[0])); + chineseStr = new StringBuilder(String.valueOf(DIGITS[0])); } //负数 if (negative) { // 整数部分不为 0 @@ -137,12 +128,12 @@ public class NumberChineseFormatter { // 小数部分 if (numFen != 0 || numJiao != 0) { if (numFen == 0) { - chineseStr.append(isMoneyMode ? "元" : "点").append(numArray[numJiao]).append(isMoneyMode ? "角" : ""); + chineseStr.append(isMoneyMode ? "元" : "点").append(numberToChinese(numJiao, isUseTraditional)).append(isMoneyMode ? "角" : ""); } else { // “分”数不为 0 if (numJiao == 0) { - chineseStr.append(isMoneyMode ? "元零" : "点零").append(numArray[numFen]).append(isMoneyMode ? "分" : ""); + chineseStr.append(isMoneyMode ? "元零" : "点零").append(numberToChinese(numFen, isUseTraditional)).append(isMoneyMode ? "分" : ""); } else { - chineseStr.append(isMoneyMode ? "元" : "点").append(numArray[numJiao]).append(isMoneyMode ? "角" : "").append(numArray[numFen]).append(isMoneyMode ? "分" : ""); + chineseStr.append(isMoneyMode ? "元" : "点").append(numberToChinese(numJiao, isUseTraditional)).append(isMoneyMode ? "角" : "").append(numberToChinese(numFen, isUseTraditional)).append(isMoneyMode ? "分" : ""); } } } else if (isMoneyMode) { @@ -163,12 +154,10 @@ public class NumberChineseFormatter { * @since 5.3.9 */ public static String numberCharToChinese(char c, boolean isUseTraditional) { - char[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS; - int index = c - 48; - if (index < 0 || index >= numArray.length) { + if (c < '0' || c > '9') { return String.valueOf(c); } - return String.valueOf(numArray[index]); + return String.valueOf(numberToChinese(c - '0', isUseTraditional)); } /** @@ -179,9 +168,6 @@ public class NumberChineseFormatter { * @return 转换后的汉字 */ private static String toChinese(int amountPart, boolean isUseTraditional) { - final char[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS; - String[] units = isUseTraditional ? TRADITIONAL_UNITS : SIMPLE_UNITS; - int temp = amountPart; StringBuilder chineseStr = new StringBuilder(); @@ -195,7 +181,7 @@ public class NumberChineseFormatter { } lastIsZero = true; } else { // 取到的数字不是 0 - chineseStr.insert(0, numArray[digit] + units[i]); + chineseStr.insert(0, numberToChinese(digit, isUseTraditional) + getUnitName(i, isUseTraditional)); lastIsZero = false; } temp = temp / 10; @@ -204,7 +190,7 @@ public class NumberChineseFormatter { } /** - * 把中文转换为数字 如 二百二 220
+ * 把中文转换为数字 如 二百二十 220
* 见:https://www.d5.nz/read/sfdlq/text-part0000_split_030.html *