fix format

This commit is contained in:
Looly 2021-08-08 20:01:02 +08:00
parent f2151abf74
commit a9282b9d7c
3 changed files with 235 additions and 69 deletions

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
# 5.7.8 (2021-08-07)
# 5.7.8 (2021-08-08)
### 🐣新特性
* 【core 】 MapProxy支持return this的setter方法pr#392@Gitee
@ -11,6 +11,7 @@
* 【core 】 增加compress包扩充Zip操作灵活性
### 🐞Bug修复
* 【core 】 改进NumberChineseFormatter算法补充完整单元测试解决零问题
-------------------------------------------------------------------------------------------------------------

View File

@ -34,8 +34,8 @@ public class NumberChineseFormatter {
new ChineseUnit('佰', 100, false),
new ChineseUnit('千', 1000, false),
new ChineseUnit('仟', 1000, false),
new ChineseUnit('万', 10000, true),
new ChineseUnit('亿', 100000000, true),
new ChineseUnit('万', 1_0000, true),
new ChineseUnit('亿', 1_0000_0000, true),
};
@ -63,71 +63,22 @@ public class NumberChineseFormatter {
throw new IllegalArgumentException("Number support only: (-99999999999999.99 99999999999999.99)");
}
// 负数
boolean negative = false;
if (amount < 0) {
negative = true;
amount = -amount;
}
// 分和角
long temp = Math.round(amount * 100);
int numFen = (int) (temp % 10);
final int numFen = (int) (temp % 10);
temp = temp / 10;
int numJiao = (int) (temp % 10);
final int numJiao = (int) (temp % 10);
temp = temp / 10;
//将数字以万为单位分为多份
int[] parts = new int[20];
int partsCount = 0;
for (int i = 0; temp != 0; i++) {
int part = (int) (temp % 10000);
parts[i] = part;
partsCount++;
temp = temp / 10000;
}
boolean underWanIsZero = true; // 标志下面一级是不是 0
StringBuilder chineseStr = new StringBuilder();
for (int i = 0; i < partsCount; i++) {
final String partChinese = toChinese(parts[i], isUseTraditional);
if (i % 2 == 0) {
underWanIsZero = StrUtil.isEmpty(partChinese);
}
// TODO 此处逻辑过于复杂等待整理重构
if (i != 0) {
if (i % 2 == 0) {
if (parts[i - 1] < 1000 && parts[i - 1] > 0) {
// 如果"亿"的部分不为 0, "亿"以下的部分小于 1000则亿后面应该跟如一亿零三十五万
chineseStr.insert(0, "");
}
chineseStr.insert(0, "亿");
} else {
if (StrUtil.isEmpty(partChinese) && false == underWanIsZero) {
// 如果对应的 part 0下面一级不为 0则不加而加
chineseStr.insert(0, "");
} else {
if (parts[i - 1] < 1000 && parts[i - 1] > 0) {
// 如果""的部分不为 0, ""以下的部分小于 1000 大于 0 则万后面应该跟如一万零三百
chineseStr.insert(0, "");
} else if(parts[i] > 0 && parts[i] % 10 == 0){
// 如果万的部分没有个位数需跟如十万零八千
chineseStr.insert(0, "");
}
if (parts[i] > 0) {
// 如果""的部分不为 0 则增加万
chineseStr.insert(0, "");
}
}
}
}
chineseStr.insert(0, partChinese);
}
// 整数部分为 0, 则表达为""
if (StrUtil.EMPTY.equals(chineseStr.toString())) {
chineseStr = new StringBuilder(String.valueOf(DIGITS[0]));
}
final StringBuilder chineseStr = new StringBuilder(longToChinese(temp, isUseTraditional));
//负数
if (negative) { // 整数部分不为 0
chineseStr.insert(0, "");
@ -150,7 +101,6 @@ public class NumberChineseFormatter {
}
return chineseStr.toString();
}
/**
@ -168,6 +118,95 @@ public class NumberChineseFormatter {
return String.valueOf(numberToChinese(c - '0', isUseTraditional));
}
/**
* 阿拉伯数字整数部分转换成中文只支持正数
*
* @param amount 数字
* @param isUseTraditional 是否使用繁体
* @return 中文
*/
private static String longToChinese(long amount, boolean isUseTraditional) {
if(0 == amount){
return "";
}
//将数字以万为单位分为多份
int[] parts = new int[4];
for (int i = 0; amount != 0; i++) {
parts[i] = (int) (amount % 10000);
amount = amount / 10000;
}
final StringBuilder chineseStr = new StringBuilder();
int partValue;
String partChinese;
//
partValue = parts[0];
if(partValue > 0){
partChinese = thousandToChinese(partValue, isUseTraditional);
chineseStr.insert(0, partChinese);
if(partValue < 1000){
// 和万位之间空0则补零如一万零三百
addPreZero(chineseStr);
}
}
//
partValue = parts[1];
if(partValue > 0){
if((partValue % 10 == 0 && parts[0] > 0)){
// 如果""的个位是0则补零如十万零八千
addPreZero(chineseStr);
}
partChinese = thousandToChinese(partValue, isUseTraditional);
chineseStr.insert(0, partChinese + "");
if(partValue < 1000){
// 和亿位之间空0则补零如一亿零三百万
addPreZero(chineseStr);
}
} else{
addPreZero(chineseStr);
}
// 亿
partValue = parts[2];
if(partValue > 0){
if((partValue % 10 == 0 && parts[1] > 0)){
// 如果""的个位是0则补零如十万零八千
addPreZero(chineseStr);
}
partChinese = thousandToChinese(partValue, isUseTraditional);
chineseStr.insert(0, partChinese + "亿");
if(partValue < 1000){
// 和万亿位之间空0则补零如一万亿零三百亿
addPreZero(chineseStr);
}
} else{
addPreZero(chineseStr);
}
// 万亿
partValue = parts[3];
if(partValue > 0){
if(parts[2] == 0){
chineseStr.insert(0, "亿");
}
partChinese = thousandToChinese(partValue, isUseTraditional);
chineseStr.insert(0, partChinese + "");
}
if(StrUtil.isNotEmpty(chineseStr) && '零' == chineseStr.charAt(0)){
return chineseStr.substring(1);
}
return chineseStr.toString();
}
/**
* 把一个 0~9999 之间的整数转换为汉字的字符串如果是 0 则返回 ""
*
@ -175,7 +214,7 @@ public class NumberChineseFormatter {
* @param isUseTraditional 是否使用繁体单位
* @return 转换后的汉字
*/
private static String toChinese(int amountPart, boolean isUseTraditional) {
private static String thousandToChinese(int amountPart, boolean isUseTraditional) {
int temp = amountPart;
StringBuilder chineseStr = new StringBuilder();
@ -365,4 +404,14 @@ public class NumberChineseFormatter {
this.secUnit = secUnit;
}
}
private static void addPreZero(StringBuilder chineseStr){
if(StrUtil.isEmpty(chineseStr)){
return;
}
final char c = chineseStr.charAt(0);
if('零' != c){
chineseStr.insert(0, '零');
}
}
}

