作者: tianshi0253 鏈接:http://tianshi0253.javaeye.com/blog/202928 發表時間: 2008年06月13日
聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!
package com.jqqd.ywc; /** * 程序目的: 從命令行接收一個數,并將其轉化為中文金額的大寫方式 例如 123.45 --> 壹佰貳拾叁元肆角伍分 * * @author LovinChan * * 看到網上有很多這樣的例子程序,不過覺得很不滿意。有些程序我從命名上就覺得 實在是不符合規范,程序里面的算法沒有讓人明白得很清楚的注釋,讀上去覺得有 * 點難度,可讀性不強。而且很多程序還存在不少bug,隨便一測就測出來了。 所以本人還是決定重新寫一下這個程序,并且盡量做到消除不必要的bug。這個程 * 序我沒有用什么很精妙的算法,不過用了一些Java類庫中的類,像是正則表達式之類 * 的東西。由于本人對算法不怎么在行,在做轉換操作的時候用的是很笨的方法。望各位 大蝦海涵,呵呵。 * * 程序的注釋我盡量寫得詳細一點,如果覺得這個程序哪里有問題或者是哪里有改進的 地方歡迎隨時跟我交流。 我的msn:egg.chenlw@gmail.com * QQ:543669516(注上為什么加我就可以了) 我的blog:http://hi.baidu.com/egg_chen 歡迎交流 */ public class Trans2RMB { /** * 測試程序的可行性 * * @param args */ public static void main(String[] args) { System.out.println("--------將數字轉換成中文金額的大寫形式------------\n"); Trans2RMB t2r = new Trans2RMB(); String s = t2r.cleanZero(t2r.splitNum(t2r.roundString(t2r.getNum()))); // 如果轉換過后是一個空串,則不輸出屏幕 if (!"".equals(s)) { System.out.println("轉換成中文后為:" + s); ; } System.out.println("\n---------------------------------------------"); } /** * 從命令行接收一個數,在其中調用 checkNum() 方法對其進行 驗證,并返回相應的值 * * @return 如果輸入合法,返回輸入的這個數 */ private String getNum() { String s = null; System.out.println("請輸入一個數字(精確到小數點后兩位):"); // 從命令行輸入這個浮點數 java.util.Scanner scanner = new java.util.Scanner(System.in); s = scanner.next(); // 判斷用戶輸入是否合法 // 若合法,返回這個值;若非法返回 "0" if (this.checkNum(s)) { return s; } else { return ""; } } /** * 判斷用戶輸入的數據是否合法,用戶只能輸入大于零的數字,不能輸入其它字符 * * @param s * String * @return 如果用戶輸入數據合法,返回 true,否則返回 false */ private boolean checkNum(String s) { // 如果用戶輸入的數里有非數字字符,則視為非法數據,返回 false try { float f = Float.valueOf(s); // 如果這個數小于零則視為非法數據,返回 false if (f < 0) { System.out.println("非法數據,請檢查!"); return false; } else { return true; } } catch (NumberFormatException e) { System.out.println("非法數據,請檢查!"); return false; } } /** * 把用戶輸入的數以小數點為界分割開來,并調用 numFormat() 方法 進行相應的中文金額大寫形式的轉換 注:傳入的這個數應該是經過 * roundString() 方法進行了四舍五入操作的 * * @param s * String * @return 轉換好的中文金額大寫形式的字符串 */ private String splitNum(String s) { // 如果傳入的是空串則繼續返回空串 if ("".equals(s)) { return ""; } // 以小數點為界分割這個字符串 int index = s.indexOf("."); // 截取并轉換這個數的整數部分 String intOnly = s.substring(0, index); String part1 = this.numFormat(1, intOnly); // 截取并轉換這個數的小數部分 String smallOnly = s.substring(index + 1); String part2 = this.numFormat(2, smallOnly); // 把轉換好了的整數部分和小數部分重新拼湊一個新的字符串 String newS = part1 + part2; return newS; } /** * 對傳入的數進行四舍五入操作 * * @param s * String 從命令行輸入的那個數 * @return 四舍五入后的新值 */ private String roundString(String s) { // 如果傳入的是空串則繼續返回空串 if ("".equals(s)) { return ""; } // 將這個數轉換成 double 類型,并對其進行四舍五入操作 double d = Double.parseDouble(s); // 此操作作用在小數點后兩位上 d = (d * 100 + 0.5) / 100; // 將 d 進行格式化 s = new java.text.DecimalFormat("##0.000").format(d); // 以小數點為界分割這個字符串 int index = s.indexOf("."); // 這個數的整數部分 String intOnly = s.substring(0, index); // 規定數值的最大長度只能到萬億單位,否則返回 "0" if (intOnly.length() > 13) { System.out.println("輸入數據過大!(整數部分最多13位!)"); return ""; } // 這個數的小數部分 String smallOnly = s.substring(index + 1); // 如果小數部分大于兩位,只截取小數點后兩位 if (smallOnly.length() > 2) { String roundSmall = smallOnly.substring(0, 2); // 把整數部分和新截取的小數部分重新拼湊這個字符串 s = intOnly + "." + roundSmall; } return s; } /** * 把傳入的數轉換為中文金額大寫形式 * * @param flag * int 標志位,1 表示轉換整數部分,0 表示轉換小數部分 * @param s * String 要轉換的字符串 * @return 轉換好的帶單位的中文金額大寫形式 */ private String numFormat(int flag, String s) { int sLength = s.length(); // 貨幣大寫形式 String bigLetter[] = { "零", "壹", "貳", "叁", "肆", "伍", "陸", "柒", "捌", "玖" }; // 貨幣單位 String unit[] = { "元", "拾", "佰", "仟", "萬", // 拾萬位到仟萬位 "拾", "佰", "仟", // 億位到萬億位 "億", "拾", "佰", "仟", "萬" }; String small[] = { "分", "角" }; // 用來存放轉換后的新字符串 String newS = ""; // 逐位替換為中文大寫形式 for (int i = 0; i < sLength; i++) { if (flag == 1) { // 轉換整數部分為中文大寫形式(帶單位) newS = newS + bigLetter[s.charAt(i) - 48] + unit[sLength - i - 1]; } else if (flag == 2) { // 轉換小數部分(帶單位) newS = newS + bigLetter[s.charAt(i) - 48] + small[sLength - i - 1]; } } return newS; } /** * 把已經轉換好的中文金額大寫形式加以改進,清理這個字 符串里面多余的零,讓這個字符串變得更加可觀 注:傳入的這個數應該是經過 splitNum() * 方法進行處理,這個字 符串應該已經是用中文金額大寫形式表示的 * * @param s * String 已經轉換好的字符串 * @return 改進后的字符串 */ private String cleanZero(String s) { // 如果傳入的是空串則繼續返回空串 if ("".equals(s)) { return ""; } // 如果用戶開始輸入了很多 0 去掉字符串前面多余的'零',使其看上去更符合習慣 while (s.charAt(0) == '零') { // 將字符串中的 "零" 和它對應的單位去掉 s = s.substring(2); // 如果用戶當初輸入的時候只輸入了 0,則只返回一個 "零" if (s.length() == 0) { return "零"; } } // 字符串中存在多個'零'在一起的時候只讀出一個'零',并省略多余的單位 /* 由于本人對算法的研究太菜了,只能用4個正則表達式去轉換了,各位大蝦別介意哈... */ String regex1[] = { "零仟", "零佰", "零拾" }; String regex2[] = { "零億", "零萬", "零元" }; String regex3[] = { "億", "萬", "元" }; String regex4[] = { "零角", "零分" }; // 第一輪轉換把 "零仟", 零佰","零拾"等字符串替換成一個"零" for (int i = 0; i < 3; i++) { s = s.replaceAll(regex1[i], "零"); } // 第二輪轉換考慮 "零億","零萬","零元"等情況 // "億","萬","元"這些單位有些情況是不能省的,需要保留下來 for (int i = 0; i < 3; i++) { // 當第一輪轉換過后有可能有很多個零疊在一起 // 要把很多個重復的零變成一個零 s = s.replaceAll("零零零", "零"); s = s.replaceAll("零零", "零"); s = s.replaceAll(regex2[i], regex3[i]); } // 第三輪轉換把"零角","零分"字符串省略 for (int i = 0; i < 2; i++) { s = s.replaceAll(regex4[i], ""); } // 當"萬"到"億"之間全部是"零"的時候,忽略"億萬"單位,只保留一個"億" s = s.replaceAll("億萬", "億"); return s; } }
本文的討論也很精彩,瀏覽討論>>
JavaEye推薦
- Oracle專區上線,有Oracle最新文章,重要下載及知識庫等精彩內容,歡迎訪問。
- 北京: 千橡集團暨校內網誠聘軟件研發工程師
- 搜狐網站誠聘Java、PHP和C++工程師
- 立刻報名,免費獲取門票,參加SOA技術論壇(廣州6月19日)
文章來源:http://tianshi0253.javaeye.com/blog/202928