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