Merge pull request #1469 from totalo/v5-dev

feat:支持汉字转阿拉伯数字
This commit is contained in:
Golden Looly 2021-03-10 15:21:52 +08:00 committed by GitHub
commit fc47566ddc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 160 additions and 6 deletions

View File

@ -0,0 +1,52 @@
package cn.hutool.core.convert;
/**
* @author totalo
* @since 5.6.0
* 中文转数字结构
*/
public final class ChineseNameValue {
/**
* 中文权名称
*/
String name;
/**
* 10的倍数值
*/
int value;
/**
* 是否为节权位
*/
boolean secUnit;
public ChineseNameValue(String name, int value, boolean secUnit) {
this.name = name;
this.value = value;
this.secUnit = secUnit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isSecUnit() {
return secUnit;
}
public void setSecUnit(boolean secUnit) {
this.secUnit = secUnit;
}
}

View File

@ -33,6 +33,18 @@ public class NumberChineseFormatter {
**/
private static final String[] TRADITIONAL_UNITS = {"", "", "", ""};
/**
* 汉字转阿拉伯数字的
*/
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),
};
/**
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数小数的转换.
*
@ -193,4 +205,79 @@ public class NumberChineseFormatter {
}
return chineseStr.toString();
}
/**
* 把中文转换为数字 二百二 220
* @see <url>https://www.d5.nz/read/sfdlq/text-part0000_split_030.html</url>
* @param chinese 中文字符
* @return
*/
public static int chineseToNumber(String chinese) {
int pos = 0;
int rtn = 0;
int section = 0;
int number = 0;
boolean secUnit = false;
while (pos < chinese.length()) {
int num = chineseToValue(chinese.substring(pos, pos + 1));
if (num >= 0) {
number = num;
pos += 1;
if (pos >= chinese.length()) {
section += number;
rtn += section;
break;
}
} else {
int unit = 1;
int tmp = chineseToUnit(chinese.substring(pos, pos + 1));
if (tmp != -1) {
unit = CHINESE_NAME_VALUE[tmp].getValue();
secUnit = CHINESE_NAME_VALUE[tmp].isSecUnit();
}
if (secUnit) {
section = (section + number) * unit;
rtn += section;
section = 0;
} else {
section += (number * unit);
}
number = 0;
pos += 1;
if (pos >= chinese.length()) {
rtn += section;
break;
}
}
}
return rtn;
}
/**
* 中文到数字的转换
* @param chinese
* @return
*/
private static int chineseToValue(String chinese) {
for (int i = 0; i < SIMPLE_DIGITS.length; i++) {
if (SIMPLE_DIGITS[i].equals(chinese)) {
return i;
}
}
return -1;
}
/**
* 查找对应的权
* @param chinese
* @return
*/
private static int chineseToUnit(String chinese) {
for (int i = 0; i < CHINESE_NAME_VALUE.length; i++) {
if (CHINESE_NAME_VALUE[i].getName().equals(chinese)) {
return i;
}
}
return -1;
}
}

View File

@ -4,7 +4,7 @@ import org.junit.Assert;
import org.junit.Test;
public class NumberChineseFormatterTest {
@Test
public void formatTest() {
String f1 = NumberChineseFormatter.format(10889.72356, false);
@ -24,7 +24,7 @@ public class NumberChineseFormatterTest {
f1 = NumberChineseFormatter.format(0.05, false);
Assert.assertEquals("零点零五", f1);
}
@Test
public void formatTest2() {
String f1 = NumberChineseFormatter.format(-0.3, false, false);
@ -33,7 +33,7 @@ public class NumberChineseFormatterTest {
f1 = NumberChineseFormatter.format(10, false, false);
Assert.assertEquals("一十", f1);
}
@Test
public void formatTraditionalTest() {
String f1 = NumberChineseFormatter.format(10889.72356, true);
@ -53,15 +53,15 @@ public class NumberChineseFormatterTest {
f1 = NumberChineseFormatter.format(0.05, true);
Assert.assertEquals("零点零伍", f1);
}
@Test
public void digitToChineseTest() {
String digitToChinese = Convert.digitToChinese(12412412412421.12);
Assert.assertEquals("壹拾贰万肆仟壹佰贰拾肆亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元壹角贰分", digitToChinese);
String digitToChinese2 = Convert.digitToChinese(12412412412421D);
Assert.assertEquals("壹拾贰万肆仟壹佰贰拾肆亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元整", digitToChinese2);
String digitToChinese3 = Convert.digitToChinese(2421.02);
Assert.assertEquals("贰仟肆佰贰拾壹元零贰分", digitToChinese3);
}
@ -79,4 +79,19 @@ public class NumberChineseFormatterTest {
s = NumberChineseFormatter.numberCharToChinese('A', false);
Assert.assertEquals("A", s);
}
@Test
public void chineseToNumberTest(){
Assert.assertEquals(0, NumberChineseFormatter.chineseToNumber(""));
Assert.assertEquals(102, NumberChineseFormatter.chineseToNumber("一百零二"));
Assert.assertEquals(112, NumberChineseFormatter.chineseToNumber("一百一十二"));
Assert.assertEquals(1012, NumberChineseFormatter.chineseToNumber("一千零一十二"));
Assert.assertEquals(1000000, NumberChineseFormatter.chineseToNumber("一百万"));
Assert.assertEquals(2000100112, NumberChineseFormatter.chineseToNumber("二十亿零一十万零一百一十二"));
}
}