Java 阿拉伯數(shù)字轉(zhuǎn)漢字
網(wǎng)上看過很多實現(xiàn),但都有 BUG,不是多余0沒有處理,就是很多生成的漢字字符串根本不符合中文閱讀習慣(各位代碼寫完測試的時候用例多搞一點?。?/p>
剛好公司有個項目就要實現(xiàn)這個小功能,顧把自己的實現(xiàn)分享出來
1、結(jié)果示例
看代碼前,先觀察一下結(jié)果是否滿足各位的預期
用例輸入:
int[] nums = {1000, 1024, 10, 100024, 92030003, 90000003, 1, 2, 3, 11};
用例輸出:
一千
一千零二十四
十
十萬零二十四
九千二百零三萬零三
九千萬零三
一
二
三
十一
用例基本能覆蓋所有特殊場景,支持 Integer.MIN_VALUE - Integer.MAX_VALUE
范圍內(nèi)的所有輸入
小數(shù)場景沒做,因為暫時沒這個需要,不過小數(shù)場景要更好做一些,畢竟按照中文閱讀習慣,小數(shù)只要把小數(shù)點后的數(shù)字一一列出來轉(zhuǎn)換為中文字符就行,沒有位數(shù)轉(zhuǎn)換的需求
3.14159 -> 三點一四一五九
有小數(shù)轉(zhuǎn)換需求的同學,只要把整數(shù)部分取出來,用我的代碼轉(zhuǎn)換,小數(shù)部分再寫個簡單的函數(shù)實現(xiàn)即可
可能有人習慣把"二"讀成"兩"的,到時候在代碼里替換字符就行
2、完整代碼
急著用的同學,寫個工具類,直接拷貝過去就能用了
/**
* @ClassName NumStrConvertor
* @Description 阿拉伯數(shù)字轉(zhuǎn)中文
* @Author faro_z
* @Date 2022/12/5 18:07
* @Version 1.0
**/
public class NumStrConvertor {
public static void main(String[] args) {
int[] nums = {1000, 1024, 10, 100024, 92030003, 90000003, 1, 2, 3, 11};
for (int num : nums) {
System.out.println(cnNumConvertor(num));
}
}
/**
* 轉(zhuǎn)換阿拉伯數(shù)字到中文字符
*
* @param num
* @return
*/
public static String cnNumConvertor(int num) {
if (num==0) {
return "零";
}
final String illegalPrefix = "一十";
final String[] units = {"", "萬", "億", "兆"};
String prefix = "";
if (num < 0) {
prefix = "負";
num = -num;
}
String numStr = String.valueOf(num);
final int metaLen = 4;
int r = numStr.length() - 1;
int l = Math.max(0, r - metaLen + 1);
int unitIndex = 0;
StringBuilder builder = new StringBuilder();
while (r >= 0 && l >= 0) {
builder.insert(0, cnNumMetaConvertor(numStr.substring(l, r + 1)) + units[unitIndex++]);
r = l - 1;
l = Math.max(0, r - metaLen + 1);
}
String res = builder.toString();
if (res.startsWith(illegalPrefix)) {
res = res.substring(1, res.length());
}
return prefix + res;
}
/**
* 按照中文閱讀習慣,處理最高4位的 meta 數(shù)字集
*
* @param num
* @return
*/
private static String cnNumMetaConvertor(String num) {
final int metaLen = 4;
final String zeroStr = "0";
final String[] cnNums = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
final String[] units = {"千", "百", "十", ""};
StringBuilder builder = new StringBuilder();
int N = num.length();
boolean canNotJudge = N > metaLen || (N < metaLen && num.startsWith(zeroStr));
if (canNotJudge) {
return "";
}
boolean isPreZero = false;
int unitIndex = metaLen - num.length() - 1;
for (int i = 0; i < N; i++) {
++unitIndex;
final int currNum = num.charAt(i) - '0';
final String currNumCn = cnNums[currNum];
final String currUnit = units[unitIndex];
if (currNum == 0) {
if (isPreZero) {
continue;
}
isPreZero = true;
builder.append(currNumCn);
} else {
isPreZero = false;
builder.append(currNumCn);
builder.append(currUnit);
}
}
String res = builder.toString();
return res.endsWith("零") ? res.substring(0, res.length() - 1) : res;
}
}
3、思路講解
按照中文閱讀習慣,我們習慣將每四位分為一個單元做閱讀,比如如下示例:
因為每四位的處理邏輯都是一樣的,所以這部分我們可以單獨拆出來處理:
private static String cnNumMetaConvertor(String num) {
final int metaLen = 4;
final String zeroStr = "0";
final String[] cnNums = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
final String[] units = {"千", "百", "十", ""};
StringBuilder builder = new StringBuilder();
int N = num.length();
// 大于四位或者 小于四位,但是開頭的數(shù)字為0,都不滿足處理條件
boolean canNotJudge = N > metaLen || (N < metaLen && num.startsWith(zeroStr));
if (canNotJudge) {
return "";
}
// 用來標識前一個字符是否為0,避免出現(xiàn)重復打印“零”的情況
boolean isPreZero = false;
int unitIndex = metaLen - num.length() - 1;
for (int i = 0; i < N; i++) {
++unitIndex;
final int currNum = num.charAt(i) - '0';
final String currNumCn = cnNums[currNum];
final String currUnit = units[unitIndex];
if (currNum == 0) {
if (isPreZero) {
continue;
}
isPreZero = true;
builder.append(currNumCn);
} else {
isPreZero = false;
builder.append(currNumCn);
builder.append(currUnit);
}
}
String res = builder.toString();
return res.endsWith("零") ? res.substring(0, res.length() - 1) : res;
}
}
接著,就是將“每個四位”進行拼接,并依次在后面加上,萬、億、兆的單位:
這里使用雙指針法進行范圍截取,以 4 為單位截取字符串,然后使用上面的函數(shù)處理
cnNumConvertor(num) {
// 負數(shù)和非0判斷
// ...
res=""
while() {
currSplit = split(num)
currSplitCN = cnNumMetaConvertor(currSplit)
res+= currSplitCN + 單位
}
// 特殊字符處理
// ...
return res
}
同時外層函數(shù)我們還要做個負數(shù)和0的判斷
負數(shù)的話,要轉(zhuǎn)換成正數(shù)處理,最后返回結(jié)果時加上"負"的前綴
0 直接返回 “零”
public static String cnNumConvertor(int num) {
if (num==0) {
return "零";
}
final String illegalPrefix = "一十";
final String[] units = {"", "萬", "億", "兆"};
String prefix = "";
if (num < 0) {
prefix = "負";
num = -num;
}
String numStr = String.valueOf(num);
final int metaLen = 4;
int r = numStr.length() - 1;
int l = Math.max(0, r - metaLen + 1);
int unitIndex = 0;
StringBuilder builder = new StringBuilder();
while (r >= 0 && l >= 0) {
builder.insert(0, cnNumMetaConvertor(numStr.substring(l, r + 1)) + units[unitIndex++]);
r = l - 1;
l = Math.max(0, r - metaLen + 1);
}
String res = builder.toString();
// 對一十,一十萬,一十四這類結(jié)果做處理
if (res.startsWith(illegalPrefix)) {
res = res.substring(1, res.length());
}
return prefix + res;
}
特殊結(jié)果處理:
上述代碼本身能完成很好的結(jié)果生成,但是還是有部分結(jié)果不滿足中文閱讀習慣文章來源:http://www.zghlxwxcb.cn/news/detail-704678.html
比如 對一十,一十萬,一十四
這類結(jié)果,只要將前綴的 “一” 去掉即可文章來源地址http://www.zghlxwxcb.cn/news/detail-704678.html
if (res.startsWith(illegalPrefix)) {
res = res.substring(1, res.length());
}
到了這里,關(guān)于【Java】阿拉伯數(shù)字轉(zhuǎn)漢字(完全符合中文閱讀習慣)(支持所有整數(shù)類型)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!