View File

@ -5,11 +5,115 @@ import org.junit.Test;
public class NumberChineseFormatterTest {
// 测试千
@Test
public void formatThousandLongTest(){
String f = NumberChineseFormatter.format(0, false);
Assert.assertEquals("", f);
f = NumberChineseFormatter.format(1, false);
Assert.assertEquals("", f);
f = NumberChineseFormatter.format(10, false);
Assert.assertEquals("一十", f);
f = NumberChineseFormatter.format(12, false);
Assert.assertEquals("一十二", f);
f = NumberChineseFormatter.format(100, false);
Assert.assertEquals("一百", f);
f = NumberChineseFormatter.format(101, false);
Assert.assertEquals("一百零一", f);
f = NumberChineseFormatter.format(110, false);
Assert.assertEquals("一百一十", f);
f = NumberChineseFormatter.format(112, false);
Assert.assertEquals("一百一十二", f);
f = NumberChineseFormatter.format(1000, false);
Assert.assertEquals("一千", f);
f = NumberChineseFormatter.format(1001, false);
Assert.assertEquals("一千零一", f);
f = NumberChineseFormatter.format(1010, false);
Assert.assertEquals("一千零一十", f);
f = NumberChineseFormatter.format(1100, false);
Assert.assertEquals("一千一百", f);
f = NumberChineseFormatter.format(1101, false);
Assert.assertEquals("一千一百零一", f);
f = NumberChineseFormatter.format(9999, false);
Assert.assertEquals("九千九百九十九", f);
}
// 测试万
@Test
public void formatTenThousandLongTest(){
String f = NumberChineseFormatter.format(1_0000, false);
Assert.assertEquals("一万", f);
f = NumberChineseFormatter.format(1_0001, false);
Assert.assertEquals("一万零一", f);
f = NumberChineseFormatter.format(1_0010, false);
Assert.assertEquals("一万零一十", f);
f = NumberChineseFormatter.format(1_0100, false);
Assert.assertEquals("一万零一百", f);
f = NumberChineseFormatter.format(1_1000, false);
Assert.assertEquals("一万一千", f);
f = NumberChineseFormatter.format(10_1000, false);
Assert.assertEquals("一十万零一千", f);
f = NumberChineseFormatter.format(10_0100, false);
Assert.assertEquals("一十万零一百", f);
f = NumberChineseFormatter.format(100_1000, false);
Assert.assertEquals("一百万零一千", f);
f = NumberChineseFormatter.format(100_0100, false);
Assert.assertEquals("一百万零一百", f);
f = NumberChineseFormatter.format(1000_1000, false);
Assert.assertEquals("一千万零一千", f);
f = NumberChineseFormatter.format(1000_0100, false);
Assert.assertEquals("一千万零一百", f);
f = NumberChineseFormatter.format(9999_0000, false);
Assert.assertEquals("九千九百九十九万", f);
}
// 测试亿
@Test
public void formatHundredMillionLongTest(){
String f = NumberChineseFormatter.format(1_0000_0000L, false);
Assert.assertEquals("一亿", f);
f = NumberChineseFormatter.format(1_0000_0001L, false);
Assert.assertEquals("一亿零一", f);
f = NumberChineseFormatter.format(1_0000_1000L, false);
Assert.assertEquals("一亿零一千", f);
f = NumberChineseFormatter.format(1_0001_0000L, false);
Assert.assertEquals("一亿零一万", f);
f = NumberChineseFormatter.format(1_0010_0000L, false);
Assert.assertEquals("一亿零一十万", f);
f = NumberChineseFormatter.format(1_0010_0000L, false);
Assert.assertEquals("一亿零一十万", f);
f = NumberChineseFormatter.format(1_0100_0000L, false);
Assert.assertEquals("一亿零一百万", f);
f = NumberChineseFormatter.format(1_1000_0000L, false);
Assert.assertEquals("一亿一千万", f);
f = NumberChineseFormatter.format(10_1000_0000L, false);
Assert.assertEquals("一十亿零一千万", f);
f = NumberChineseFormatter.format(100_1000_0000L, false);
Assert.assertEquals("一百亿零一千万", f);
f = NumberChineseFormatter.format(1000_1000_0000L, false);
Assert.assertEquals("一千亿零一千万", f);
f = NumberChineseFormatter.format(1100_1000_0000L, false);
Assert.assertEquals("一千一百亿零一千万", f);
f = NumberChineseFormatter.format(9999_0000_0000L, false);
Assert.assertEquals("九千九百九十九亿", f);
}
// 测试万亿
@Test
public void formatTrillionsLongTest(){
String f = NumberChineseFormatter.format(1_0000_0000_0000L, false);
Assert.assertEquals("一万亿", f);
f = NumberChineseFormatter.format(1_0000_1000_0000L, false);
Assert.assertEquals("一万亿零一千万", f);
f = NumberChineseFormatter.format(1_0010_0000_0000L, false);
Assert.assertEquals("一万零一十亿", f);
}
@Test
public void formatTest() {
String f0 = NumberChineseFormatter.format(50008000, false);
String f0 = NumberChineseFormatter.format(5000_8000, false);
Assert.assertEquals("五千万零八千", f0);
String f1 = NumberChineseFormatter.format(10889.72356, false);
String f1 = NumberChineseFormatter.format(1_0889.72356, false);
Assert.assertEquals("一万零八百八十九点七二", f1);
f1 = NumberChineseFormatter.format(12653, false);
Assert.assertEquals("一万二千六百五十三", f1);
@ -73,14 +177,20 @@ public class NumberChineseFormatterTest {
@Test
public void digitToChineseTest() {
String digitToChinese = Convert.digitToChinese(12412412412421.12);
String digitToChinese = Convert.digitToChinese(12_4124_1241_2421.12);
Assert.assertEquals("壹拾贰万肆仟壹佰贰拾肆亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元壹角贰分", digitToChinese);
String digitToChinese2 = Convert.digitToChinese(12412412412421D);
Assert.assertEquals("壹拾贰万肆仟壹佰贰拾肆亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元整", digitToChinese2);
digitToChinese = Convert.digitToChinese(12_0000_1241_2421L);
Assert.assertEquals("壹拾贰万亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元整", digitToChinese);
String digitToChinese3 = Convert.digitToChinese(2421.02);
Assert.assertEquals("贰仟肆佰贰拾壹元零贰分", digitToChinese3);
digitToChinese = Convert.digitToChinese(12_0000_0000_2421L);
Assert.assertEquals("壹拾贰万亿零贰仟肆佰贰拾壹元整", digitToChinese);
digitToChinese = Convert.digitToChinese(12_4124_1241_2421D);
Assert.assertEquals("壹拾贰万肆仟壹佰贰拾肆亿壹仟贰佰肆拾壹万贰仟肆佰贰拾壹元整", digitToChinese);
digitToChinese = Convert.digitToChinese(2421.02);
Assert.assertEquals("贰仟肆佰贰拾壹元零贰分", digitToChinese);
}
@Test
@ -93,8 +203,8 @@ public class NumberChineseFormatterTest {
digitUppercase = Convert.digitToChinese(a);
Assert.assertEquals("壹仟零贰拾肆元整", digitUppercase);
a = 1024;
digitUppercase = Convert.digitToChinese(a);
double b = 1024;
digitUppercase = Convert.digitToChinese(b);
Assert.assertEquals("壹仟零贰拾肆元整", digitUppercase);
}
@ -108,6 +218,12 @@ public class NumberChineseFormatterTest {
Assert.assertEquals("贰万亿元整", digitToChinese);
}
@Test
public void digitToChineseTest4() {
String digitToChinese = Convert.digitToChinese(400_0000.00);
Assert.assertEquals("肆佰万元整", digitToChinese);
}
@Test
public void numberCharToChineseTest(){
String s = NumberChineseFormatter.numberCharToChinese('1', false);