問題: 商業領域,開發票,支票等金錢相關項目通常要求轉換成大寫,諸如“壹拾圓陸角玖分”.編程過程中,一般的錢幣都是double型.
當前看到的方法:之所以寫這個方法,因為看到的方法設計的不是很好,通常的做法就是逐個字符處理,通過冗長的switch...case結構判斷,來決定當前是否應該輸出某某漢字,總體來說,完成這件任務是簡單的,但是代碼和設計質量卻不令人滿意.
設計方法如下:
需要注意的問題:
1.各個阿拉伯數字可以通過一個數組'壹','貳','叁'....表示.
2.對于大于10000和大于100000000的數字,可能出現'萬','億'字樣
3.對于中間連續為0的數字,正確出現'零'的字樣,但是有幾種不同的情況需要處理
4.對于某個段的數字全零的情況,例如,整個萬段都是0的情況-100000101,中間的0如何出現
5.角分的處理,如果不存在角分的話,應該出現'圓整'的字樣
6.整數部分不存在的情況,即只有角分,應該沒有'圓'的字樣
設計框架:
1.把數字轉化成字符串處理,使用Java的時候,把一個double類型轉化成一個字符串類型很簡單,
調用 String.valueOf(double_var)即可得到,但是有一個問題,當你的數字大于10個位的時候,
也就是達億的時候,他會轉換成科學計數法的字串,解決方法就是把他轉化成整形long.
2.把數字分割成整數部分和小數部分分別處理,根據上面的方法,我們索性把double乘上100,
取后兩位為小數部分,前面的為整數部分,得到
long l = (long)(d*100);
String strVal = String.valueOf(l);
String head = strVal.substring(0,strVal.length()-2); //整數部分
String end = strVal.substring(strVal.length()-2); //小數部分
3.我們應該把錢數分成段,每四個一段,實際上得到的是一個二維數組,如下:
仟 佰 拾 ' '
' ' $4 $3 $2 $1
萬 $8 $7 $6 $5
億 $12 $11 $10 $9
其中$i表示這個數字的第i個位置的數字,我們并不實際設定二維數組,我們得到的是數字的位置,
要處理的該產生什么樣的表示法,很簡單這種處理方式往往就是:設pos表示數字位置,pos/4 在那一個段
萬以下段,萬段,億段.pos%4表示某一個段的段內位置,仟,佰,拾,由于疊加的緣故,即會有千萬,百萬,千億等
出現,因此這種設計是成立的.這里面隱含了一個問題就是,我們當前的處理的最大數字達千億位,
更大的數字用這種結構是不妥的,因為可能會有萬億,這時候推薦的想法是把這些設計成單維的數組結構,
從而取得疊加的表示.
4.循環處理各個位的過程中,我們可以預想到,零的問題是最難解決的.
因為我們多個連續的零你只能出現一個表示,更有甚者,當某段全為0時,'零'還不能出現.
因此這些問題綜合考慮得到以下代碼.
代碼:(JAVA描述)
public static String changeToBig(double value){
char[] hunit={'拾','佰','仟'}; //段內位置表示
char[] vunit={'萬','億'}; //段名表示
char[] digit={'零','壹','貳','叁','肆','伍','陸','柒','捌','玖'}; //數字表示
long midVal = (long)(value*100); //轉化成整形
String valStr=String.valueOf(midVal); //轉化成字符串
String head=valStr.substring(0,valStr.length()-2); //取整數部分
String rail=valStr.substring(valStr.length()-2); //取小數部分
String prefix=""; //整數部分轉化的結果
String suffix=""; //小數部分轉化的結果
//處理小數點后面的數
if(rail.equals("00")){ //如果小數部分為0
suffix="整";
} else{
suffix=digit[rail.charAt(0)-'0']+"角"+digit[rail.charAt(1)-'0']+"分"; //否則把角分轉化出來
}
//處理小數點前面的數
char[] chDig=head.toCharArray(); //把整數部分轉化成字符數組
char zero='0'; //標志'0'表示出現過0
byte zeroSerNum = 0; //連續出現0的次數
for(int i=0;i<chDig.length;i++){ //循環處理每個數字
int idx=(chDig.length-i-1)%4; //取段內位置
int vidx=(chDig.length-i-1)/4; //取段位置
if(chDig[i]=='0'){ //如果當前字符是0
zeroSerNum++; //連續0次數遞增
if(zero == '0'){ //標志
zero=digit[0];
} else if(idx==0 && vidx >0 &&zeroSerNum < 4){
prefix += vunit[vidx-1];
zero='0';
}
continue;
}
zeroSerNum = 0; //連續0次數清零
if(zero != '0') { //如果標志不為0,則加上,例如萬,億什么的
prefix+=zero;
zero='0';
}
prefix+=digit[chDig[i]-'0']; //轉化該數字表示
if(idx > 0) prefix += hunit[idx-1];
if(idx==0 && vidx>0){
prefix+=vunit[vidx-1]; //段結束位置應該加上段名如萬,億
}
}
if(prefix.length() > 0) prefix += '圓'; //如果整數部分存在,則有圓的字樣
return prefix+suffix; //返回正確表示
}