mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -1047,7 +1047,7 @@ public class Convert {
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static int chineseToNumber(final String number){
|
||||
public static BigDecimal chineseToNumber(final String number){
|
||||
return ChineseNumberParser.parseFromChineseNumber(number);
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@@ -52,7 +53,7 @@ public class ChineseNumberParser {
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static Number parseFromChinese(final String chinese) {
|
||||
public static BigDecimal parseFromChinese(final String chinese) {
|
||||
if (StrUtil.containsAny(chinese, '元', '圆', '角', '分')) {
|
||||
return parseFromChineseMoney(chinese);
|
||||
}
|
||||
@@ -61,74 +62,36 @@ public class ChineseNumberParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 把中文转换为数字 如 二百二十 220<br>
|
||||
* 把中文转换为数字<br>
|
||||
* <ul>
|
||||
* <li>一百一十二 -》 112</li>
|
||||
* <li>一千零一十二 -》 1012</li>
|
||||
* <li>十二点二三 -》 12.23</li>
|
||||
* <li>三点一四一五九二六五四 -》 3.141592654</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param chinese 中文字符
|
||||
* @return 数字
|
||||
* @since 5.6.0
|
||||
*/
|
||||
public static int parseFromChineseNumber(final String chinese) {
|
||||
public static BigDecimal parseFromChineseNumber(final String chinese) {
|
||||
Assert.notBlank(chinese, "Chinese number is blank!");
|
||||
final int dotIndex = chinese.indexOf('点');
|
||||
|
||||
// 整数部分
|
||||
BigDecimal result = NumberUtil.toBigDecimal(parseLongFromChineseNumber(chinese, dotIndex > 0 ? dotIndex : chinese.length()));
|
||||
|
||||
// 小数部分
|
||||
if (dotIndex > 0) {
|
||||
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;
|
||||
for (int i = dotIndex + 1; i < length; i++) {
|
||||
// 保留位数取决于实际数字的位数
|
||||
// result + (numberChar / 10^(i-dotIndex))
|
||||
result = result.add(NumberUtil.div(chineseToNumber(chinese.charAt(i)), BigDecimal.TEN.pow(i-dotIndex), (length - dotIndex + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (number > 0 && null != unit) {
|
||||
number = number * (unit.value / 10);
|
||||
}
|
||||
|
||||
return result + section + number;
|
||||
return result.stripTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,15 +155,15 @@ public class ChineseNumberParser {
|
||||
}
|
||||
|
||||
//元、角、分
|
||||
int y = 0, j = 0, f = 0;
|
||||
long y = 0, j = 0, f = 0;
|
||||
if (StrUtil.isNotBlank(yStr)) {
|
||||
y = parseFromChineseNumber(yStr);
|
||||
y = parseLongFromChineseNumber(yStr, yStr.length());
|
||||
}
|
||||
if (StrUtil.isNotBlank(jStr)) {
|
||||
j = parseFromChineseNumber(jStr);
|
||||
j = parseLongFromChineseNumber(jStr, jStr.length());
|
||||
}
|
||||
if (StrUtil.isNotBlank(fStr)) {
|
||||
f = parseFromChineseNumber(fStr);
|
||||
f = parseLongFromChineseNumber(fStr, fStr.length());
|
||||
}
|
||||
|
||||
BigDecimal amount = new BigDecimal(y);
|
||||
@@ -209,6 +172,76 @@ public class ChineseNumberParser {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把中文整数转换为数字 如 二百二十 220<br>
|
||||
* <ul>
|
||||
* <li>一百一十二 -》 112</li>
|
||||
* <li>一千零一十二 -》 1012</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param chinese 中文字符
|
||||
* @param toIndex 结束位置(不包括),如果提供的是整数,这个为length(),小数则是“点”的位置
|
||||
* @return 数字
|
||||
*/
|
||||
public static long parseLongFromChineseNumber(final String chinese, final int toIndex) {
|
||||
long result = 0;
|
||||
|
||||
// 节总和
|
||||
long section = 0;
|
||||
long number = 0;
|
||||
ChineseUnit unit = null;
|
||||
char c;
|
||||
for (int i = 0; i < toIndex; 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 {
|
||||
// 非节单位,和单位前的单数字组合为值
|
||||
long 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找对应的权对象
|
||||
*
|
||||
|
@@ -281,51 +281,6 @@ public class ChineseNumberFormatterTest {
|
||||
Assertions.assertEquals('A', s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest(){
|
||||
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, ChineseNumberParser.parseFromChinese("一百二"));
|
||||
Assertions.assertEquals(1200, ChineseNumberParser.parseFromChinese("一千二"));
|
||||
Assertions.assertEquals(22000, ChineseNumberParser.parseFromChinese("两万二"));
|
||||
Assertions.assertEquals(22003, ChineseNumberParser.parseFromChinese("两万二零三"));
|
||||
Assertions.assertEquals(22010, ChineseNumberParser.parseFromChinese("两万二零一十"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest3(){
|
||||
// issue#1726,对于单位开头的数组,默认赋予1
|
||||
// 十二 -> 一十二
|
||||
// 百二 -> 一百二
|
||||
Assertions.assertEquals(12, ChineseNumberParser.parseFromChinese("十二"));
|
||||
Assertions.assertEquals(120, ChineseNumberParser.parseFromChinese("百二"));
|
||||
Assertions.assertEquals(1300, ChineseNumberParser.parseFromChinese("千三"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNumberTest(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 连续数字检查
|
||||
ChineseNumberParser.parseFromChinese("一百一二三");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNumberTest2(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 非法字符
|
||||
ChineseNumberParser.parseFromChinese("一百你三");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleMoneyTest(){
|
||||
String format = ChineseNumberFormatter.of().setMoneyMode(true).format(0.01);
|
||||
@@ -359,27 +314,4 @@ public class ChineseNumberFormatterTest {
|
||||
format = ChineseNumberFormatter.of().format(1.02);
|
||||
Assertions.assertEquals("一点零二", format);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
public void testChineseMoneyToNumber(){
|
||||
/*
|
||||
* s=陆万柒仟伍佰伍拾陆圆, n=67556
|
||||
* s=陆万柒仟伍佰伍拾陆元, n=67556
|
||||
* s=叁角, n=0.3
|
||||
* s=贰分, n=0.02
|
||||
* s=陆万柒仟伍佰伍拾陆元叁角, n=67556.3
|
||||
* s=陆万柒仟伍佰伍拾陆元贰分, n=67556.02
|
||||
* s=叁角贰分, n=0.32
|
||||
* s=陆万柒仟伍佰伍拾陆元叁角贰分, n=67556.32
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,88 @@
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class ChineseNumberParserTest {
|
||||
@Test
|
||||
public void chineseToNumberTest(){
|
||||
Assertions.assertEquals(0, parseFromChinese("零"));
|
||||
Assertions.assertEquals(102, parseFromChinese("一百零二"));
|
||||
Assertions.assertEquals(112, parseFromChinese("一百一十二"));
|
||||
Assertions.assertEquals(1012, parseFromChinese("一千零一十二"));
|
||||
Assertions.assertEquals(1000000, parseFromChinese("一百万"));
|
||||
Assertions.assertEquals(2000100112, parseFromChinese("二十亿零一十万零一百一十二"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest2(){
|
||||
Assertions.assertEquals(120, parseFromChinese("一百二"));
|
||||
Assertions.assertEquals(1200, parseFromChinese("一千二"));
|
||||
Assertions.assertEquals(22000, parseFromChinese("两万二"));
|
||||
Assertions.assertEquals(22003, parseFromChinese("两万二零三"));
|
||||
Assertions.assertEquals(22010, parseFromChinese("两万二零一十"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chineseToNumberTest3(){
|
||||
// issue#1726,对于单位开头的数组,默认赋予1
|
||||
// 十二 -> 一十二
|
||||
// 百二 -> 一百二
|
||||
Assertions.assertEquals(12, parseFromChinese("十二"));
|
||||
Assertions.assertEquals(120, parseFromChinese("百二"));
|
||||
Assertions.assertEquals(1300, parseFromChinese("千三"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNumberTest(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 连续数字检查
|
||||
ChineseNumberParser.parseFromChinese("一百一二三");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badNumberTest2(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
// 非法字符
|
||||
ChineseNumberParser.parseFromChinese("一百你三");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChineseMoneyToNumber(){
|
||||
/*
|
||||
* s=陆万柒仟伍佰伍拾陆圆, n=67556
|
||||
* s=陆万柒仟伍佰伍拾陆元, n=67556
|
||||
* s=叁角, n=0.3
|
||||
* s=贰分, n=0.02
|
||||
* s=陆万柒仟伍佰伍拾陆元叁角, n=67556.3
|
||||
* s=陆万柒仟伍佰伍拾陆元贰分, n=67556.02
|
||||
* s=叁角贰分, n=0.32
|
||||
* s=陆万柒仟伍佰伍拾陆元叁角贰分, n=67556.32
|
||||
*/
|
||||
Assertions.assertEquals(67556, parseFromChinese("陆万柒仟伍佰伍拾陆圆"));
|
||||
Assertions.assertEquals(67556, parseFromChinese("陆万柒仟伍佰伍拾陆元"));
|
||||
Assertions.assertEquals(0.3D, parseFromChinese("叁角"), 0);
|
||||
Assertions.assertEquals(0.02, parseFromChinese("贰分"), 0);
|
||||
Assertions.assertEquals(67556.3, parseFromChinese("陆万柒仟伍佰伍拾陆元叁角"), 0);
|
||||
Assertions.assertEquals(67556.02, parseFromChinese("陆万柒仟伍佰伍拾陆元贰分"), 0);
|
||||
Assertions.assertEquals(0.32, parseFromChinese("叁角贰分"), 0);
|
||||
Assertions.assertEquals(67556.32, parseFromChinese("陆万柒仟伍佰伍拾陆元叁角贰分"), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseFromChineseNumberTest() {
|
||||
BigDecimal i = ChineseNumberParser.parseFromChineseNumber("十二点二三");
|
||||
Assertions.assertEquals(NumberUtil.toBigDecimal(12.23D), i);
|
||||
|
||||
i = ChineseNumberParser.parseFromChineseNumber("三点一四一五九二六五四");
|
||||
Assertions.assertEquals(NumberUtil.toBigDecimal(3.141592654D), i);
|
||||
}
|
||||
|
||||
private double parseFromChinese(final String str){
|
||||
return ChineseNumberParser.parseFromChinese(str).doubleValue();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user