人民币大写金额转换算法
《疯狂Java讲义》里面的一道练习题:将浮点数转成人民币读法字符串,例如将1006.33转为壹仟零陆元叁角叁分。
根据人民币大写金额规范,转换有几点要注意的:
- 阿拉伯数字中间有“0”时,中文大写金额中间可以只写一个“零”字。如¥1,409.50,应写成人民币壹仟肆佰零玖元伍角。
- 阿拉伯数字中间连续有几个“0”,中文大写金额中间可以只写一个“零”字,如¥6,007.14,应写成人民币陆仟零柒元壹角肆分。
- 阿拉伯金额数字万位或元位是“0”,或者数字中间连续有几个“0”,万位、元位也是“0”,但仟位、角位不是“0”时,中文大写金额中可以只写一个零字,也可以不写“零”字,如¥1,680.32,应写成人民币壹仟陆佰捌拾元零三角贰分,或者写成人民币壹仟陆佰捌拾元三角贰分;又如¥107,000.53,应写成人民币壹拾万柒仟元零伍角叁分,或者写成人民币壹拾万柒仟元伍角叁分。
- 阿拉伯金额数字角位是“0”,而分位不是“0”时,中文大写金额“元”后面应写“零”字。如¥16,409.02,应写成人民币壹万陆仟肆佰零玖元零贰分;又如¥325.04,应写成人民币叁佰贰拾元零肆分。
- 大写金额到“元”为止的,在“元”之后应写上“整”或“正”字,在“角”之后可以不写“整”或“正”字,在“分”之后的不写”整“或”正“字。
我的思路是:
- 将输入格式化成:“xxxx,xxxx,xx”,以千位划分整数部分,小数部分保留两位(到分位);
- 将输入拆分为整数部分和小数部分;
- 倒序逐位转换,先处理小数部分,再处理整数部分;
- 转换后,根据人民币大写金额规范处理多余的“零”字。
详见代码:
- package avstudio.utils;
- import java.text.DecimalFormat;
- /**
- * Program Name: ConvertRMB <br />
- * Description: 将浮点金额转换成人民币读法,精确到分,例如输入:1006.33,输出:壹仟零陆元叁角叁分 <br /> 最大支持值到9999999999999998 <br />
- * Date: 2011-10-19 <br />
- * Email: chialvin.chan@gmail.com <br />
- * Copyright (C), 2011-2012, ChiAlvin.Chan <br />
- * @author ChiAlvin.Chan
- * @version 1.0
- */
- publicclass ConvertRMB {
- /**
- * @param d 需要转换的金额
- * @return 返回大写金额字符串(String)
- */
- publicstatic String convert(double d) {
- String[] numTables = new String[]{"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
- String[] unitTables = new String[]{"分", "角"};
- String[] levelTables = new String[]{"万", "亿"};
- String[] mulTables = new String[]{"", "拾", "佰", "仟"};
- StringBuffer result = new StringBuffer();
- int index = -1;
- // 将数字格式化为xxxx.xx
- DecimalFormat df = new DecimalFormat();
- df.setGroupingSize(4);
- df.setMinimumFractionDigits(2);
- String strFormat = df.format(d);
- // 拆分整数部分和小数部分
- StringBuffer intPart = new StringBuffer(strFormat.substring(0, strFormat.length()-3));
- StringBuffer decimalPart = new StringBuffer(strFormat.substring(intPart.length()+1, strFormat.length()));
- // 处理小数部分
- decimalPart.reverse();
- for(int i=0; i<decimalPart.length(); i++) {
- result.append(unitTables[i%2]);
- result.append(numTables[Character.getNumericValue(decimalPart.charAt(i))]);
- }
- // 处理整数部分
- result.append("元");
- intPart.reverse();
- int level = 0;
- for(int i=0; i<intPart.length(); i++) {
- if(intPart.charAt(i) != ',') {
- result.append(mulTables[i%5]);
- result.append(numTables[Character.getNumericValue(intPart.charAt(i))]);
- } else {
- result.append(levelTables[level]);
- level = ++level % 2;
- }
- }
- result.reverse();
- // 处理多余的零
- while((index = result.indexOf("零分")) != -1){ result.deleteCharAt(index+1); };
- while((index = result.indexOf("零角")) != -1){ result.deleteCharAt(index+1); };
- while((index = result.indexOf("零拾")) != -1){ result.deleteCharAt(index+1); };
- while((index = result.indexOf("零佰")) != -1){ result.deleteCharAt(index+1); };
- while((index = result.indexOf("零仟")) != -1){ result.deleteCharAt(index+1); };
- // 没有小数部分
- while((index = result.indexOf("元零零")) != -1) {
- result.delete(index+1, index+3);
- result.append("整");
- };
- while((index = result.indexOf("零零")) != -1){ result.deleteCharAt(index); };
- while((index = result.indexOf("零元")) != -1) {result.deleteCharAt(index);};
- while((index = result.indexOf("零万")) != -1) {result.deleteCharAt(index);};
- while((index = result.indexOf("零亿")) != -1) {result.deleteCharAt(index);};
- while((index = result.indexOf("亿万")) != -1) {result.deleteCharAt(index+1);};
- // 没有分位
- while((index = result.indexOf("角零")) != -1){ result.deleteCharAt(index+1); };
- // 只有分位
- while((index = result.indexOf("元零")) != -1 && index == 0){ result.delete(index, index+2); };
- // 只有小数位
- while((index = result.indexOf("元")) != -1 && index == 0){ result.deleteCharAt(index); };
- // 零元
- while((index = result.indexOf("整")) != -1 && index == 0){ result.replace(index, index+2, "零元"); };
- return result.toString();
- }
- publicstaticvoid main(String[] args) {
- // TODO Auto-generated method stub
- System.out.println(ConvertRMB.convert(1680.32));
- System.out.println(ConvertRMB.convert(1409.50));
- System.out.println(ConvertRMB.convert(6007.14));
- System.out.println(ConvertRMB.convert(107000.53));
- System.out.println(ConvertRMB.convert(16409.02));
- System.out.println(ConvertRMB.convert(325.04));
- System.out.println(ConvertRMB.convert(0.01));
- System.out.println(ConvertRMB.convert(2.10));
- System.out.println(ConvertRMB.convert(0.49));
- System.out.println(ConvertRMB.convert(1.49));
- System.out.println(ConvertRMB.convert(1d));
- System.out.println(ConvertRMB.convert(0d));
- System.out.println(ConvertRMB.convert(1234567891012d));
- System.out.println(ConvertRMB.convert(9000000000000d));
- System.out.println(ConvertRMB.convert(9010000000005d));
- System.out.println(ConvertRMB.convert(9999999999999998d));
- }
- }
输出:
- 壹仟陆佰捌拾元叁角贰分
- 壹仟肆佰零玖元伍角
- 陆仟零柒元壹角肆分
- 壹拾万柒仟元伍角叁分
- 壹万陆仟肆佰零玖元零贰分
- 叁佰贰拾伍元零肆分
- 壹分
- 贰元壹角
- 肆角玖分
- 壹元肆角玖分
- 壹元整
- 零元
- 壹万贰仟叁佰肆拾伍亿陆仟柒佰捌拾玖万壹仟零壹拾贰元整
- 玖万亿元整
- 玖万零壹佰亿零伍元整
- 玖仟玖佰玖拾玖万玖仟玖佰玖拾玖亿玖仟玖佰玖拾玖万玖仟玖佰玖拾捌元整