网上很多算法都是到亿就gg了,目前的算法能到大数,什么是大数?来张图了解下
算法可以到1000大数,也就是10的75次方,不过一般京以上是用不到了
有个细节,105000是读十万五千,还是十万零五千,网上查了一些资料,还是读十万零五千的规范一些
System.out.println(NumberUtil.numberToChinese("1024"));
结果:
Integer.MAX_VALUE都不想演示了,直接Long.MAX_VALUE
System.out.println(NumberUtil.numberToChinese(Long.MAX_VALUE));
结果:
System.out.println(NumberUtil.numberToMoney("105000"));
结果:
注意:最多只能有2位小数点
System.out.println(NumberUtil.numberToMoney("0.61"));
System.out.println(NumberUtil.numberToMoney("1024.00"));
System.out.println(NumberUtil.numberToMoney(1024.06));
结果:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 数字转换工具
*
* @author 猴哥
*/
public class NumberUtil {
/**
* 数字转中文
*
* @param number 数字
* @return 中文
*/
public static String numberToChinese(String number) {
return numberToChinese(number, false);
}
/**
* 数字转中文
*
* @param number 数字
* @return 中文
*/
public static String numberToChinese(long number) {
return numberToChinese(String.valueOf(number));
}
/**
* 数字转中文
*
* @param number 数字
* @return 中文
*/
public static String numberToChinese(int number) {
return numberToChinese(String.valueOf(number));
}
/**
* 数字转中文
*
* @param number 数字
* @return 中文
*/
public static String numberToChinese(BigInteger number) {
return numberToChinese(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(String number) {
return numberToChinese(number, true);
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(float number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(double number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(int number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(long number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(BigInteger number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转金钱
*
* @param number 数字
* @return 金钱
*/
public static String numberToMoney(BigDecimal number) {
return numberToMoney(String.valueOf(number));
}
/**
* 数字转中文
*
* @param number 数字
* @param money 是否是金钱模式
* @return 中文
*/
private static String numberToChinese(String number, boolean money) {
// 单位
final List units = Arrays.asList("万", "亿", "兆", "京", "垓", "杼", "穰", "沟", "涧", "正", "载", "极",
"恒河沙", "阿僧祇", "那由它", "不可思议", "无量", "大数");
// 数字转中文
List chineseList = Arrays.asList("", "一", "二", "三", "四", "五", "六", "七", "八", "九");
// 位数单位
List digitList = Arrays.asList("", "十", "百", "千");
// 字符串校验
Optional.ofNullable(number).orElseThrow(() -> new RuntimeException("内容不能为空"));
// 如果是金钱模式
if (money) {
chineseList = Arrays.asList("", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖");
digitList = Arrays.asList("", "拾", "佰", "仟");
// 校验金钱
if (!number.matches("^\\d+(.\\d{1,2})?$")) {
throw new RuntimeException("不符合金钱格式");
}
} else if (!number.matches("^\\d+$")) {
throw new RuntimeException("请输入自然数");
}
// 封装对象(每个字符给它一个对象)
List chineseChars = new LinkedList<>();
// 小数部分
LinkedList decimals = new LinkedList<>();
boolean isDecimal = false;
char[] charArray = number.toCharArray();
for (int i = 0; i < charArray.length; i++) {
// 如果遇到小数点
if (charArray[i] == '.') {
isDecimal = true;
continue;
}
ChineseChar chineseChar = new ChineseChar();
// 数字
chineseChar.setNumber(Integer.parseInt(charArray[i] + ""));
// 中文字符
chineseChar.setChinese(chineseList.get(chineseChar.getNumber()));
// 从右往左第几位
chineseChar.setDigit(charArray.length - i);
// 单位
chineseChar.setDigitName(digitList.get((chineseChar.getDigit() + 3) % 4));
// 如果是小数
if (isDecimal) {
// 添加到小数位
decimals.add(chineseChar);
} else {
chineseChars.add(chineseChar);
}
}
// 金钱模式如果有小数位,需要重新计算位数
if (money && isDecimal) {
for (int i = 0; i < chineseChars.size(); i++) {
ChineseChar chineseChar = chineseChars.get(i);
chineseChar.setDigit(chineseChars.size() - i);
chineseChar.setDigitName(digitList.get((chineseChar.getDigit() + 3) % 4));
}
}
for (int i = 0; i < chineseChars.size(); i++) {
ChineseChar chineseChar = chineseChars.get(i);
// 常规
chineseChar.setResult(chineseChar.getChinese() + chineseChar.getDigitName());
// 处理为0的数字
if (chineseChar.getNumber() == 0) {
chineseChar.setResult("");
}
// 处理十位、十万位、十亿位等等
if (chineseChar.getDigit() % 4 == 2) {
if (chineseChar.getNumber() == 1 && chineseChars.size() == chineseChar.getDigit()) {
chineseChar.setResult(chineseChar.getDigitName());
}
}
}
// 补零
for (int i = chineseChars.size() - 1; i >= 0; i--) {
ChineseChar chineseChar = chineseChars.get(i);
// 如果遇到0
if (chineseChar.getNumber() == 0) {
chineseChar.setResult("零");
// 前面的零全部忽略
for (int j = i - 1; j >= 0 && chineseChars.get(j).getNumber() == 0; j--) {
i = j;
}
}
}
// 去掉结尾的零
for (int i = chineseChars.size() - 1; i >= 0 && chineseChars.get(i).getNumber() == 0; i--) {
chineseChars.get(i).setResult("");
}
// 遍历每个字符,加上计量单位
for (int i = 0; i < chineseChars.size(); i++) {
ChineseChar chineseChar = chineseChars.get(i);
// 遍历计量单位
for (int j = 0; j < units.size(); j++) {
String unit = units.get(j);
// 如果当前的位数刚好是计量单位的位数
if (chineseChar.getDigit() == (j + 1) * 4 + 1) {
// 如果是前4位,则加上单位
// 如果这块区域有值,也加上单位
if (i < 4
|| chineseChars.get(i - 1).getNumber() != 0
|| chineseChars.get(i - 2).getNumber() != 0
|| chineseChars.get(i - 3).getNumber() != 0) {
// 把计量单位加上去
chineseChar.setResult(chineseChar.getNumber() == 0 ? unit + chineseChar.getResult() : chineseChar.getResult() + unit);
}
break;
}
}
}
String result = chineseChars.stream()
.map(ChineseChar::getResult)
.collect(Collectors.joining(""));
// 判断是否为0
result = zero(result, chineseChars);
// 如果是金钱
if (money) {
return moneyHandler(result, decimals);
}
return result;
}
/**
* 判断是否为零
*
* @param result 结果
* @param chineseChars 中文
* @return 中文
*/
private static String zero(String result, List chineseChars) {
boolean isZero = chineseChars.stream().allMatch(chineseChar -> chineseChar.getNumber() == 0);
return isZero ? "零" : result;
}
/**
* 处理金钱的小数部分
*
* @param result 整数处理结果
* @param decimals 金钱小数位
* @return 处理结果
*/
private static String moneyHandler(String result, LinkedList decimals) {
result += "元";
// 如果没有小数位
if (decimals.isEmpty()) {
result += "整";
return result;
}
// 处理角
ChineseChar jiao = decimals.pop();
result += jiao.getNumber() == 0 ? "" : jiao.getChinese() + "角";
// 处理分
ChineseChar fen = null;
if (!decimals.isEmpty() && (fen = decimals.removeFirst()) != null && fen.getNumber() != 0) {
result += jiao.getNumber() == 0 ? "零" + fen.getChinese() + "分" : fen.getChinese() + "分";
}
// 如果是.0或者.00
if (jiao.getNumber() == 0 && (fen == null || fen.getNumber() == 0)) {
result += "整";
}
return result;
}
/**
* 字符对象
*/
static class ChineseChar {
/**
* 数字
*/
private Integer number;
/**
* 中文
*/
private String chinese;
/**
* 位数
*/
private Integer digit;
/**
* 位数名称
*/
private String digitName;
/**
* 结果
*/
private String result;
public String getChinese() {
return chinese;
}
public void setChinese(String chinese) {
this.chinese = chinese;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public Integer getDigit() {
return digit;
}
public void setDigit(Integer digit) {
this.digit = digit;
}
public String getDigitName() {
return digitName;
}
public void setDigitName(String digitName) {
this.digitName = digitName;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
@Override
public String toString() {
return "ChineseChar{" +
"number=" + number +
", chinese='" + chinese + '\'' +
", digit=" + digit +
", digitName='" + digitName + '\'' +
", result='" + result + '\'' +
'}';
}
}
}