問題:????商業領域,開發票,支票等金錢相關項目通常要求轉換成大寫,諸如“壹拾圓陸角玖分”.編程過程中,一般的錢幣都是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;?????????????????????????
//
返回正確表示
??????}