Java數字轉中文大寫工具類詳細代碼(拿去即用)
更新時間:2024年05月20日 09:44:11 作者:UnIQUE?Eason
最近項目中用到金額轉大寫的地方,索性給大家總結下,這篇文章主要給大家介紹了關于Java數字轉中文大寫工具類的相關資料,文中給出了詳細的代碼示例,需要的朋友可以參考下

工具類包括:
- 數字轉中文大寫形式,比如一百二十一
- 數字轉金額用的大寫形式,比如:壹佰貳拾壹
- 轉金額形式,比如:壹佰貳拾壹整
package cn.hutool.core.convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
/**
* 數字轉中文類
**/
public class NumberChineseFormatterUtils {
/**
* 中文形式,奇數位置是簡體,偶數位置是記賬繁體,0共用
* 使用混合數組提高效率和數組復用
**/
private 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),
};
/**
* 阿拉伯數字轉換成中文,小數點后四舍五入保留兩位. 使用于整數、小數的轉換.
*
* @param amount 數字
* @param isUseTraditional 是否使用繁體
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional) {
return format(amount, isUseTraditional, false);
}
/**
* 阿拉伯數字轉換成中文,小數點后四舍五入保留兩位. 使用于整數、小數的轉換.
*
* @param amount 數字
* @param isUseTraditional 是否使用繁體
* @param isMoneyMode 是否為金額模式
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) {
if (amount > 99_9999_9999_9999.99 || amount < -99999999999999.99) {
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);
final int numFen = (int) (temp % 10);
temp = temp / 10;
final int numJiao = (int) (temp % 10);
temp = temp / 10;
final StringBuilder chineseStr = new StringBuilder(longToChinese(temp, isUseTraditional));
//負數
if (negative) { // 整數部分不為 0
chineseStr.insert(0, "負");
}
// 小數部分
if (numFen != 0 || numJiao != 0) {
if (numFen == 0) {
chineseStr.append(isMoneyMode ? "元" : "點").append(numberToChinese(numJiao, isUseTraditional)).append(isMoneyMode ? "角" : "");
} else { // “分”數不為 0
if (numJiao == 0) {
chineseStr.append(isMoneyMode ? "元零" : "點零").append(numberToChinese(numFen, isUseTraditional)).append(isMoneyMode ? "分" : "");
} else {
chineseStr.append(isMoneyMode ? "元" : "點").append(numberToChinese(numJiao, isUseTraditional)).append(isMoneyMode ? "角" : "").append(numberToChinese(numFen, isUseTraditional)).append(isMoneyMode ? "分" : "");
}
}
} else if (isMoneyMode) {
//無小數部分的金額結尾
chineseStr.append("元整");
}
return chineseStr.toString();
}
/**
* 數字字符轉中文,非數字字符原樣返回
*
* @param c 數字字符
* @param isUseTraditional 是否繁體
* @return 中文字符
* @since 5.3.9
*/
public static String numberCharToChinese(char c, boolean isUseTraditional) {
if (c < '0' || c > '9') {
return String.valueOf(c);
}
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 則返回 ""
*
* @param amountPart 數字部分
* @param isUseTraditional 是否使用繁體單位
* @return 轉換后的漢字
*/
private static String thousandToChinese(int amountPart, boolean isUseTraditional) {
int temp = amountPart;
StringBuilder chineseStr = new StringBuilder();
boolean lastIsZero = true; // 在從低位往高位循環(huán)時,記錄上一位數字是不是 0
for (int i = 0; temp > 0; i++) {
int digit = temp % 10;
if (digit == 0) { // 取到的數字為 0
if (false == lastIsZero) {
// 前一個數字不是 0,則在當前漢字串前加“零”字;
chineseStr.insert(0, "零");
}
lastIsZero = true;
} else { // 取到的數字不是 0
chineseStr.insert(0, numberToChinese(digit, isUseTraditional) + getUnitName(i, isUseTraditional));
lastIsZero = false;
}
temp = temp / 10;
}
return chineseStr.toString();
}
/**
* 把中文轉換為數字 如 二百二十 220
*
* 一百一十二 -》 112
* 一千零一十二 -》 1012
*
* @param chinese 中文字符
* @return 數字
*/
public static int chineseToNumber(String chinese) {
final int length = chinese.length();
int result = 0;
// 節(jié)總和
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) {
// 遇到零時節(jié)結束,權位失效,比如兩萬二零一十
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) {
// 節(jié)單位,按照節(jié)求和
section = (section + number) * unit.value;
result += section;
section = 0;
} else {
// 非節(jié)單位,和單位前的單數字組合為值
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;
}
/**
* 查找對應的權對象
*
* @param chinese 中文權位名
* @return 權對象
*/
private static ChineseUnit chineseToUnit(char chinese) {
for (ChineseUnit chineseNameValue : CHINESE_NAME_VALUE) {
if (chineseNameValue.name == chinese) {
return chineseNameValue;
}
}
return null;
}
/**
* 將漢字單個數字轉換為int類型數字
*
* @param chinese 漢字數字,支持簡體和繁體
* @return 數字,-1表示未找到
*/
private static int chineseToNumber(char chinese) {
if ('兩' == chinese) {
// 口語糾正
chinese = '二';
}
final int i = ArrayUtil.indexOf(DIGITS, chinese);
if (i > 0) {
return (i + 1) / 2;
}
return i;
}
/**
* 單個數字轉漢字
*
* @param number 數字
* @param isUseTraditional 是否使用繁體
* @return 漢字
*/
private static char numberToChinese(int number, boolean isUseTraditional) {
if (0 == number) {
return DIGITS[0];
}
return DIGITS[number * 2 - (isUseTraditional ? 0 : 1)];
}
/**
* 獲取對應級別的單位
*
* @param index 級別,0表示各位,1表示十位,2表示百位,以此類推
* @param isUseTraditional 是否使用繁體
* @return 單位
*/
private static String getUnitName(int index, boolean isUseTraditional) {
if (0 == index) {
return StrUtil.EMPTY;
}
return String.valueOf(CHINESE_NAME_VALUE[index * 2 - (isUseTraditional ? 0 : 1)].name);
}
/**
* 權位
*/
private static class ChineseUnit {
/**
* 中文權名稱
*/
private final char name;
/**
* 10的倍數值
*/
private final int value;
/**
* 是否為節(jié)權位,它不是與之相鄰的數字的倍數,而是整個小節(jié)的倍數。
* 例如二十三萬,萬是節(jié)權位,與三無關,而和二十三關聯
*/
private final boolean secUnit;
/**
* 構造
*
* @param name 名稱
* @param value 值,即10的倍數
* @param secUnit 是否為節(jié)權位
*/
public ChineseUnit(char name, int value, boolean secUnit) {
this.name = name;
this.value = value;
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, '零');
}
}
}注意:以上代碼用到hutool工具,需要引入依賴:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>附:數字轉換
// 數字轉英文
double a = 23.56;
// TWENTY THREE AND CENTS FIFTY SIX ONLY
String a1 = Convert.numberToWord(a);
// 數字轉中文
long b = 345673;
// 跟Convert.digitToChinese方法一樣,第二個參數如果設為false,就是中文的一二三四...
String s = Convert.numberToChinese(b, true);
// 數字簡化
long b = 345673;
// 34.57w
String s = Convert.numberToSimple(b);
log.info(s);
// 1.2k
String s1 = Convert.numberToSimple(1200);
log.info(s1);
// 中文數字轉數字
// 1012
int b = Convert.chineseToNumber("一千零一十二");
log.info(b + "");
總結
到此這篇關于Java數字轉中文大寫工具類的文章就介紹到這了,更多相關Java數字轉中文大寫工具類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
idea創(chuàng)建properties文件,解決亂碼問題
這篇文章主要介紹了idea創(chuàng)建properties文件,解決亂碼問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
spring mvc常用注解_動力節(jié)點Java學院整理
這篇文章主要介紹了spring mvc常用注解,詳細的介紹了@RequestMapping, @RequestParam, @ModelAttribute等等這樣類似的注解,有興趣的可以了解一下2017-08-08
MybatisPlusInterceptor實現sql攔截器超詳細教程
這篇文章主要給大家介紹了關于MybatisPlusInterceptor實現sql攔截器超詳細教程的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08
關于SpringBoot中controller參數校驗的使用
本文主要介紹了關于SpringBoot中controller參數校驗的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01

