金额数字转为大写,修改一千万元时异常情况
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
package com.yxt.common.base.utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @Author dimengzhe
|
||||
* @Date 2022/11/8 19:10
|
||||
* @Description
|
||||
*/
|
||||
public class TransformMoney {
|
||||
|
||||
/*
|
||||
以下摘自百度百科:http://baike.baidu.com/view/359995.htm
|
||||
大写数字规则
|
||||
中文大写金额数字应用正楷或行书填写,如壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整(正)等字样。不得用一、二(两)、三、四、五、六、七、八、九、十、廿、毛、另(或0)填写,不得自造简化字。如果金额数字书写中使用繁体字,如贰、陆、亿、万、圆的,也可。
|
||||
中文大写金额数字到"元"为止的,在"元"之后,应写"整"(或"正")字,在"角"之后,可以不写"整"(或"正")字。大写金额数字有"分"的,"分"后面不写"整"(或"正")字。
|
||||
中文大写金额数字前应标明"人民币"字样,大写金额数字有"分"的,"分"后面不写"整"(或"正")字。
|
||||
中文大写金额数字前应标明"人民币"字样,大写金额数字应紧接"人民币"字样填写,不得留有空白。大写金额数字前未印"人民币"字样的,应加填"人民币"三字。在票据和结算凭证大写金额栏内不得预印固定的"仟、佰、拾、万、仟、佰、拾、元、角、分"字样。
|
||||
阿拉伯数字小写金额数字中有"0"时,中文大写应按照汉语语言规律、金额数字构成和防止涂改的要求进行书写。举例如下:
|
||||
阿拉伯数字中间有"0"时,中文大写要写"零"字,如¥1409.50,应写成人民币壹仟肆佰零玖元伍角。
|
||||
阿拉伯数字中间连续有几个"0"时,中文大写金额中间可以只写一个"零"字,如¥6007.14,应写成人民币陆仟零柒元壹角肆分。
|
||||
阿拉伯金额数字万位和元位是"0",或者数字中间连续有几个"0",万位、元位也是"0",但千位、角位不是"0"时,中文大写金额中可以只写一个零字,也可以不写"零"字。如¥1680.32,应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分,又如¥107000.53,应写成人民币壹拾万柒仟元零伍角叁分,或者写成人民币壹拾万零柒仟元伍角叁分。
|
||||
阿拉伯金额数字角位是"0",而分位不是"0"时,中文大写金额"元"后面应写"零"字。如¥16409.02,应写成人民币壹万陆仟肆佰零玖元零贰分;又如¥325.04,应写成人民币叁佰贰拾伍元零肆分。
|
||||
*/
|
||||
|
||||
static final String big = "零壹贰叁肆伍陆柒捌玖"; //大写
|
||||
static final String[] units = {"仟佰拾", "角分"}; //单位
|
||||
|
||||
|
||||
/**
|
||||
* 双精度浮点数转换成字符串
|
||||
* 注:
|
||||
* 1、如果直接用String.toString(double d)方法,超大数额会出现科学计数法的字符串;
|
||||
* 2、如果整数部分超过15位数,低位部分可能出现误差,所以不支持超过15位整数的数值,
|
||||
* 一般数据库设计金额字段时都不会超过15位整数,如oracle用Number(18,3)的类型表示,整数部分最多15位,小数点后保留3位有效数字。
|
||||
*/
|
||||
public static String getDecimalStr(double d) {
|
||||
//设置小数点后的精度,保留两位
|
||||
/*四舍五入结果参考:
|
||||
0.005,//0.01入
|
||||
0.015,//0.01舍
|
||||
0.025,//0.03入
|
||||
0.035,//0.04入
|
||||
0.045,//0.04舍
|
||||
0.055,//0.06入(前一位是5则入)
|
||||
*/
|
||||
String str = new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
|
||||
|
||||
/*
|
||||
//经过测试,以下三种方法都是可以用的:
|
||||
//或1:
|
||||
String str = new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
|
||||
|
||||
//或2:
|
||||
DecimalFormat format = new DecimalFormat();
|
||||
format.applyPattern("#################0.00");
|
||||
String str = format.format(d);
|
||||
|
||||
//或3:
|
||||
DecimalFormat decimalFormat = new DecimalFormat();
|
||||
decimalFormat.setMinimumFractionDigits(2);
|
||||
decimalFormat.setMaximumFractionDigits(2);
|
||||
decimalFormat.setGroupingUsed(false);
|
||||
decimalFormat.setMaximumIntegerDigits(15);
|
||||
decimalFormat.setMinimumIntegerDigits(15);
|
||||
str=decimalFormat.format(d);
|
||||
*/
|
||||
|
||||
//如果结果是整数,则去掉尾巴
|
||||
if (str.endsWith(".00")) {
|
||||
str = str.replace(".00", "");
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额是double类型的要先转换成字符串
|
||||
*
|
||||
* @param money 金额
|
||||
*/
|
||||
public static String transform(double money) {
|
||||
String moneyStr = getDecimalStr(money);
|
||||
return transform(moneyStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额转换成大字
|
||||
* 我的思路:
|
||||
* 1、double数值转换成数值字符串
|
||||
* 2、处理整数部分:
|
||||
* 填充到16位,不足16位则前面补'0',然后右起分成四组,每组根据"x仟x佰x拾x"的规则转换成大写,若该组为"0000"则结果是"零";
|
||||
* 对这四组结果从高位到低位拼接起来,规则:[组4]万[组3]亿[组2]万[组1]圆。
|
||||
* 3、处理小数部分(不多说)
|
||||
*/
|
||||
public static String transform(String moneyStr) {
|
||||
String[] parts = moneyStr.split("\\."); //区别整数、小数部分
|
||||
String result = "";
|
||||
|
||||
//处理整数部分
|
||||
int length = parts[0].length(); //整数部分的位数
|
||||
if (length > 15) {
|
||||
return "金额太大,不能处理整数部分超过15位的金额!";
|
||||
}
|
||||
String intPart = parts[0];
|
||||
|
||||
//填充到16位,因为是分4组,每组4个数字
|
||||
while (intPart.length() < 16) {
|
||||
intPart = '0' + intPart;
|
||||
}
|
||||
//共分四组,右起四位一组,例如:0001,2003,0030,3400
|
||||
String[] groups = new String[4];
|
||||
for (int i = 0; i < groups.length; i++) {
|
||||
int start = intPart.length() - (i + 1) * 4; //开始位置
|
||||
int end = intPart.length() - i * 4; //结束位置
|
||||
groups[i] = intPart.substring(start, end);
|
||||
groups[i] = transformGroup(groups[i]); //当前组的四位数字转换成大写
|
||||
}
|
||||
|
||||
//对这四组结果从高位到低位拼接起来,规则:[组4]万[组3]亿[组2]万[组1]圆
|
||||
for (int i = groups.length - 1; i >= 0; i--) {
|
||||
if (i == 3) { //第四组:万亿级
|
||||
if (!"零".equals(groups[i])) {
|
||||
result += groups[i] + "万";
|
||||
}
|
||||
} else if (i == 2) { //第三组:亿级
|
||||
if (!"零".equals(groups[i])) {
|
||||
result += groups[i] + "亿";
|
||||
} else {
|
||||
if (result.length() > 0) {
|
||||
result += "亿";
|
||||
}
|
||||
}
|
||||
} else if (i == 1) { //第二组:万级
|
||||
if (!"零".equals(groups[i])) {
|
||||
result += groups[i] + "万";
|
||||
} else if (!groups[i].startsWith("零")) {
|
||||
result += groups[i];
|
||||
}
|
||||
} else { //第一组:千级
|
||||
if (!"零".equals(groups[i]) || result.length() == 0) {
|
||||
result += groups[i];
|
||||
}
|
||||
result += "元";
|
||||
}
|
||||
}
|
||||
if (!"零元".equals(result) && result.startsWith("零")) {
|
||||
result = result.substring(1, result.length()); //最前面的可能出现的“零”去掉
|
||||
}
|
||||
|
||||
//处理小数部分
|
||||
if (parts.length == 2) {
|
||||
String decimalPart = parts[1]; //小数部分
|
||||
for (int i = 0; i < decimalPart.length(); i++) {
|
||||
int num = Integer.valueOf(decimalPart.charAt(i) + ""); //提取数字,左起
|
||||
result += big.charAt(num) + "" + units[1].charAt(i); //数字变大写加上单位
|
||||
}
|
||||
result = result.replace("零角", "零"); //去掉"零角"的"角"
|
||||
result = result.replace("零分", ""); //去掉"零分"
|
||||
} else {
|
||||
result += "整"; //没有小数部分,则加上“整”
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理整数部分的组,右起每四位是一组
|
||||
*
|
||||
* @param group 四位数字字符串
|
||||
*/
|
||||
public static String transformGroup(String group) {
|
||||
String result = "";
|
||||
int length = group.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
int digit = Integer.valueOf(group.charAt(i) + ""); //单个数字,左起
|
||||
String unit = ""; //单位
|
||||
if (i != length - 1) {
|
||||
unit = units[0].charAt(i) + "";
|
||||
}
|
||||
result += big.charAt(digit) + unit; //数字变大写加上单位
|
||||
}
|
||||
|
||||
result = result.replace("零仟", "零");
|
||||
result = result.replace("零佰", "零");
|
||||
result = result.replace("零拾", "零");
|
||||
|
||||
while (result.contains("零零")) {
|
||||
result = result.replace("零零", "零"); //如果有“零零”则变成一个“零”
|
||||
}
|
||||
|
||||
if (!"零".equals(result) && result.endsWith("零")) {
|
||||
result = result.substring(0, result.length() - 1); //最未尾的可能出现的“零”去掉
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user