需求场景:传入一个数字,把它转成人民币大写。
先看下人民币大写规则:
一、人民币大写金额数字到“元”为止的.在“元”之后.应写“整”(或“正”)字.在“角”之后.可以不写“整”(或“正”)字.大写金额数字有“分”的.“分”后面不写“整”(或“正”)字。
二、人民币大写金额数字前应标明“人民币”字样.大写金额数字有“分”的.“分”后面不写“整”(或“正”)字.
三、人民币大写金额数字前应标明“人民币”字样.大写金额数字应紧接“人民币”字样填写.不得留有空白.大写金额数字前未印“人民币”字样的.应加填“人民币”三字.在票据和结算凭证大写金额栏内不得预印固定的“仟.佰.拾.万.仟.佰.拾.元.角.分”字样。
四、阿拉伯数字小写金额数字中有“0”时.人民币大写应按照汉语语言规律.金额数字构成和防止涂改的要求进行书写.举例如下:
1. 阿拉伯金额数字中间有“0”时.人民币大写要写“零”字.如¥1409.50.应写成人民币陆壹仟肆佰零玖元伍角。
2. 阿拉伯金额数字中间连续有几个“0”时.人民币大写金额中间可以只写一个“零”字.如¥6007.14.应写成人民币陆仟零柒元壹角肆分.
3. 阿拉伯金额数字万位和元位是“0”.或者数字中间连续有几个“0”.万位.元位也是“0”.但千位.角位不是“0”时.中文大写金额中可以只写一个零字.也可以不写“零”字.如¥1680.32.应写成人民币壹仟陆佰捌拾元零叁角贰分.或者写成人民币壹仟陆佰捌拾元叁角贰分.又如¥107000.53.应写成人民币壹拾万柒仟元零伍角叁分.或者写成人民币壹拾万零柒仟元伍角叁分。
4. 阿拉伯金额数字角位是“0”.而分位不是“0”时.中文大写金额“元”后面应写“零”字.如¥16409.02.应写成人民币壹万陆仟肆佰零玖元零贰分,又如¥325.04.应写成人民币叁佰贰拾伍元零肆分。
再介绍下面我写的工具类,我写的这个类就一个方法toUpper(String s),入参的整数部分不能超过16位数,返回参数是转换后的大写。总体而言就是一个String根据一定的规则转成另一个String。逻辑就不说了,直接看代码:
package com.syz.rmb;
import java.util.Arrays;
public class RmbUtil {
private static String reg = "[0-9]*\\.?[0-9]{0,2}";
private static String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒",
"捌", "玖" };
private static String[] iunit = { "元", "万", "亿", "万亿" };// 整数部分单位
private static String[] dunit = { "角", "分" };// 小数部分单位
private static String[] funit = { "", "拾", "佰", "仟" };// 四进制单位
public static void main(String[] args) {
String[] ary = { "00010001001.01", "005420101020000000.06", "00.70",
".00", "1200", "1409.50", "6007.14", "1680.32", "107000.53",
"16409.02", "325.00", "325.0", "1.", ".3", "." };
for (String s : ary) {
String r = toUpper(s);
System.out.println(r);
}
}
public static String toUpper(String s) {
if (!s.matches(reg)) {
throw new RuntimeException("参数不合法" + s);
}
// 在所有前面加0,防止出现split的第一个元素为空的情况,在后面会去掉这个零
s = "0" + s;
String[] ary = s.split("\\.");
// 打印一下将要处理的数据
System.out.println(Arrays.toString(ary));
String left = "";
String right = "";
if (ary.length == 1) {// 只有整数
left = ary[0];
}
else {// 有小数
left = ary[0];
right = ary[1];
}
String leftUpper = "";
String rightUpper = "";
// 除去左边的0
left = left.replaceAll("^0*", "");
if (left.length() > 16) {
throw new RuntimeException("最高支持万亿级别");
}
if (!left.equals("")) {
int llen = left.length();
int j = 0;
int k = 0;
boolean flag = true;
for (int i = llen - 1; i >= 0; i--) {
if (j == 0) {
leftUpper = iunit[k] + leftUpper;
}
if (left.charAt(i) == 48) {
if (flag) {
}
else {
leftUpper = digit[left.charAt(i) - 48] + leftUpper;
flag = true;
}
}
else {
leftUpper = digit[left.charAt(i) - 48] + funit[j]
+ leftUpper;
flag = false;
}
if (j == 3) {
j = 0;
k++;
flag = true;
}
else {
j++;
}
}
}
if (!right.equals("")) {
boolean rflag = false;
if (right.length() == 2) {
if (right.charAt(1) > 48) {
rightUpper = digit[right.charAt(1) - 48] + dunit[1]
+ rightUpper;
rflag = true;
}
}
if (right.charAt(0) == 48) {
if (rflag) {
rightUpper = digit[right.charAt(0) - 48] + rightUpper;
}
}
else {
rightUpper = digit[right.charAt(0) - 48] + dunit[0]
+ rightUpper;
}
}
if (leftUpper.equals("") && rightUpper.equals("")) {
return "零元";
}
if (rightUpper.equals("")) {
rightUpper = "整";
}
return leftUpper + rightUpper;
}
}
控制台打印结果:
[000010001001, 01]
壹仟万壹仟零壹元零壹分
[0005420101020000000, 06]
伍仟肆佰贰拾万亿壹仟零壹拾亿贰仟万元零陆分
[000, 70]
柒角
[0, 00]
零元
[01200]
壹仟贰佰元整
[01409, 50]
壹仟肆佰零玖元伍角
[06007, 14]
陆仟零柒元壹角肆分
[01680, 32]
壹仟陆佰捌拾元叁角贰分
[0107000, 53]
壹拾万柒仟元伍角叁分
[016409, 02]
壹万陆仟肆佰零玖元零贰分
[0325, 00]
叁佰贰拾伍元整
[0325, 0]
叁佰贰拾伍元整
[01]
壹元整
[0, 3]
叁角
[0]
零元