mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -20,7 +20,8 @@ import org.dromara.hutool.core.convert.impl.EnumConverter;
|
||||
import org.dromara.hutool.core.convert.impl.MapConverter;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.math.ChineseNumberFormatter;
|
||||
import org.dromara.hutool.core.math.NumberWordFormatter;
|
||||
import org.dromara.hutool.core.math.ChineseNumberParser;
|
||||
import org.dromara.hutool.core.math.EnglishNumberFormatter;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.text.UnicodeUtil;
|
||||
@@ -1003,7 +1004,7 @@ public class Convert {
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public static String numberToWord(final Number number) {
|
||||
return NumberWordFormatter.format(number);
|
||||
return EnglishNumberFormatter.format(number);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1018,7 +1019,7 @@ public class Convert {
|
||||
* @since 5.5.9
|
||||
*/
|
||||
public static String numberToSimple(final Number number) {
|
||||
return NumberWordFormatter.formatSimple(number.longValue());
|
||||
return EnglishNumberFormatter.formatSimple(number.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1047,7 +1048,7 @@ public class Convert {
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static int chineseToNumber(final String number){
|
||||
return ChineseNumberFormatter.parseFromChinese(number);
|
||||
return ChineseNumberParser.parseFromChineseNumber(number);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1078,7 +1079,7 @@ public class Convert {
|
||||
* @since 5.8.5
|
||||
*/
|
||||
public static BigDecimal chineseMoneyToNumber(final String chineseMoneyAmount){
|
||||
return ChineseNumberFormatter.parseFromChineseMoney(chineseMoneyAmount);
|
||||
return ChineseNumberParser.parseFromChineseMoney(chineseMoneyAmount);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- 数字转换
|
||||
|
@@ -14,10 +14,6 @@ package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 数字转中文类<br>
|
||||
@@ -68,155 +64,6 @@ public class ChineseNumberFormatter {
|
||||
return numberToChinese(c - '0', isUseTraditional);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把中文转换为数字 如 二百二十 220<br>
|
||||
* <ul>
|
||||
* <li>一百一十二 -》 112</li>
|
||||
* <li>一千零一十二 -》 1012</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param chinese 中文字符
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static int parseFromChinese(final String chinese) {
|
||||
final int length = chinese.length();
|
||||
int result = 0;
|
||||
|
||||
// 节总和
|
||||
int section = 0;
|
||||
int number = 0;
|
||||
ChineseUnit unit = null;
|
||||
char c;
|
||||
for (int i = 0; i < length; i++) {
|
||||
c = chinese.charAt(i);
|
||||
final int num = parseFromChinese(c);
|
||||
if (num >= 0) {
|
||||
if (num == 0) {
|
||||
// 遇到零时节结束,权位失效,比如两万二零一十
|
||||
if (number > 0 && null != unit) {
|
||||
section += number * (unit.value / 10);
|
||||
}
|
||||
unit = null;
|
||||
} else if (number > 0) {
|
||||
// 多个数字同时出现,报错
|
||||
throw new IllegalArgumentException(StrUtil.format("Bad number '{}{}' at: {}", chinese.charAt(i - 1), c, i));
|
||||
}
|
||||
// 普通数字
|
||||
number = num;
|
||||
} else {
|
||||
unit = chineseToUnit(c);
|
||||
if (null == unit) {
|
||||
// 出现非法字符
|
||||
throw new IllegalArgumentException(StrUtil.format("Unknown unit '{}' at: {}", c, i));
|
||||
}
|
||||
|
||||
//单位
|
||||
if (unit.secUnit) {
|
||||
// 节单位,按照节求和
|
||||
section = (section + number) * unit.value;
|
||||
result += section;
|
||||
section = 0;
|
||||
} else {
|
||||
// 非节单位,和单位前的单数字组合为值
|
||||
int unitNumber = number;
|
||||
if (0 == number && 0 == i) {
|
||||
// issue#1726,对于单位开头的数组,默认赋予1
|
||||
// 十二 -> 一十二
|
||||
// 百二 -> 一百二
|
||||
unitNumber = 1;
|
||||
}
|
||||
section += (unitNumber * unit.value);
|
||||
}
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (number > 0 && null != unit) {
|
||||
number = number * (unit.value / 10);
|
||||
}
|
||||
|
||||
return result + section + number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中文大写数字金额转换为数字,返回结果以元为单位的BigDecimal类型数字<br>
|
||||
* 如:
|
||||
* “陆万柒仟伍佰伍拾陆元叁角贰分”返回“67556.32”
|
||||
* “叁角贰分”返回“0.32”
|
||||
*
|
||||
* @param chineseMoneyAmount 中文大写数字金额
|
||||
* @return 返回结果以元为单位的BigDecimal类型数字
|
||||
*/
|
||||
public static BigDecimal parseFromChineseMoney(final String chineseMoneyAmount) {
|
||||
if (StrUtil.isBlank(chineseMoneyAmount)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int yi = chineseMoneyAmount.indexOf("元");
|
||||
if (yi == -1) {
|
||||
yi = chineseMoneyAmount.indexOf("圆");
|
||||
}
|
||||
final int ji = chineseMoneyAmount.indexOf("角");
|
||||
final int fi = chineseMoneyAmount.indexOf("分");
|
||||
|
||||
// 先找到单位为元的数字
|
||||
String yStr = null;
|
||||
if (yi > 0) {
|
||||
yStr = chineseMoneyAmount.substring(0, yi);
|
||||
}
|
||||
|
||||
// 再找到单位为角的数字
|
||||
String jStr = null;
|
||||
if (ji > 0) {
|
||||
if (yi >= 0) {
|
||||
//前面有元,角肯定要在元后面
|
||||
if (ji > yi) {
|
||||
jStr = chineseMoneyAmount.substring(yi + 1, ji);
|
||||
}
|
||||
} else {
|
||||
//没有元,只有角
|
||||
jStr = chineseMoneyAmount.substring(0, ji);
|
||||
}
|
||||
}
|
||||
|
||||
// 再找到单位为分的数字
|
||||
String fStr = null;
|
||||
if (fi > 0) {
|
||||
if (ji >= 0) {
|
||||
//有角,分肯定在角后面
|
||||
if (fi > ji) {
|
||||
fStr = chineseMoneyAmount.substring(ji + 1, fi);
|
||||
}
|
||||
} else if (yi > 0) {
|
||||
//没有角,有元,那就坐元后面找
|
||||
if (fi > yi) {
|
||||
fStr = chineseMoneyAmount.substring(yi + 1, fi);
|
||||
}
|
||||
} else {
|
||||
//没有元、角,只有分
|
||||
fStr = chineseMoneyAmount.substring(0, fi);
|
||||
}
|
||||
}
|
||||
|
||||
//元、角、分
|
||||
int y = 0, j = 0, f = 0;
|
||||
if (StrUtil.isNotBlank(yStr)) {
|
||||
y = ChineseNumberFormatter.parseFromChinese(yStr);
|
||||
}
|
||||
if (StrUtil.isNotBlank(jStr)) {
|
||||
j = ChineseNumberFormatter.parseFromChinese(jStr);
|
||||
}
|
||||
if (StrUtil.isNotBlank(fStr)) {
|
||||
f = ChineseNumberFormatter.parseFromChinese(fStr);
|
||||
}
|
||||
|
||||
BigDecimal amount = new BigDecimal(y);
|
||||
amount = amount.add(BigDecimal.valueOf(j).divide(BigDecimal.TEN, 2, RoundingMode.HALF_UP));
|
||||
amount = amount.add(BigDecimal.valueOf(f).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 NumberChineseFormatter 默认对象
|
||||
*
|
||||
@@ -230,24 +77,9 @@ public class ChineseNumberFormatter {
|
||||
* 中文形式,奇数位置是简体,偶数位置是记账繁体,0共用<br>
|
||||
* 使用混合数组提高效率和数组复用
|
||||
**/
|
||||
private static final char[] DIGITS = {'零', '一', '壹', '二', '贰', '三', '叁', '四', '肆', '五', '伍',
|
||||
static final char[] DIGITS = {'零', '一', '壹', '二', '贰', '三', '叁', '四', '肆', '五', '伍',
|
||||
'六', '陆', '七', '柒', '八', '捌', '九', '玖'};
|
||||
|
||||
/**
|
||||
* 汉字转阿拉伯数字的
|
||||
*/
|
||||
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('万', 1_0000, true),
|
||||
new ChineseUnit('亿', 1_0000_0000, true),
|
||||
};
|
||||
|
||||
// region ----- 配置项
|
||||
private boolean useTraditional;
|
||||
private boolean moneyMode;
|
||||
@@ -514,7 +346,7 @@ public class ChineseNumberFormatter {
|
||||
lastIsZero = true;
|
||||
} else { // 取到的数字不是 0
|
||||
final boolean isUseTraditional = this.useTraditional;
|
||||
chineseStr.insert(0, numberToChinese(digit, isUseTraditional) + getUnitName(i, isUseTraditional));
|
||||
chineseStr.insert(0, numberToChinese(digit, isUseTraditional) + ChineseNumberParser.getUnitName(i, isUseTraditional));
|
||||
lastIsZero = false;
|
||||
}
|
||||
temp = temp / 10;
|
||||
@@ -522,40 +354,6 @@ public class ChineseNumberFormatter {
|
||||
return chineseStr.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找对应的权对象
|
||||
*
|
||||
* @param chinese 中文权位名
|
||||
* @return 权对象
|
||||
*/
|
||||
private static ChineseUnit chineseToUnit(final char chinese) {
|
||||
for (final ChineseUnit chineseNameValue : CHINESE_NAME_VALUE) {
|
||||
if (chineseNameValue.name == chinese) {
|
||||
return chineseNameValue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将汉字单个数字转换为int类型数字
|
||||
*
|
||||
* @param chinese 汉字数字,支持简体和繁体
|
||||
* @return 数字,-1表示未找到
|
||||
* @since 5.6.4
|
||||
*/
|
||||
private static int parseFromChinese(char chinese) {
|
||||
if ('两' == chinese) {
|
||||
// 口语纠正
|
||||
chinese = '二';
|
||||
}
|
||||
final int i = ArrayUtil.indexOf(DIGITS, chinese);
|
||||
if (i > 0) {
|
||||
return (i + 1) / 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个数字转汉字
|
||||
*
|
||||
@@ -570,20 +368,6 @@ public class ChineseNumberFormatter {
|
||||
return DIGITS[number * 2 - (isUseTraditional ? 0 : 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应级别的单位
|
||||
*
|
||||
* @param index 级别,0表示各位,1表示十位,2表示百位,以此类推
|
||||
* @param isUseTraditional 是否使用繁体
|
||||
* @return 单位
|
||||
*/
|
||||
private static String getUnitName(final int index, final boolean isUseTraditional) {
|
||||
if (0 == index) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
return String.valueOf(CHINESE_NAME_VALUE[index * 2 - (isUseTraditional ? 0 : 1)].name);
|
||||
}
|
||||
|
||||
private static void addPreZero(final StringBuilder chineseStr) {
|
||||
if (StrUtil.isEmpty(chineseStr)) {
|
||||
return;
|
||||
@@ -592,39 +376,4 @@ public class ChineseNumberFormatter {
|
||||
chineseStr.insert(0, '零');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 权位
|
||||
*
|
||||
* @author totalo
|
||||
* @since 5.6.0
|
||||
*/
|
||||
private static class ChineseUnit {
|
||||
/**
|
||||
* 中文权名称
|
||||
*/
|
||||
private final char name;
|
||||
/**
|
||||
* 10的倍数值
|
||||
*/
|
||||
private final int value;
|
||||
/**
|
||||
* 是否为节权位,它不是与之相邻的数字的倍数,而是整个小节的倍数。<br>
|
||||
* 例如二十三万,万是节权位,与三无关,而和二十三关联
|
||||
*/
|
||||
private final boolean secUnit;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 名称
|
||||
* @param value 值,即10的倍数
|
||||
* @param secUnit 是否为节权位
|
||||
*/
|
||||
public ChineseUnit(final char name, final int value, final boolean secUnit) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.secUnit = secUnit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2024. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 中文数字或金额解析类
|
||||
*
|
||||
* @author fanqun, looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class ChineseNumberParser {
|
||||
|
||||
/**
|
||||
* 汉字转阿拉伯数字的
|
||||
*/
|
||||
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('万', 1_0000, true),
|
||||
new ChineseUnit('亿', 1_0000_0000, true),
|
||||
};
|
||||
|
||||
/**
|
||||
* 把中文转换为数字 如 二百二十 -》 220<br>
|
||||
* <ul>
|
||||
* <li>一百一十二 -》 112</li>
|
||||
* <li>一千零一十二 -》 1012</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param chinese 中文字符
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static Number parseFromChinese(final String chinese) {
|
||||
if(StrUtil.containsAny(chinese, '元', '圆', '角', '分')){
|
||||
return parseFromChineseMoney(chinese);
|
||||
}
|
||||
|
||||
return parseFromChineseNumber(chinese);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把中文转换为数字 如 二百二十 220<br>
|
||||
* <ul>
|
||||
* <li>一百一十二 -》 112</li>
|
||||
* <li>一千零一十二 -》 1012</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param chinese 中文字符
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static int parseFromChineseNumber(final String chinese) {
|
||||
final int length = chinese.length();
|
||||
int result = 0;
|
||||
|
||||
// 节总和
|
||||
int section = 0;
|
||||
int number = 0;
|
||||
ChineseUnit unit = null;
|
||||
char c;
|
||||
for (int i = 0; i < length; i++) {
|
||||
c = chinese.charAt(i);
|
||||
final int num = chineseToNumber(c);
|
||||
if (num >= 0) {
|
||||
if (num == 0) {
|
||||
// 遇到零时节结束,权位失效,比如两万二零一十
|
||||
if (number > 0 && null != unit) {
|
||||
section += number * (unit.value / 10);
|
||||
}
|
||||
unit = null;
|
||||
} else if (number > 0) {
|
||||
// 多个数字同时出现,报错
|
||||
throw new IllegalArgumentException(StrUtil.format("Bad number '{}{}' at: {}", chinese.charAt(i - 1), c, i));
|
||||
}
|
||||
// 普通数字
|
||||
number = num;
|
||||
} else {
|
||||
unit = chineseToUnit(c);
|
||||
if (null == unit) {
|
||||
// 出现非法字符
|
||||
throw new IllegalArgumentException(StrUtil.format("Unknown unit '{}' at: {}", c, i));
|
||||
}
|
||||
|
||||
//单位
|
||||
if (unit.secUnit) {
|
||||
// 节单位,按照节求和
|
||||
section = (section + number) * unit.value;
|
||||
result += section;
|
||||
section = 0;
|
||||
} else {
|
||||
// 非节单位,和单位前的单数字组合为值
|
||||
int unitNumber = number;
|
||||
if (0 == number && 0 == i) {
|
||||
// issue#1726,对于单位开头的数组,默认赋予1
|
||||
// 十二 -> 一十二
|
||||
// 百二 -> 一百二
|
||||
unitNumber = 1;
|
||||
}
|
||||
section += (unitNumber * unit.value);
|
||||
}
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (number > 0 && null != unit) {
|
||||
number = number * (unit.value / 10);
|
||||
}
|
||||
|
||||
return result + section + number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中文大写数字金额转换为数字,返回结果以元为单位的BigDecimal类型数字<br>
|
||||
* 如:
|
||||
* “陆万柒仟伍佰伍拾陆元叁角贰分”返回“67556.32”
|
||||
* “叁角贰分”返回“0.32”
|
||||
*
|
||||
* @param chineseMoneyAmount 中文大写数字金额
|
||||
* @return 返回结果以元为单位的BigDecimal类型数字
|
||||
*/
|
||||
public static BigDecimal parseFromChineseMoney(final String chineseMoneyAmount) {
|
||||
if (StrUtil.isBlank(chineseMoneyAmount)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int yi = chineseMoneyAmount.indexOf("元");
|
||||
if (yi == -1) {
|
||||
yi = chineseMoneyAmount.indexOf("圆");
|
||||
}
|
||||
final int ji = chineseMoneyAmount.indexOf("角");
|
||||
final int fi = chineseMoneyAmount.indexOf("分");
|
||||
|
||||
// 先找到单位为元的数字
|
||||
String yStr = null;
|
||||
if (yi > 0) {
|
||||
yStr = chineseMoneyAmount.substring(0, yi);
|
||||
}
|
||||
|
||||
// 再找到单位为角的数字
|
||||
String jStr = null;
|
||||
if (ji > 0) {
|
||||
if (yi >= 0) {
|
||||
//前面有元,角肯定要在元后面
|
||||
if (ji > yi) {
|
||||
jStr = chineseMoneyAmount.substring(yi + 1, ji);
|
||||
}
|
||||
} else {
|
||||
//没有元,只有角
|
||||
jStr = chineseMoneyAmount.substring(0, ji);
|
||||
}
|
||||
}
|
||||
|
||||
// 再找到单位为分的数字
|
||||
String fStr = null;
|
||||
if (fi > 0) {
|
||||
if (ji >= 0) {
|
||||
//有角,分肯定在角后面
|
||||
if (fi > ji) {
|
||||
fStr = chineseMoneyAmount.substring(ji + 1, fi);
|
||||
}
|
||||
} else if (yi > 0) {
|
||||
//没有角,有元,那就坐元后面找
|
||||
if (fi > yi) {
|
||||
fStr = chineseMoneyAmount.substring(yi + 1, fi);
|
||||
}
|
||||
} else {
|
||||
//没有元、角,只有分
|
||||
fStr = chineseMoneyAmount.substring(0, fi);
|
||||
}
|
||||
}
|
||||
|
||||
//元、角、分
|
||||
int y = 0, j = 0, f = 0;
|
||||
if (StrUtil.isNotBlank(yStr)) {
|
||||
y = parseFromChineseNumber(yStr);
|
||||
}
|
||||
if (StrUtil.isNotBlank(jStr)) {
|
||||
j = parseFromChineseNumber(jStr);
|
||||
}
|
||||
if (StrUtil.isNotBlank(fStr)) {
|
||||
f = parseFromChineseNumber(fStr);
|
||||
}
|
||||
|
||||
BigDecimal amount = new BigDecimal(y);
|
||||
amount = amount.add(BigDecimal.valueOf(j).divide(BigDecimal.TEN, 2, RoundingMode.HALF_UP));
|
||||
amount = amount.add(BigDecimal.valueOf(f).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找对应的权对象
|
||||
*
|
||||
* @param chinese 中文权位名
|
||||
* @return 权对象
|
||||
*/
|
||||
private static ChineseUnit chineseToUnit(final char chinese) {
|
||||
for (final ChineseUnit chineseNameValue : CHINESE_NAME_VALUE) {
|
||||
if (chineseNameValue.name == chinese) {
|
||||
return chineseNameValue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将汉字单个数字转换为int类型数字
|
||||
*
|
||||
* @param chinese 汉字数字,支持简体和繁体
|
||||
* @return 数字,-1表示未找到
|
||||
* @since 5.6.4
|
||||
*/
|
||||
private static int chineseToNumber(char chinese) {
|
||||
if ('两' == chinese) {
|
||||
// 口语纠正
|
||||
chinese = '二';
|
||||
}
|
||||
final int i = ArrayUtil.indexOf(ChineseNumberFormatter.DIGITS, chinese);
|
||||
if (i > 0) {
|
||||
return (i + 1) / 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应级别的单位
|
||||
*
|
||||
* @param index 级别,0表示各位,1表示十位,2表示百位,以此类推
|
||||
* @param isUseTraditional 是否使用繁体
|
||||
* @return 单位
|
||||
*/
|
||||
static String getUnitName(final int index, final boolean isUseTraditional) {
|
||||
if (0 == index) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
return String.valueOf(CHINESE_NAME_VALUE[index * 2 - (isUseTraditional ? 0 : 1)].name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权位
|
||||
*
|
||||
* @author totalo
|
||||
* @since 5.6.0
|
||||
*/
|
||||
private static class ChineseUnit {
|
||||
/**
|
||||
* 中文权名称
|
||||
*/
|
||||
private final char name;
|
||||
/**
|
||||
* 10的倍数值
|
||||
*/
|
||||
private final int value;
|
||||
/**
|
||||
* 是否为节权位,它不是与之相邻的数字的倍数,而是整个小节的倍数。<br>
|
||||
* 例如二十三万,万是节权位,与三无关,而和二十三关联
|
||||
*/
|
||||
private final boolean secUnit;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 名称
|
||||
* @param value 值,即10的倍数
|
||||
* @param secUnit 是否为节权位
|
||||
*/
|
||||
public ChineseUnit(final char name, final int value, final boolean secUnit) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.secUnit = secUnit;
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,7 +12,6 @@
|
||||
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
/**
|
||||
@@ -22,7 +21,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
* @author Looly, totalo
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public class NumberWordFormatter {
|
||||
public class EnglishNumberFormatter {
|
||||
|
||||
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
|
||||
"EIGHT", "NINE"};
|
@@ -283,21 +283,21 @@ public class NumberChineseFormatterTest {
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest(){
|
||||
Assertions.assertEquals(0, ChineseNumberFormatter.parseFromChinese("零"));
|
||||
Assertions.assertEquals(102, ChineseNumberFormatter.parseFromChinese("一百零二"));
|
||||
Assertions.assertEquals(112, ChineseNumberFormatter.parseFromChinese("一百一十二"));
|
||||
Assertions.assertEquals(1012, ChineseNumberFormatter.parseFromChinese("一千零一十二"));
|
||||
Assertions.assertEquals(1000000, ChineseNumberFormatter.parseFromChinese("一百万"));
|
||||
Assertions.assertEquals(2000100112, ChineseNumberFormatter.parseFromChinese("二十亿零一十万零一百一十二"));
|
||||
Assertions.assertEquals(0, ChineseNumberParser.parseFromChinese("零"));
|
||||
Assertions.assertEquals(102, ChineseNumberParser.parseFromChinese("一百零二"));
|
||||
Assertions.assertEquals(112, ChineseNumberParser.parseFromChinese("一百一十二"));
|
||||
Assertions.assertEquals(1012, ChineseNumberParser.parseFromChinese("一千零一十二"));
|
||||
Assertions.assertEquals(1000000, ChineseNumberParser.parseFromChinese("一百万"));
|
||||
Assertions.assertEquals(2000100112, ChineseNumberParser.parseFromChinese("二十亿零一十万零一百一十二"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest2(){
|
||||
Assertions.assertEquals(120, ChineseNumberFormatter.parseFromChinese("一百二"));
|
||||
Assertions.assertEquals(1200, ChineseNumberFormatter.parseFromChinese("一千二"));
|
||||
Assertions.assertEquals(22000, ChineseNumberFormatter.parseFromChinese("两万二"));
|
||||
Assertions.assertEquals(22003, ChineseNumberFormatter.parseFromChinese("两万二零三"));
|
||||
Assertions.assertEquals(22010, ChineseNumberFormatter.parseFromChinese("两万二零一十"));
|
||||
Assertions.assertEquals(120, ChineseNumberParser.parseFromChinese("一百二"));
|
||||
Assertions.assertEquals(1200, ChineseNumberParser.parseFromChinese("一千二"));
|
||||
Assertions.assertEquals(22000, ChineseNumberParser.parseFromChinese("两万二"));
|
||||
Assertions.assertEquals(22003, ChineseNumberParser.parseFromChinese("两万二零三"));
|
||||
Assertions.assertEquals(22010, ChineseNumberParser.parseFromChinese("两万二零一十"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -305,16 +305,16 @@ public class NumberChineseFormatterTest {
|
||||
// issue#1726,对于单位开头的数组,默认赋予1
|
||||
// 十二 -> 一十二
|
||||
// 百二 -> 一百二
|
||||
Assertions.assertEquals(12, ChineseNumberFormatter.parseFromChinese("十二"));
|
||||
Assertions.assertEquals(120, ChineseNumberFormatter.parseFromChinese("百二"));
|
||||
Assertions.assertEquals(1300, ChineseNumberFormatter.parseFromChinese("千三"));
|
||||
Assertions.assertEquals(12, ChineseNumberParser.parseFromChinese("十二"));
|
||||
Assertions.assertEquals(120, ChineseNumberParser.parseFromChinese("百二"));
|
||||
Assertions.assertEquals(1300, ChineseNumberParser.parseFromChinese("千三"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNumberTest(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 连续数字检查
|
||||
ChineseNumberFormatter.parseFromChinese("一百一二三");
|
||||
ChineseNumberParser.parseFromChinese("一百一二三");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ public class NumberChineseFormatterTest {
|
||||
public void badNumberTest2(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 非法字符
|
||||
ChineseNumberFormatter.parseFromChinese("一百你三");
|
||||
ChineseNumberParser.parseFromChinese("一百你三");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -373,13 +373,13 @@ public class NumberChineseFormatterTest {
|
||||
* s=叁角贰分, n=0.32
|
||||
* s=陆万柒仟伍佰伍拾陆元叁角贰分, n=67556.32
|
||||
*/
|
||||
Assertions.assertEquals(67556, ChineseNumberFormatter.parseFromChineseMoney("陆万柒仟伍佰伍拾陆圆").longValue());
|
||||
Assertions.assertEquals(67556, ChineseNumberFormatter.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元").longValue());
|
||||
Assertions.assertEquals(0.3D, ChineseNumberFormatter.parseFromChineseMoney("叁角").doubleValue(), 0);
|
||||
Assertions.assertEquals(0.02, ChineseNumberFormatter.parseFromChineseMoney("贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.3, ChineseNumberFormatter.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元叁角").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.02, ChineseNumberFormatter.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(0.32, ChineseNumberFormatter.parseFromChineseMoney("叁角贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.32, ChineseNumberFormatter.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元叁角贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556, ChineseNumberParser.parseFromChineseMoney("陆万柒仟伍佰伍拾陆圆").longValue());
|
||||
Assertions.assertEquals(67556, ChineseNumberParser.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元").longValue());
|
||||
Assertions.assertEquals(0.3D, ChineseNumberParser.parseFromChineseMoney("叁角").doubleValue(), 0);
|
||||
Assertions.assertEquals(0.02, ChineseNumberParser.parseFromChineseMoney("贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.3, ChineseNumberParser.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元叁角").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.02, ChineseNumberParser.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(0.32, ChineseNumberParser.parseFromChineseMoney("叁角贰分").doubleValue(), 0);
|
||||
Assertions.assertEquals(67556.32, ChineseNumberParser.parseFromChineseMoney("陆万柒仟伍佰伍拾陆元叁角贰分").doubleValue(), 0);
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@
|
||||
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.math.NumberWordFormatter;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -20,37 +19,37 @@ public class NumberWordFormatTest {
|
||||
|
||||
@Test
|
||||
public void formatTest() {
|
||||
final String format = NumberWordFormatter.format(100.23);
|
||||
final String format = EnglishNumberFormatter.format(100.23);
|
||||
Assertions.assertEquals("ONE HUNDRED AND CENTS TWENTY THREE ONLY", format);
|
||||
|
||||
final String format2 = NumberWordFormatter.format("2100.00");
|
||||
final String format2 = EnglishNumberFormatter.format("2100.00");
|
||||
Assertions.assertEquals("TWO THOUSAND ONE HUNDRED AND CENTS ONLY", format2);
|
||||
|
||||
final String format3 = NumberWordFormatter.format("1234567890123.12");
|
||||
final String format3 = EnglishNumberFormatter.format("1234567890123.12");
|
||||
Assertions.assertEquals("ONE TRILLION TWO HUNDRED AND THIRTY FOUR BILLION FIVE HUNDRED AND SIXTY SEVEN MILLION EIGHT HUNDRED AND NINETY THOUSAND ONE HUNDRED AND TWENTY THREE AND CENTS TWELVE ONLY", format3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatSimpleTest() {
|
||||
final String format1 = NumberWordFormatter.formatSimple(1200, false);
|
||||
final String format1 = EnglishNumberFormatter.formatSimple(1200, false);
|
||||
Assertions.assertEquals("1.2k", format1);
|
||||
|
||||
final String format2 = NumberWordFormatter.formatSimple(4384324, false);
|
||||
final String format2 = EnglishNumberFormatter.formatSimple(4384324, false);
|
||||
Assertions.assertEquals("4.38m", format2);
|
||||
|
||||
final String format3 = NumberWordFormatter.formatSimple(4384324, true);
|
||||
final String format3 = EnglishNumberFormatter.formatSimple(4384324, true);
|
||||
Assertions.assertEquals("438.43w", format3);
|
||||
|
||||
final String format4 = NumberWordFormatter.formatSimple(4384324);
|
||||
final String format4 = EnglishNumberFormatter.formatSimple(4384324);
|
||||
Assertions.assertEquals("438.43w", format4);
|
||||
|
||||
final String format5 = NumberWordFormatter.formatSimple(438);
|
||||
final String format5 = EnglishNumberFormatter.formatSimple(438);
|
||||
Assertions.assertEquals("438", format5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatSimpleTest2(){
|
||||
final String s = NumberWordFormatter.formatSimple(1000);
|
||||
final String s = EnglishNumberFormatter.formatSimple(1000);
|
||||
Assertions.assertEquals("1k", s);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user