中文數字轉阿拉伯數字(C++實現)
阿新 • • 發佈:2018-12-20
中文數字的權位是明的,阿拉伯數字的權位則隱含在數字的位置中。比如中文數字“一萬”,對應的阿拉伯數字是10000,如何確定補多少個 0 才能將 1 頂在正確的位置上?這正是中文數字轉換成阿拉伯數字的關鍵,如何將明的權位轉換成數字的位置。
通過這個關係,可以將阿拉伯數字隱含的權位轉換成 10 的倍數表示,比如中文數字“五百”,就可以轉換成 5x100,其結果就是 500。再來看一個複雜的中文數字“四萬二千五百一十三”,對每個權位依次轉換成倍數並求和:
由以上分析可知,從中文數字轉阿拉伯數字的基本方法就是從中文數字中逐個識別出數字和權位的組合,然後根據權位和阿拉伯數字倍數的對應關係計算出每個數字和權位組合的值,最後求和得到結果。
但是中文數字並不是嚴格用“數字”+“權位”組合成的,“零”的使用就是個特例,它在數字中出現,卻沒有權位。
除此之外,節權位也需要考慮,因為它常和其他權位連在一起使用,比如“二十萬”中的“十”是數字權位,“萬”是節權位。在設計演算法時,由於“零”沒有權位,因此對於中文數字中的“零”不需處理,直接跳過即可。節權位比較特殊,它不是與之相鄰的數字的倍數,而是整個小節的倍數,因此轉換過程中,需要臨時儲存每個節權位出現之前的小節的值。
中文數字轉換成阿拉伯數字可以通過反查 chnNumChar 表實現。將中文權位轉成 10 的倍數需要事先建立一箇中文權位與 10 的倍數的關係表,我們這樣定義一箇中文權位和 10 的倍數關係:
根據這個關係的定義建立的權位與 10 的倍數的關係表如下:
轉換的基本方法
對於十進位制阿拉伯數字,數字的所在位數就是該數字與10的倍數關係。個位就是 1 倍,十位就是 10 倍,百位就是 100 倍,以此類推。通過這個關係,可以將阿拉伯數字隱含的權位轉換成 10 的倍數表示,比如中文數字“五百”,就可以轉換成 5x100,其結果就是 500。再來看一個複雜的中文數字“四萬二千五百一十三”,對每個權位依次轉換成倍數並求和:
4x 10000 + 2x 1000 + 5x 100 +1 x 10+3x1
就可以得到對應的阿拉伯數字 42513。由以上分析可知,從中文數字轉阿拉伯數字的基本方法就是從中文數字中逐個識別出數字和權位的組合,然後根據權位和阿拉伯數字倍數的對應關係計算出每個數字和權位組合的值,最後求和得到結果。
但是中文數字並不是嚴格用“數字”+“權位”組合成的,“零”的使用就是個特例,它在數字中出現,卻沒有權位。
除此之外,節權位也需要考慮,因為它常和其他權位連在一起使用,比如“二十萬”中的“十”是數字權位,“萬”是節權位。在設計演算法時,由於“零”沒有權位,因此對於中文數字中的“零”不需處理,直接跳過即可。節權位比較特殊,它不是與之相鄰的數字的倍數,而是整個小節的倍數,因此轉換過程中,需要臨時儲存每個節權位出現之前的小節的值。
演算法實現
中文數字轉換成阿拉伯數字的演算法實現,首先要做兩件事情:- 將中文數字轉換成阿拉伯數字;
- 將中文權位轉換成 10 的倍數。
中文數字轉換成阿拉伯數字可以通過反查 chnNumChar 表實現。將中文權位轉成 10 的倍數需要事先建立一箇中文權位與 10 的倍數的關係表,我們這樣定義一箇中文權位和 10 的倍數關係:
typedef struct { const char *name; //中文權位名稱 int value; //10的倍數值 bool secUnit; //是否是節權位 }CHN_NAME_VALUE;
CHN_NAME_VALUE chnValuePair[]={ {"十",10, false }, {"百", 100, false }, {"千", 1000, false }, {"萬",10000, true }, {"億",100000000, true } };根據以上定義實現的轉換演算法如下:
unsigned int ChineseToNumber(const std::string& chnString) { unsigned int rtn = 0; unsigned int section = 0; int number = 0; bool secUnit = false; std::string::size_type pos = 0; while(pos < chnString.length()) { int num = ChineseToValue(chnString.substr(pos, CHN_CHAR_LENGTH)); if(num >= 0) /*數字還是單位? */ { number = num; pos += CHN_CHAR_LENGTH; if (pos >= chnString.length())//如果是最後一位數字,直接結束 { section += number; rtn += section; break; } } else { int unit = ChineseToUnit(chnString.substr(pos,CHN_CHAR_LENGTH), secUnit); if(SeCUnit)//是節權位說明一個節己經結束 { section = (section + number) * unit; rtn += section; section = 0; } else { section += (number * unit); } number = 0; pos += CHN_CHAR_LENGTH; if(pos >= chnString.length()) { rtn += section; break; } } } return rtn; }
ChineseToNumber()
函式就是中文數字轉阿拉伯數字演算法的主要部分,chnString
引數就是合法的中文字串,轉換的過程就是對 chnString
中的中文逐個處理:
- 如果遇到中文數字,就存放在 number 變數中,對於“零”不處理,直接跳過。
- 如果是中文權位,則將其對應的倍數與 number 相乘得到對應的數字,同時累加到 section 變數中。
- 如果是節權位,則將節權位對應的倍數與 section 相乘得到對應的數字,同時累加到最終的結果 rtn 變數中。
ChineseToValue()
函式負責查表完成中文數字到英文數字的轉換,如果返回 -1,則表示這是一個權位字元。ChineseToUnit()
函式負責查 chnValuePair
表得到權位對應的 10 的倍數。