阅读:0       作者:严长生

中文数字转阿拉伯数字(C++实现)

中文数字的权位是明的,阿拉伯数字的权位则隐含在数字的位置中。比如中文数字“一万”,对应的阿拉伯数字是10000,如何确定补多少个 0 才能将 1 顶在正确的位置上?这正是中文数字转换成阿拉伯数字的关键,如何将明的权位转换成数字的位置。

转换的基本方法

对于十进制阿拉伯数字,数字的所在位数就是该数字与10的倍数关系。个位就是 1 倍,十位就是 10 倍,百位就是 100 倍,以此类推。

通过这个关系,可以将阿拉伯数字隐含的权位转换成 10 的倍数表示,比如中文数字“五百”,就可以转换成 5x100,其结果就是 500。再来看一个复杂的中文数字“四万二千五百一十三”,对每个权位依次转换成倍数并求和:

4x 10000 + 2x 1000 + 5x 100 +1 x 10+3x1

就可以得到对应的阿拉伯数字 42513。

由以上分析可知,从中文数字转阿拉伯数字的基本方法就是从中文数字中逐个识别出数字和权位的组合,然后根据权位和阿拉伯数字倍数的对应关系计算出每个数字和权位组合的值,最后求和得到结果。

但是中文数字并不是严格用“数字”+“权位”组合成的,“零”的使用就是个特例,它在数字中出现,却没有权位。

除此之外,节权位也需要考虑,因为它常和其他权位连在一起使用,比如“二十万”中的“十”是数字权位,“万”是节权位。在设计算法时,由于“零”没有权位,因此对于中文数字中的“零”不需处理,直接跳过即可。节权位比较特殊,它不是与之相邻的数字的倍数,而是整个小节的倍数,因此转换过程中,需要临时保存每个节权位出现之前的小节的值。

算法实现

中文数字转换成阿拉伯数字的算法实现,首先要做两件事情:
  1. 将中文数字转换成阿拉伯数字;
  2. 将中文权位转换成 10 的倍数。

中文数字转换成阿拉伯数字可以通过反查 chnNumChar 表实现。将中文权位转成 10 的倍数需要事先建立一个中文权位与 10 的倍数的关系表,我们这样定义一个中文权位和 10 的倍数关系:
typedef struct {
    const char *name; //中文权位名称
    int value; //10的倍数值
    bool secUnit; //是否是节权位
}CHN_NAME_VALUE;
根据这个关系的定义建立的权位与 10 的倍数的关系表如下:
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 的倍数。