工具类
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* 金额处理工具类
*
* @author zql
* @version 1.0
* @createTime 2023-05-14 16:31:00
* @modifyLog
*/
public class MoneyUtil {
private MoneyUtil() {}
private static String MODULUS = "10000";
/**
* Double类型需要进行格式化,否则会出现科学计数法
*/
private static DecimalFormat DF = new DecimalFormat("###################.0000000");
/**
* 元转万元(默认四舍五入保留6位小数)
* @param amt
* @return
*/
public static BigDecimal toTenThousand(String amt) {
if (isNotNumber(amt)) {
return BigDecimal.ZERO;
}
return toTenThousand(new BigDecimal(amt));
}
/**
* 元转万元(默认四舍五入保留6位小数)
* @param amt 不推荐用Double存金额,数值过大会导致精度丢失
* @return
*/
public static BigDecimal toTenThousand(Double amt) {
if (Objects.isNull(amt)) {
return BigDecimal.ZERO;
}
String amtStr = String.valueOf(DF.format(amt));
return toTenThousand(amtStr);
}
/**
* 元转万元(默认四舍五入保留6位小数)
* @param amt
* @return
*/
public static BigDecimal toTenThousand(BigDecimal amt) {
return amt.divide(new BigDecimal(MODULUS)).setScale(6, BigDecimal.ROUND_HALF_UP);
}
/**
* 万元转元(默认四舍五入保留2位小数)
* @param amt
* @return
*/
public static BigDecimal toTheUnit(String amt) {
if (isNotNumber(amt)) {
return BigDecimal.ZERO;
}
return toTheUnit(new BigDecimal(amt));
}
/**
* 万元转元(默认四舍五入保留2位小数)
* @param amt 不推荐用Double存金额,数值过大会导致精度丢失
* @return
*/
public static BigDecimal toTheUnit(Double amt) {
if (Objects.isNull(amt)) {
return BigDecimal.ZERO;
}
String amtStr = String.valueOf(DF.format(amt));
return toTheUnit(amtStr);
}
/**
* 万元转元(默认四舍五入保留2位小数)
* @param amt
* @return
*/
public static BigDecimal toTheUnit(BigDecimal amt) {
return amt.multiply(new BigDecimal(MODULUS)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
/**
* 数字 + 中文金额转纯金额,单位元(例:500万元,输出结果5000000)
* @param str
* @return
*/
public static BigDecimal getMoney(String str) {
StringBuffer sb = new StringBuffer();
if(isNotBlank(str)){
for(int i = 0; i < str.length(); i++){
// 46是小数点 (.)
if(str.charAt(i) >= 48 && str.charAt(i) <= 57 || str.charAt(i) == 46){
sb.append(str.charAt(i));
}
}
}
String res = sb.toString();
if (isNotBlank(res) && str.contains(UNIT_ARR[7])) {
return toTheUnit(res);
}
if (isNotBlank(res) && str.contains(UNIT_ARR[8])) {
return new BigDecimal(res).multiply(getUnit(8));
}
if (isNotBlank(res)) {
return new BigDecimal(res);
}
return BigDecimal.ZERO;
}
/**
* 对某个数保留小数位数的
* @author zql
* @createTime 2020-12-05 16:26:02
*
* @param num 某个数
* @param type 类型,1四舍五入,2五舍六入,3进位处理(就是直接加1),4直接去掉尾数
* <pre>
* type = 2,五舍六入时,需要看要求精度后面的第二位(如果存在)是否大于等于5,如果是则会进位
* </pre>
* @param count 要保留的小数位数
* @return 返回double类型的结果
* <pre>
* 如果num不是数字时,返回0
* 如果不处于类型内,则默认四舍五入
* 如果count小于1时,默认为保留两位小数
* </pre>
*
*/
public static BigDecimal getBigDecimal(String num, int type, int count) {
if (isNotNumber(num)) {
return BigDecimal.ZERO;
}
if (type < 1 || type > 4) {
type = 1;
}
if (count < 1) {
count = 2;
}
BigDecimal b = new BigDecimal(num);
BigDecimal r;
switch (type) {
case 1:
// 四舍五入
r = b.setScale(count, BigDecimal.ROUND_HALF_UP);
break;
case 2:
// 五舍六入,需要看要求精度后面的第二位(如果存在)是否大于等于5,如果是则会进位
r = b.setScale(count, BigDecimal.ROUND_HALF_DOWN);
break;
case 3:
// 进位处理(就是直接加1)
r = b.setScale(count, BigDecimal.ROUND_UP);
break;
case 4:
// 直接去掉尾数
r = b.setScale(count, BigDecimal.ROUND_DOWN);
break;
default:
r = BigDecimal.ZERO;
}
return r;
}
/**
* 将大写金额转化为数字金额
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param cnStr 大写金额
* @return
* @throws Exception
*/
public static BigDecimal cnToNum(String cnStr) {
if (isBlank(cnStr)) {
return BigDecimal.ZERO;
}
cnStr = cnStr.replace("元", "圆");
// 兆级处理
if (cnStr.indexOf(UNIT_ARR[9]) != -1) {
return cnToNum1(cnStr);
} else if (cnStr.indexOf(UNIT_ARR[8]) != -1) {// 亿级处理
return cnToNum2(cnStr);
} else if (cnStr.indexOf(UNIT_ARR[7]) != -1) {// 万级处理
return cnToNum3(cnStr);
} else {// 低于万级处理
return cnToNum4(cnStr);
}
}
/**
* 兆级处理
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param cnStr 大写金额
* @return
* @throws Exception
*/
private static BigDecimal cnToNum1(String cnStr) {
String prefix = cnStr.substring(0, cnStr.indexOf(UNIT_ARR[9]));
BigDecimal preB = cnToNum4(prefix).multiply(getUnit(9));
String suffix = cnStr.substring(cnStr.indexOf(UNIT_ARR[9]) + 1, cnStr.length());
BigDecimal suffB = cnToNum2(suffix);
return preB.add(suffB);
}
/**
* 亿级处理
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param cnStr 大写金额
* @return
* @throws Exception
*/
private static BigDecimal cnToNum2(String cnStr) {
String prefix = cnStr.substring(0, cnStr.indexOf(UNIT_ARR[8]));
BigDecimal res = cnToNum4(prefix);
BigDecimal preB = res.multiply(getUnit(8));
String suffix = cnStr.substring(cnStr.indexOf(UNIT_ARR[8]) + 1, cnStr.length());
BigDecimal suffB = cnToNum3(suffix);
return preB.add(suffB);
}
/**
* 万级处理
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param cnStr 大写金额
* @return
* @throws Exception
*/
private static BigDecimal cnToNum3(String cnStr) {
String prefix = cnStr.substring(0, cnStr.indexOf(UNIT_ARR[7]));
BigDecimal res = cnToNum4(prefix);
BigDecimal preB = res.multiply(getUnit(7));
String suffix = cnStr.substring(cnStr.indexOf(UNIT_ARR[7]) + 1, cnStr.length());
BigDecimal suffB = cnToNum4(suffix);
return preB.add(suffB);
}
/**
* 低于万级处理
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param cnStr 大写金额
* @return
* @throws Exception
*/
private static BigDecimal cnToNum4(String cnStr) {
BigDecimal result = BigDecimal.ZERO;
int lastUnitIndex = 0, num = 0;
for (int i = 0; i < cnStr.length(); i++) {
boolean isUnit = true;
char c = cnStr.charAt(i);
for (int j = 0; j < NUM_CN.length; j++) {
// 是数字
if (c == NUM_CN[j].charAt(0)) {
// 数字值 = 索引
num = j;
isUnit = false;
break;
}
}
if (isUnit) {
// 第一个就是单位,如:拾伍万圆整
if (i == 0) {
num = 1;
}
int unitIndex = getUnitIndex(c);
BigDecimal unit = getUnit(unitIndex);
// 大写乘单位的结果
BigDecimal unitSource = new BigDecimal(num).multiply(unit);
if (unitIndex > lastUnitIndex) {
result = result.add(new BigDecimal(num)).multiply(unit);
} else {
result = result.add(unitSource);
}
lastUnitIndex = unitIndex;
num = 0;
} else if (i == (cnStr.length() - 1)) {// 最后一位处理
result = result.add(new BigDecimal(num));
}
}
return result.setScale(3, BigDecimal.ROUND_DOWN);
}
/**
* 将数字金额转化为大写金额
* @author zql
* @createTime 2020-11-15 21:53:26
* @version 1.0
*
* @param amount
* @return
* @throws Exception
*/
public static String toBigAmt(String amount) throws Exception {
if (isBlank(amount)) {
throw new Exception("输入的金额为空!");
}
if (isNotNumber(amount)) {
throw new Exception("输入的金额【" + amount + "】不是数字!" );
}
// 四舍五入
String amt = new BigDecimal(amount).setScale(3, BigDecimal.ROUND_HALF_UP).toString();
// 取小数位
String dotPart = "";
// 取整数位
String intPart = "";
// 结果
String result = null;
int dotPos;
if ((dotPos = amt.indexOf(".")) != -1) {
intPart = amt.substring(0, dotPos);
dotPart = amt.substring(dotPos + 1);
} else {
intPart = amt;
}
if (intPart.length() > 16) {
throw new Exception("金额太大【" + amount + "】,无法转换成大写金额!");
}
String intBig = intToBig(intPart);
String dotBig = dotToBig(dotPart);
if (dotBig.length() == 0 && intBig.length() != 0) {
result = intBig + "元整";
} else if (dotBig.length() == 0 && intBig.length() == 0) {
result = intBig + "零元";
} else if (dotBig.length() != 0 && intBig.length() != 0) {
result = intBig + "元" + dotBig;
} else {
result = dotBig;
}
return result;
}
/**
* 阿拉伯对应中文
*/
private static String[] NUM_CN = new String[]{"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
/**
* 单位
*/
private static String[] UNIT_ARR = new String[]{"厘", "分", "角", "圆", "拾", "佰", "仟", "万", "亿", "兆"};
/**
* 用来处理整数部分
* @author zql
* @createTime 2020-11-15 21:25:44
* @version 1.0
*
* @param intPart
* @return
*/
private static String intToBig(String intPart) {
int grade = 4;
// 级长
int gradeLen;
String result = "";
String strTmp = "";
// 得到当前级长
gradeLen = intPart.length() / grade;
// 调整级次长度
if (intPart.length() % grade != 0) {
gradeLen += 1;
}
for (int i = gradeLen; i >= 1; i--) {
// 取得当前级次数字
strTmp = getNowGradeVal(intPart, i);
// 转换大写
result += getSubUnit(strTmp);
// 除零 去掉连续的零
result = dropZero(result);
// 加级次单位,末位不加单位
if (i > 1) {
// 单位不能相连续,连续4个零要特殊处理
if ("零零零零".equals(getSubUnit(strTmp))) {
result += "零";
} else {
result += UNIT_ARR[6 + (i - 1)];
}
}
}
return result;
}
/**
* 删除“零”
* @author zql
* @createTime 2020-11-28 01:31:31
* @version 1.0
*
* @param val
* @return
*/
private static String dropZero(String val) {
// 结果
String rst;
// 前一位置字符
String before;
// 当前位置字符
String now;
before = val.substring(0, 1);
rst = before;
for (int i = 1; i < val.length(); i++) {
now = val.substring(i, i + 1);
// 不同时为零
if (!("零".equals(now) && "零".equals(before))) {
rst += now;
}
before = now;
}
// 结果长度
int rstLen = rst.length();
// 末位去零
if ("零".equals(rst.substring(rstLen - 1, rstLen))) {
rst = rst.substring(0, rstLen - 1);
}
return rst;
}
/**
* 用来处理小数部分
* @author zql
* @createTime 2020-11-15 21:34:39
* @version 1.0
*
* @param dotPart
* @return
*/
private static String dotToBig(String dotPart) {
String ret = "";
for (int i = 0; i < dotPart.length() && i < 3; i++) {
int n;
if ((n = Integer.parseInt(dotPart.substring(i, i + 1))) != 0) {
ret += NUM_CN[n] + UNIT_ARR[2 - i];
}
}
return ret;
}
/**
* 数值转换
* @author zql
* @createTime 2021-01-03 03:09:06
*
* @param val
* @return
* @throws
*/
private static String getSubUnit(String val) {
String rst = "";
int valLen = val.length();
for (int i = 0; i < valLen; i++) {
String s = val.substring(i, i + 1);
int n = Integer.parseInt(s);
// “零”作特殊处理,转换后数末不能为零
if (n == 0 && i != valLen - 1) {
rst += "零";
} else {
rst += NUM_CN[n];
// 个位不加单位
if (i != valLen - 1) {
rst += UNIT_ARR[6 - (i + 4 - valLen)];
}
}
}
return rst;
}
/**
* 得到当前级次的字符串
* @author zql
* @createTime 2021-01-03 03:09:47
*
* @param val
* @param grade
* @return
* @throws
*/
private static String getNowGradeVal(String val, int grade) {
int curGrade = 4;
String rst;
int valLen = val.length();
if (valLen <= grade * curGrade) {
rst = val.substring(0, valLen - (grade - 1) * curGrade);
} else {
rst = val.substring(valLen - grade * curGrade, valLen - (grade - 1) * curGrade);
}
return rst;
}
/**
* 获取单位索引
* @param c
* @return
*/
private static int getUnitIndex(char c) {
for (int j = 0; j < UNIT_ARR.length; j++) {
if (c == UNIT_ARR[j].charAt(0)) {
return j;
}
}
return 0;
}
/**
* 获取单位金额
* @param unitIndex 单位索引
* @return
*/
private static BigDecimal getUnit(int unitIndex) {
String num = "0";
switch (unitIndex) {
// '厘', '分', '角', '圆', '拾', '佰', '仟', '万', '亿', '兆'
case 0:
num = "0.001";
break;
case 1:
num = "0.01";
break;
case 2:
num = "0.1";
break;
case 3:
num = "1";
break;
case 4:
num = "10";
break;
case 5:
num = "100";
break;
case 6:
num = "1000";
break;
case 7:
num = "10000";
break;
case 8:
num = "100000000";
break;
case 9:
num = "1000000000000";
break;
default:
break;
}
return new BigDecimal(num);
}
private static String REGEX_NUMBER_1 = "[-\\+]{0,1}0|^\\+{0,1}[1-9]\\d*|^-[1-9]\\d*";
private static String REGEX_NUMBER_2 = "[-\\+]{0,1}\\d{1}\\.\\d+|[-\\+]{0,1}[1-9]{1}\\d*\\.\\d+";
/**
* 判断字符串是否不是数字
* @author zql
* @createTime 2020-12-05 16:31:34
*
* @param str
* @return 不是数字返回true,是数字返回false
*/
private static boolean isNotNumber(String str) {
return !isNumber(str);
}
/**
* 判断字符串是否是数字
* @author zql
* @createTime 2020-12-05 16:31:34
*
* @param str
* <pre>
* 小数点后都是0会判断成不是数字,例如:0.00返回的是false
* </pre>
* @return 是数字返回true,否则返回false
*/
private static boolean isNumber(String str) {
return isMatch(REGEX_NUMBER_1, str) || isMatch(REGEX_NUMBER_2, str);
}
/**
* 是否和正则表达式匹配
* @author zql
* @createTime 2020-12-05 16:27:39
*
* @param regex 正则表达式
* @param matchStr 要匹配的字符串
* @return 匹配成功返回true,否则返回false;
*/
private static boolean isMatch(String regex, String matchStr) {
if (Objects.isNull(matchStr) || matchStr.trim().length() == 0) {
return false;
}
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(matchStr).matches();
}
/**
* 检查一个字符串是否为空、""或null。
* <pre>
* StringUtil.isBlank(null) = true
* StringUtil.isBlank("") = true
* StringUtil.isBlank(" ") = true
* StringUtil.isBlank("bob") = false
* StringUtil.isBlank(" bob ") = false
* </pre>
*
* @param str
* @return
*/
public static boolean isBlank(String str) {
int strLen;
if (Objects.isNull(str) || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
/**
* 检查一个字符串是否不为空、不为""或不为null。
* <pre>
* StringUtil.isNotBlank(null) = false
* StringUtil.isNotBlank("") = false
* StringUtil.isNotBlank(" ") = false
* StringUtil.isNotBlank("bob") = true
* StringUtil.isNotBlank(" bob ") = true
* </pre>
*
* @param str
* @return
*/
public static boolean isNotBlank(String str) {
return !isBlank(str);
}
}
测试类
import org.junit.Test;
import top.zqlweb.util.tool.MoneyUtil;
import java.math.BigDecimal;
public class MoneyUtilTest {
@Test
public void toBigAmtAndCnToNumTest() throws Exception {
String s0 = "0.00";
String t0 = MoneyUtil.toBigAmt(s0);
System.out.println(s0 + "=" + t0);
System.out.println(MoneyUtil.cnToNum(t0) + "=" + t0);
System.out.println();
String s1 = "1314.7408";
String t1 = MoneyUtil.toBigAmt(s1);
System.out.println(s1 + "=" + t1);
System.out.println(MoneyUtil.cnToNum(t1) + "=" + t1);
System.out.println();
String s2 = "1004.7488";
String t2 = MoneyUtil.toBigAmt(s2);
System.out.println(s2 + "=" + t2);
System.out.println(MoneyUtil.cnToNum(t2) + "=" + t2);
System.out.println();
String s3 = "5201314";
String t3 = MoneyUtil.toBigAmt(s3);
System.out.println(s3 + "=" + t3);
System.out.println(MoneyUtil.cnToNum(t3) + "=" + t3);
System.out.println();
String s4 = "100145201314.7";
String t4 = MoneyUtil.toBigAmt(s4);
System.out.println(s4 + "=" + t4);
System.out.println(MoneyUtil.cnToNum(t4) + "=" + t4);
System.out.println();
String s5 = "9765412345201300.0408";
String t5 = MoneyUtil.toBigAmt(s5);
System.out.println(s5 + "=" + t5);
System.out.println(MoneyUtil.cnToNum(t5) + "=" + t5);
System.out.println();
String s6 = "9000002345201314.7";
String t6 = MoneyUtil.toBigAmt(s6);
System.out.println(s6 + "=" + t6);
System.out.println(MoneyUtil.cnToNum(t6) + "=" + t6);
System.out.println();
String s7 = "9000002005201000.7408";
String t7 = MoneyUtil.toBigAmt(s7);
System.out.println(s7 + "=" + t7);
System.out.println(MoneyUtil.cnToNum(t7) + "=" + t7);
System.out.println();
String s8 = "10202209.01";
String t8 = MoneyUtil.toBigAmt(s8);
System.out.println(s8 + "=" + t8);
System.out.println(MoneyUtil.cnToNum(t8) + "=" + t8);
System.out.println();
String s9 = "10200209.01";
String t9 = MoneyUtil.toBigAmt(s9);
System.out.println(s9 + "=" + t9);
System.out.println(MoneyUtil.cnToNum(t9) + "=" + t9);
System.out.println();
String e = "19000002345201314.7408";
System.out.println(e + "=" + MoneyUtil.toBigAmt(e));
}
@Test
public void toTenThousandTest() throws Exception {
String s11 = "10202209.01";
System.out.println("11=" + MoneyUtil.toTenThousand(s11));
String s12 = "1020.220901";
System.out.println("12=" + MoneyUtil.toTheUnit(s12));
Double s21 = 876543211.12;
System.out.println("21=" + MoneyUtil.toTenThousand(s21));
Double s22 = 87654.321112;
System.out.println("22=" + MoneyUtil.toTheUnit(s22));
BigDecimal b1 = new BigDecimal("19000002345201314.7408");
System.out.println("b1=" + MoneyUtil.toTenThousand(b1));
BigDecimal b2 = new BigDecimal("1900000234520.13147408");
System.out.println("b2=" + MoneyUtil.toTheUnit(b2));
}
@Test
public void getMoneyTest() {
String s1 = null;
System.out.println(s1 + "=" + MoneyUtil.getMoney(s1));
String s2 = " 5 0.1234567 万 元";
System.out.println(s2 + "=" + MoneyUtil.getMoney(s2));
String s3 = "5000元";
System.out.println(s3 + "=" + MoneyUtil.getMoney(s3));
String s4 = " 500万元";
System.out.println(s4 + "=" + MoneyUtil.getMoney(s4));
String s5 = " 1.2 5万元";
System.out.println(s5 + "=" + MoneyUtil.getMoney(s5));
String s6 = " 1.2 5亿元";
System.out.println(s6 + "=" + MoneyUtil.getMoney(s6));
}
}