|
|
@@ -15,113 +15,177 @@
|
|
|
*/
|
|
|
package com.java110.utils.util;
|
|
|
|
|
|
-import java.math.BigDecimal;
|
|
|
-
|
|
|
/**
|
|
|
* @desc add by 吴学文 17:14
|
|
|
*/
|
|
|
public class Money2ChineseUtil {
|
|
|
- /*
|
|
|
-eg:640 409 329
|
|
|
- 987 654 321 //对应的坐标
|
|
|
-
|
|
|
- &&& &&& &&& //替换成对应的字符 (如果是0加上标记)
|
|
|
- --- --- --- //每位修辞符常量
|
|
|
- * //每隔5位数字修辞符常量
|
|
|
-
|
|
|
-*/
|
|
|
- //数字转中文常量
|
|
|
- private final static String[] C_N = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
|
|
|
- //每隔5位数字修辞符常量
|
|
|
- private final static String[] C_F = {"", "万", "亿", "兆", "吉", "太", "拍", "艾"};
|
|
|
- //对应的每位修辞符常量
|
|
|
- private final static String[] C_S = {"", "拾", "佰", "仟"};
|
|
|
- private final static String[] CNY = {"元", "角", "分", "毫", "厘"};
|
|
|
- //"-"
|
|
|
- private final static String negative = "负";
|
|
|
- //"+"
|
|
|
- private final static String positive = "";
|
|
|
+ // 大写数字
|
|
|
+ private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
|
|
|
+ // 整数部分的单位
|
|
|
+ private static final String[] IUNIT = {"元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟"};
|
|
|
+ // 小数部分的单位
|
|
|
+ private static final String[] DUNIT = {"角", "分", "厘"};
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
- * 将整数转换成对应的中文字符串
|
|
|
+ * 转换为大写的中文金额
|
|
|
*
|
|
|
- * @param l
|
|
|
- * @return StringBuffed
|
|
|
+ * @param price 字符串类型的 金额数字
|
|
|
+ * @return
|
|
|
*/
|
|
|
- public static String toChineseChar(long l) {
|
|
|
- //定义变量保存中文字符串
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- //将阿拉伯数字转换为无符号的字符串数组
|
|
|
- char[] ch = (Math.abs(l) + "").toCharArray();
|
|
|
- //加上符号
|
|
|
- sb.append(l < 0 ? negative : positive);
|
|
|
- //定义一个标记,判断该数位前面是否有'0'
|
|
|
- boolean beforeHaveZore = false;
|
|
|
- //遍历中文字符串
|
|
|
- for (int i = 0, j = ch.length - 1; i < ch.length; i++, j--) {
|
|
|
- //如果首位是1且是十位就不用加'壹'了:eg 15 拾伍 150213 拾伍万零贰佰壹叁 150013 拾伍万零壹拾叁 拾亿零壹拾万/拾亿零拾万
|
|
|
- if (i == 0 && ch[i] - 48 == 1 && j % 4 == 1) {
|
|
|
- sb.append(C_S[1]);
|
|
|
- //判断这个数字是否为0且它前面没有0
|
|
|
- } else if (ch[i] != 48 && !beforeHaveZore)
|
|
|
- //中文常量 + 对应的每位修辞符常量 + 每隔4位数字修辞符常量
|
|
|
- sb.append(C_N[ch[i] - 48] + C_S[j % 4] + C_F[j % 4 == 0 ? j / 4 : 0]);
|
|
|
- //判断这个数字是否为0且它前面有0
|
|
|
- else if (ch[i] != 48 && beforeHaveZore) {
|
|
|
- //中文常量"零"+中文常量+对应的每位修辞符常量+每隔4位数字修辞符常量
|
|
|
- sb.append(C_N[0] + C_N[ch[i] - 48] + C_S[j % 4] + C_F[j % 4 == 0 ? j / 4 : 0]);
|
|
|
- //消出标记
|
|
|
- beforeHaveZore = false;
|
|
|
- //这个数字是0
|
|
|
- } else {
|
|
|
- //如果这个数的位置不是第5位?标记:不标记
|
|
|
- beforeHaveZore = beforeHaveZore || j % 4 != 0;
|
|
|
- //每隔5位数字修辞符常量 eg: 50000 伍万
|
|
|
- sb.append(C_F[j % 4 == 0 ? j / 4 : 0]);
|
|
|
- }
|
|
|
+ public static String toChineseChar(double price) {
|
|
|
+ // 判断输入的金额字符串是否符合要求
|
|
|
+ String str = price + "";
|
|
|
+ if (StringUtil.isEmpty(str) || !str.matches("(-)?[\\d]*(.)?[\\d]*")) {
|
|
|
+ return "抱歉,请输入数字!";
|
|
|
+ }
|
|
|
+
|
|
|
+ if ("0".equals(str) || "0.00".equals(str) || "0.0".equals(str)) {
|
|
|
+ return "零元";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断金额数字中是否存在负号"-"
|
|
|
+ boolean flag = false;
|
|
|
+ if (str.startsWith("-")) {
|
|
|
+ // 标志位,标志此金额数字为负数
|
|
|
+ flag = true;
|
|
|
+ str = str.replaceAll("-", "");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 去掉金额数字中的逗号","
|
|
|
+ str = str.replaceAll(",", "");
|
|
|
+ String integerStr;//整数部分数字
|
|
|
+ String decimalStr;//小数部分数字
|
|
|
+
|
|
|
+ // 初始化:分离整数部分和小数部分
|
|
|
+ if (str.indexOf(".") > 0) {
|
|
|
+ integerStr = str.substring(0, str.indexOf("."));
|
|
|
+ decimalStr = str.substring(str.indexOf(".") + 1);
|
|
|
+ } else if (str.indexOf(".") == 0) {
|
|
|
+ integerStr = "";
|
|
|
+ decimalStr = str.substring(1);
|
|
|
+ } else {
|
|
|
+ integerStr = str;
|
|
|
+ decimalStr = "";
|
|
|
+ }
|
|
|
+
|
|
|
+ // beyond超出计算能力,直接返回
|
|
|
+ if (integerStr.length() > IUNIT.length) {
|
|
|
+ return "超出计算能力!";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 整数部分数字
|
|
|
+ int[] integers = toIntArray(integerStr);
|
|
|
+ // 判断整数部分是否存在输入012的情况
|
|
|
+ if (integers.length > 1 && integers[0] == 0) {
|
|
|
+ return "抱歉,输入数字不符合要求!";
|
|
|
+ }
|
|
|
+ // 设置万单位
|
|
|
+ boolean isWan = isWan5(integerStr);
|
|
|
+ // 小数部分数字
|
|
|
+ int[] decimals = toIntArray(decimalStr);
|
|
|
+ // 返回最终的大写金额
|
|
|
+ String result = getChineseInteger(integers, isWan) + getChineseDecimal(decimals);
|
|
|
+ if (flag) {
|
|
|
+ // 如果是负数,加上"负"
|
|
|
+ return "负" + result;
|
|
|
+ } else {
|
|
|
+ return result;
|
|
|
}
|
|
|
- return sb.toString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * To CNY
|
|
|
+ * 将字符串转为int数组
|
|
|
*
|
|
|
- * @param d
|
|
|
+ * @param number 数字
|
|
|
* @return
|
|
|
*/
|
|
|
- public static String toChineseCNY(Double d) {
|
|
|
- long l = d.longValue();
|
|
|
- if (d - l == 0) {
|
|
|
- return toChineseChar(l) + CNY[0] + "整";
|
|
|
+ private static int[] toIntArray(String number) {
|
|
|
+ int[] array = new int[number.length()];
|
|
|
+ for (int i = 0; i < number.length(); i++) {
|
|
|
+ array[i] = Integer.parseInt(number.substring(i, i + 1));
|
|
|
}
|
|
|
- String s = (d + "").split("\\.")[1];
|
|
|
-
|
|
|
- StringBuffer sb = new StringBuffer(s.length() * 2);
|
|
|
- int i = 1;
|
|
|
- for (char c : s.toCharArray()) {
|
|
|
- if (c - 48 == 0) {
|
|
|
- i++;
|
|
|
- continue;
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将整数部分转为大写的金额
|
|
|
+ *
|
|
|
+ * @param integers 整数部分数字
|
|
|
+ * @param isWan 整数部分是否已经是达到【万】
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String getChineseInteger(int[] integers, boolean isWan) {
|
|
|
+ StringBuffer chineseInteger = new StringBuffer("");
|
|
|
+ int length = integers.length;
|
|
|
+ if (length == 1 && integers[0] == 0) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
+ String key = "";
|
|
|
+ if (integers[i] == 0) {
|
|
|
+ if ((length - i) == 13)//万(亿)
|
|
|
+ key = IUNIT[4];
|
|
|
+ else if ((length - i) == 9) {//亿
|
|
|
+ key = IUNIT[8];
|
|
|
+ } else if ((length - i) == 5 && isWan) {//万
|
|
|
+ key = IUNIT[4];
|
|
|
+ } else if ((length - i) == 1) {//元
|
|
|
+ key = IUNIT[0];
|
|
|
+ }
|
|
|
+ if ((length - i) > 1 && integers[i + 1] != 0) {
|
|
|
+ key += NUMBERS[0];
|
|
|
+ }
|
|
|
}
|
|
|
- sb.append(C_N[c - 48] + CNY[i++]);
|
|
|
- if (CNY.length == i) {
|
|
|
+ chineseInteger.append(integers[i] == 0 ? key : (NUMBERS[integers[i]] + IUNIT[length - i - 1]));
|
|
|
+ }
|
|
|
+ return chineseInteger.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将小数部分转为大写的金额
|
|
|
+ *
|
|
|
+ * @param decimals 小数部分的数字
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static String getChineseDecimal(int[] decimals) {
|
|
|
+ StringBuffer chineseDecimal = new StringBuffer("");
|
|
|
+ for (int i = 0; i < decimals.length; i++) {
|
|
|
+ if (i == 3) {
|
|
|
break;
|
|
|
}
|
|
|
+ chineseDecimal.append(decimals[i] == 0 ? "" : (NUMBERS[decimals[i]] + DUNIT[i]));
|
|
|
}
|
|
|
- return toChineseChar(l) + CNY[0] + sb;
|
|
|
+ return chineseDecimal.toString();
|
|
|
}
|
|
|
|
|
|
- public static String toChineseChar(Double d) {
|
|
|
- long l = d.longValue();
|
|
|
- if (d - l == 0) {
|
|
|
- return toChineseChar(l);
|
|
|
- }
|
|
|
- String s = (BigDecimal.valueOf(d).toPlainString()).split("\\.")[1];
|
|
|
- StringBuffer sb = new StringBuffer(s.length());
|
|
|
- sb.append("点");
|
|
|
- for (char c : s.toCharArray()) {
|
|
|
- sb.append(C_N[c - 48]);
|
|
|
+ /**
|
|
|
+ * 判断当前整数部分是否已经是达到【万】
|
|
|
+ *
|
|
|
+ * @param integerStr 整数部分数字
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static boolean isWan5(String integerStr) {
|
|
|
+ int length = integerStr.length();
|
|
|
+ if (length > 4) {
|
|
|
+ String subInteger = "";
|
|
|
+ if (length > 8) {
|
|
|
+ subInteger = integerStr.substring(length - 8, length - 4);
|
|
|
+ } else {
|
|
|
+ subInteger = integerStr.substring(0, length - 4);
|
|
|
+ }
|
|
|
+ return Integer.parseInt(subInteger) > 0;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
}
|
|
|
- return toChineseChar(l) + sb;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Test
|
|
|
+ public static void main(String[] args) {
|
|
|
+ double number = 3462.98;
|
|
|
+ System.out.println(number + ": " + toChineseChar(number));
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
}
|