[C#] 將國字數字轉換為阿拉伯數字

因為從來沒有過這種需要, 所以沒去思考這種問題, 還以為 .Net 一定有提供相關的函數。不過等到真正需要這種功能時, 才發現 .Net 似乎並沒有提供如此功能, 找過 Visual Basic 程式庫, 也沒有找到...

 

因為從來沒有過這種需要, 所以沒去思考這種問題, 還以為 .Net 一定有提供相關的函數。不過等到真正需要這種功能時, 才發現 .Net 似乎並沒有提供如此功能, 找過 Visual Basic 程式庫, 也沒有找到。沒辦法, 只好自己寫一個, 程式如下:

        /// <summary>
        /// 將國字數字轉換為阿拉伯數字 - 僅支援一億以下之數字; 若格式有誤, 可能出現 Exception
        /// </summary>
        /// <param name="cnum">請輸入正確格式之國字數字, 如 "八千四百二十一萬三千五百六十三"</param>
        public static int convChineseNumber(string cnum)
        {
            cnum = cnum.Replace("一十", "十");

            cnum = cnum.TrimEnd();
            char[] cnums = cnum.ToCharArray();
            int sum = 0, sectionUnit = 0, sectionsum = 0;
            foreach (char c in cnums)
            {
                int arab = mapCnumLetters(c);
                if (isMultiplier(c))
                {
                    if (isSegmentDelimeter(c)) // 萬/億
                    {
                        sectionsum = sum * arab;
                        sum = sectionsum;
                        if (sum < 0)
                            throw new Exception("輸入的字串無法解析!");
                        sectionsum = 0;
                    }
                    else // 十/百/千
                    {
                        if (sectionUnit == 0)
                            sectionsum = 10; // 特別處理 "十萬", "十一萬" 之類的狀況
                        else
                        {
                            sectionsum -= sectionUnit;
                            sum -= sectionUnit;
                            sectionsum = sectionUnit * arab;
                        }
                        sum += sectionsum;
                        if (sum < 0)
                            throw new Exception("輸入的字串無法解析!");
                    }
                }
                else
                {
                    sectionUnit = arab;
                    sum += arab;
                    if (sum < 0)
                        throw new Exception("輸入的字串無法解析!");
                    sectionsum += arab;
                }
            }
            return sum;
        }

        private static bool isSegmentDelimeter(char cnum)
        {
            switch (cnum)
            {
                case '萬':
                    return true;
                case '億':
                    return true;
                default:
                    return false;
            }
        }

        private static bool isMultiplier(char cnum)
        {
            switch (cnum)
            {
                case '十':
                    return true;
                case '拾':
                    return true;
                case '百':
                    return true;
                case '佰':
                    return true;
                case '千':
                    return true;
                case '仟':
                    return true;
                case '萬':
                    return true;
                case '億':
                    return true;
                default:
                    return false;
            }
        }

        private static int mapCnumLetters(char cnum)
        {
            switch (cnum)
            {
                case '零':
                    return 0;
                case '一':
                    return 1;
                case '壹':
                    return 1;
                case '二':
                    return 2;
                case '貳':
                    return 2;
                case '三':
                    return 3;
                case '參':
                    return 3;
                case '四':
                    return 4;
                case '肆':
                    return 4;
                case '五':
                    return 5;
                case '伍':
                    return 5;
                case '六':
                    return 6;
                case '陸':
                    return 6;
                case '七':
                    return 7;
                case '柒':
                    return 7;
                case '八':
                    return 8;
                case '捌':
                    return 8;
                case '九':
                    return 9;
                case '玖':
                    return 9;
                case '十':
                    return 10;
                case '拾':
                    return 10;
                case '廿':
                    return 20;
                case '丗':
                    return 30;
                case '百':
                    return 100;
                case '佰':
                    return 100;
                case '千':
                    return 1000;
                case '仟':
                    return 1000;
                case '萬':
                    return 10000;
                case '億':
                    return 100000000;
                default:
                    return 0;
            }
        } 

先聲明一下, 這個程式尚未經過嚴謹的測試, 也沒有提供防呆或偵錯的功能, 所以如果你打算拿去使用在重要的情境中 (例如薪資計算、財報編彙等), 你必須自己好好測試一番; 萬一有任何問題, 我可不負任何責任喔!

在我自己的測試中, 我已經測試過幾組數字:

  • 十五
  • 三十五
  • 廿五
  • 丗五
  • 二十
  • 二十一
  • 二十一萬
  • 二十一萬三千五百
  • 十一萬三千五百六十三
  • 一十一萬三千五百六十三
  • 八千四百萬零六十三
  • 捌仟肆佰萬零陸拾參 
  • 八千四百二十一萬三千五百六十三
  • 捌仟肆佰貳拾壹萬參仟伍佰陸拾參

不過如果輸入的數字有錯亂, 例如 「二十一千」, 則會得到錯誤的數字。此外, 這個函數只支援一億以下的數字, 如果你需要支援到一億以上, 你最好自己修改一下。

Microsoft 自己有提供一個 Visual Studio International Pack, 裡面的功能當中即有一項就是把阿拉伯數字轉換為中文數字(很可惜, 好像不能轉回來), 你如果有興趣, 不妨前往參考一下:

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-tw&FamilyID=f9cfc884-1f00-45fa-b2fb-303d9e110bc7#Instructions

 


Dev 2Share @ 點部落