问题描述
今天在CodeProject首次发表文章:http://www.codeproject.com/KB/cs/NumberToFromWord.aspx,这里特别对中文数字转换做一说明。这里好像不能上传,欢迎大家到我的博客下载代码http://www.cnblogs.com/cruisoring/archive/2011/11/21/2257091.html作为一个可扩展的工具,它能够实现数字转中文,以及中文转数字。大体思路是为每个数字建立建立字典Dictionary<int,List<string>>NumberNameDict,即newDictionary<int,List<string>>{{10,newList<string>{"十","拾"}},{20,newList<string>{"廿"}},{30,newList<string>{"卅"}},{100,newList<string>{"百","佰"}},{1000,newList<string>{"千","仟"}},{10000,newList<string>{"万"}},{100000000,newList<string>{"亿"}}},newList<string>(){"○一二三四五六七八九","0123456789","零壹贰叁肆伍陆柒捌玖"}存储所有对应的中文,其中List<string>仅对中文有效,存储0-9对应的中文字符,其中第一个字符串为缺省输出格式。类的初始化程序由此建立反向查询的字典Dictionary<string,int>WordNameDict:foreach(KeyValuePair<int,List<string>>kvpinNumberNameDict){foreach(stringsinkvp.Value){WordNameDict.Add(s,kvp.Key);if(!AllWords.Contains(s))AllWords.Add(s);}}另外对于进制数建立列表protectedList<int>groupNums:groupNums=newList<int>();intmax=NumberNameDict.Keys.Max();for(inti=firstGroupNum;i<=max;i*=10){if(NumberNameDict.ContainsKey(i)){//GroupNameDict.Add(i,NumberNameDict[i][0]);groupNums.Add(i);}}groupNums.Sort();结果是{100000000,10000,1000,100,10},即"亿万千百十"对应的数字列表。数字转中文为实现数字转中文,首先对于每个非零的字符进行转换,其位数按照groupNums解析:List<string>sections=newList<string>();intremained=number;for(inti=0;i<groupNums.Count;i++){if(remained<groupNums[i])continue;intwhole=remained/groupNums[i];sections.Add(toWords(whole));if(ToPlural!=null&&whole!=1)sections.Add(ToPlural(NumberNameDict[groupNums[i]][0]));elsesections.Add(NumberNameDict[groupNums[i]][0]);remained-=whole*groupNums[i];if(remained!=0&&NeedInsertAnd(number,remained))//if(remained!=0&&remained<100)sections.Add(AndWords[0]);}if(remained!=0)sections.Add(toWords(remained));最终结果对于中文就是简单地将以上分散的字符串连接起来:StringBuildersb=newStringBuilder();for(inti=0;i<sections.Count-1;i++){sb.Append(sections[i]+Space);}sb.Append(sections.Last());returnsb.ToString();为实现个性化的字符输出,可以调用以下接口,对特定字符进行定义。///</summary>///<paramname="number">Thenumber</param>///<paramname="samples">///Thecharactersshallbeusedtoreplacethedefaultones.///<example>///Forexample,234002052bydefaultwillbeconvertedto"二亿三千四百万零二千零五十二",///butifthesamplesissetto"佰零壹贰叁肆拾",thentheoutputwillbe"贰亿叁千肆佰万零贰千零五拾贰"///anycharactersappearedinthesampleswillreplacethedefaultones,thus"贰"willreplaceany"二"sfordigitof"2".///</example>///</param>///<returns>Theconvertedstringinwords.</returns>privatestringtoWords(intnumber,stringsamples){stringresult=ToWords(number);foreach(charchinsamples){if(allCharacters.Contains(ch)&&WordNameDict.ContainsKey(ch.ToString())){intdigit=WordNameDict[ch.ToString()];if(digit>9&&!groupNums.Contains(digit))continue;stringdigitStr=NumberNameDict[digit][0];if(digitStr.Length!=1||digitStr[0]==ch)continue;result=result.Replace(digitStr[0],ch);}}returnresult;}中文转换为数字最大的挑战在于难以判断数字对应的位数,考虑到:高位应当出现在低位之前;如果高位出现在低位之后,意味着它们应通过相乘组合为一个更高位。低位出现在高位之后,意味着对之前的数字做个确认。因此我使用一个堆栈stack<int>实现数字的解析,相应代码如下。///<summary>///Functiontogetnumberfromsplitwords.///</summary>///<paramname="sectors">Wordsforeachdigitsofthenumber</param>///<returns>Thenumber</returns>protectedintfromWords(string[]sectors){intresult=0,current,lastGroup=1,temp,maxGroup=1;Stack<int>stack=newStack<int>();foreach(stringsinsectors){if(AllWords.Contains(s)){if(AndWords.Contains(s))continue;if(WordNameDict.ContainsKey(s)){current=WordNameDict[s];if(groupNums.Contains(current)){//Thecurrentgroupishigherthananyexistedgroup,thusthedigitsshallbeincreased:byMultiply!!!!if(current>=maxGroup){temp=stack.Pop();while(stack.Count!=0){temp+=stack.Pop();};temp*=current;stack.Push(temp);maxGroup*=current;lastGroup=1;}//Thecurrentgroupishigherthanthelastgroup,thusshallbeaddelseif(current>lastGroup){temp=0;while(stack.Peek()<current){temp+=stack.Pop();};temp*=current;stack.Push(temp);lastGroup=current;}else{temp=stack.Pop();temp*=current;stack.Push(temp);lastGroup=current;}}else{stack.Push(current);}}}elsethrownewException();}do{result+=stack.Pop();}while(stack.Count!=0);returnresult;}Toparsethestringtogetnumber,thetryParse()isrecommended.Collapse|CopyCode///<summary>///Themainfunctiontotrytoretrievenumberfromstringofwords.///</summary>///<paramname="numberInWords">Theoriginalwordstringofnumber</param>///<paramname="result">Theconvertednumberifsuccessful</param>///<returns>TRUEifparsesuccessfully.</returns>protectedvirtualbooltryParse(stringnumberInWords,outintresult){result=-1;try{stringwords=IsCaseSensitive?numberInWords.ToLower():numberInWords;string[]sectors=split(words);varcontained=fromsinsectorswhereAllWords.Contains(s)selects;result=fromWords(contained.ToArray());returntrue;}catch{returnfalse;}}最终对数字与中英文的转换结果如下:5:五==>520:廿==>2021:二十一==>2199:九十九==>99100:一百==>100102:一百零二==>102131:一百三十一==>131356:三百五十六==>356909:九百零九==>9091000:一千==>10001021:一千零二十一==>10212037:二千零三十七==>203712345:一万二千三百四十五==>1234531027:三万一千零二十七==>3102740002:四万零二==>4000290010:九万零一十==>90010100232300:一亿零二十三万二千三百==>100232300234002052:二亿三千四百万零二千零五十二==>2340020525:five==>520:twenty==>2021:twenty-one==>2199:ninety-nine==>99100:onehundred==>100102:onehundredandtwo==>102131:onehundredandthirty-one==>131356:threehundredsandfifty-six==>356100232300:onehundredmillionstwohundredsandthirty-twothousandsthreehundreds==>100232300234002052:twohundredsandthirty-fourmillionstwothousandsandfifty-two==>234002052572030013:五亿七千贰佰零叁万零壹拾叁==>572030013234002052:贰亿叁千肆佰万零贰千零五拾贰==>234002052100232300:OneHundredMillionsTwoHundredsAndThirtyTwoThousandsThreeHundreds==>100232300234002052:TwoHundredsAndThirtyFourMillionsTwoThousandsAndFiftyTwo==>234002052第壹佰零八张=108
解决方案
解决方案二:
楼主,不知小数字可否有考虑?