其實這個題目本身都還有點問題。漢語數字的表達方式何止一兩種,而且還有很多不規範的稱呼。所以,轉換起來也是比較麻煩的。並且由於每個人的叫法不同,因此也不容易判定用戶的輸入是否合符常理和規範。這就只能靠大家去正確對待了。
我的基本思路是這樣的,比如說:九千八百六十四萬三千二百一十一(98643211),首先,必須提取出該字符串中量級最大的字,在該字符串裏,“萬”是量級最大的,所以,每次都把量級從高到低提取出來。按照:“億”,“萬”,“千”,“百”,“十”的順序,每次將字符串與對其對比。
因爲是循環,所以,每次取到最大量級後就跳出該次循環,如上例:第一次,取到“萬”字,跳出循環,然後以“萬”字爲分割字符,將字符串分割成兩段(九千八百六十,三千二百一十一)。並且記住該次分割的量級,然後再把前半部分傳遞到另一個遞歸調用函數進行處理(先不講這個函數),然後把後面一部分再次傳遞給該函數進行遞歸調用,而這次取量級將從該次量級以後的開始取。依次重複,直到程序結束。
那麼,前半部分的字符串將如何處理?首先,我們照樣進行量級查找,由於分割後的字符串要短得多,每次從最高量級找,找到後,分割字符串,並將量級前的數字返回。這裏與上面函數不同的就是需要返回量級前的數字。而前一個函數返回的是整個字符串。一直遞歸到取出所有量級前的數字。每次將其值乘以量級後相加。最後再返回到第一個函數,再與上一次分割字符串的量級相乘。依次完成所有步驟:
所以,依上例,有:
每一次:九千八百六十四萬三千二百一十一 分割成:九千八百六十四和三千二百一十一
下一步:將九千八百六十四傳遞給第二個遞歸函數,然後每次分割爲:九千、八百、六十、四。每次分割完成後,都取得量級前的數字。即爲:九、八、六、四
然後每次返回該數字與量級的乘積與上一次遞歸的和,最後遞歸完成時返回整個字符串(九千八百六十四)的值。
第一段字符串處理完成以後,接下來按照同樣的方法(也就是第一個遞歸函數)處理剩下的字符串,依次類推,直到處理完所有字符串。
但這只是理論上的東西,實際運用中還有許多小的細節需要注意。比如說:輸入:十九,十、一萬零一等。只要大家多想一些,就能夠處理大部分遇到的問題。當然,這種東西輸入的時候也沒有一個固定的語法可以檢查。如果真要寫個語法,估計也不是那麼容易。測試的時候也只能按照我們常規的習慣去輸入字符串,隨便亂輸入肯定會報錯。並且還要在一定的範圍內使用。
下面,我把自己寫的一點代碼帖上來,沒有處理異常,也沒有寫檢查用戶輸入的語法,但基本上可以實現十萬億以內的數值轉換,只要用戶不刻意地亂輸入:
- public class work {
- //全局數組,存儲單位量級
- String [] strCHup ={"億",
- "萬","千","百","十"};
- //通過兩次遞歸調用實現分割.
- public long excuteCharge(String str,int start)
- {
- //存儲量級單位
- long midNumber=0;
- //存儲是否可以找到最高量級
- int bre=-1;
- //找到後根據索引實行字符串分割
- int split = 0;
- //通過循環查找最高量級
- for(int i=start;i<strCHup.length;i++)
- {
- bre = str.indexOf(strCHup[i]);
- if(bre!=-1)
- {
- split=i;
- switch(i)
- {
- case 0:
- midNumber=100000000;
- break;
- case 1:
- midNumber=10000;
- break;
- case 2:
- midNumber=1000;
- break;
- case 3:
- midNumber=100;
- break;
- case 4:
- midNumber=10;
- break;
- }
- //只需要找到最高量級,找到即刻跳出循環.
- break;
- }
- }
- //如果沒有找到量級數.說明該數很小,直接調用add()返回該值.
- if(bre==-1)
- {
- return add(str);
- }
- //否則要根據量級進行字符串侵害和返回侵害前部分的值
- else
- {
- //如果大型整數,如:十萬 等.因爲後面不需要再分割
- if(str.length()==bre+1)
- {
- //對於單個量級的值,如:十、百、千、萬等。不需要裁減字符串。直接返回量級即可
- if(str.length()==1)
- {
- return midNumber;
- }
- else
- {
- return add(str.substring(0, str.length()-1))*midNumber;
- }
- }
- //對於只有兩位數的.如:十九.直接調用add()返回值即可.不能在此處遞歸.
- else if(str.length()==bre+2){
- return add(str);
- }
- //其他情況則取值和分割.然後再遞歸調用.
- else
- {
- String[] strPart = str.split(strCHup[split]);
- return (add(strPart[0])*midNumber)+excuteCharge(strPart[1],0);
- }
- }
- }
- public long add(String str)
- {
- //存儲strCHup裏具體漢字的數字值
- long mid=0;
- //存儲strNumup裏具體漢字的數字值
- int number=0;
- //存儲傳入字符串的最高級別單位在strCHup數組裏的索引.
- int num=-1;
- for(int i=0;i<strCHup.length;i++)
- {
- //取得量級在字符串中的索引.
- num=str.indexOf(strCHup[i]);
- //定義char型變量,存儲每個漢字.便於後面比較
- char ch=' ';
- ////////////////////////////////////////////////////////////////
- if(num!=-1)
- {
- switch(i)
- {
- case 0:
- mid=100000000;
- break;
- case 1:
- mid=10000;
- break;
- case 2:
- mid=1000;
- break;
- case 3:
- mid=100;
- break;
- case 4:
- mid=10;
- break;
- }
- //如果以"十"開關的,直接定義number的值.因爲在上面能夠找到它的量級.
- if((str.toCharArray())[0]=='十')
- {
- number=1;
- }
- //否則,取得量級前的數字進行比較,再確定number的值
- else
- {
- ch = (str.toCharArray())[num-1];
- }
- //////////////////////////////////////////////////////
- }
- //循環結束
- //////////////////////////////////////////////////////////////////
- //如果整個字符串就一個字,那麼就應該取該值進行比較.而不是再取量級前的數字.
- if(str.length()==1){
- ch = (str.toCharArray())[0];
- }
- //防止幾萬零幾這樣的數.
- else if((str.length()==2)&&((str.toCharArray())[0]=='零'))
- {
- ch = (str.toCharArray())[1];
- }
- switch(ch)
- {
- case '零':
- number=0;
- break;
- case '一':
- number=1;
- break;
- case '二':
- number=2;
- break;
- case '三':
- number=3;
- break;
- case '四':
- number=4;
- break;
- case '五':
- number=5;
- break;
- case '六':
- number=6;
- break;
- case '七':
- number=7;
- break;
- case '八':
- number=8;
- break;
- case '九':
- number=9;
- break;
- }
- /////////////////////////////////////////////////////////////////
- if(num!=-1)
- {
- break;
- }
- }
- if(num==-1)
- {
- return number;
- }
- String strLeft = str.substring(num+1);
- return (number*mid)+add(strLeft);
- }
- }