《瘋狂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));
- }
- }
輸出:
- 壹仟陸佰捌拾元三角貳分
- 壹仟肆佰零玖元伍角
- 陸仟零柒元壹角肆分
- 壹拾萬柒仟元伍角三分
- 壹萬陸仟肆佰零玖元零貳分
- 三佰貳拾伍元零肆分
- 壹分
- 貳元壹角
- 肆角玖分
- 壹元肆角玖分
- 壹元整
- 零元
- 壹萬貳仟三佰肆拾伍億陸仟柒佰捌拾玖萬壹仟零壹拾貳元整
- 玖萬億元整
- 玖萬零壹佰億零伍元整
- 玖仟玖佰玖拾玖萬玖仟玖佰玖拾玖億玖仟玖佰玖拾玖萬玖仟玖佰玖拾捌元整