汉字数字转阿拉伯数字。Python3实现。

系统 1906 0

 

可能有些情况没有考虑到。

 

 

源码 

python3:

            
              #encoding=utf-8
import math

#系数
CN_NUM = {
    '〇': 0,
    '一': 1,
    '二': 2,
    '两': 2,
    '三': 3,
    '四': 4,
    '五': 5,
    '六': 6,
    '七': 7,
    '八': 8,
    '九': 9,
    '零': 0,
}

#基数
CN_UNIT = {
    '十': 10,
    '百': 100,
    '千': 1000,
    '万': 10000,
    '亿': 100000000,
}

#计算中文数字值,返回string
def calcCNNumberValue(digs):
    if(not digs): return ""

    #根据系数、基数map将汉字转数值大小
    tmp =[]
    for d in digs[::-1]:
        if(CN_NUM.__contains__(d)): tmp.append(CN_NUM[d])
        elif(CN_UNIT.__contains__(d)): tmp.append(CN_UNIT[d])

    #系数直接加入tmp2,基数相邻相乘或者加入tmp2并在前面补1
    tlen = len(tmp)
    tmp2 = []
    for i in range(0, tlen):
        if(tmp[i] > 9):
            if(i == tlen - 1 or tmp[i + 1] > tmp[i]):
                tmp2.append(tmp[i])
                tmp2.append(1)
            elif(tmp[i + 1] > 9):
                tmp[i + 1] *= tmp[i]
            else: tmp2.append(tmp[i])
        else: tmp2.append(tmp[i])

    #系数直接加入seq,基数根据其大小用-1占住位置让下一个系数在正确位上
    seq = []
    curW = 0
    for t in tmp2:
        if(t > 9):
            w = math.log10(t)
            while(curW < w):
                curW += 1
                seq.append(-1)
        else:
            curW += 1
            seq.append(t)

    #对于个位是非0的前方是-1的数,要尽可能提到高位
    if(seq[0] > 0 and len(seq) > 1 and seq[1] == -1):
        seqLen, p = len(seq), 1
        while(p < seqLen and seq[p] == -1): p += 1
        #swap 
        seq[p - 1] = seq[0]
        seq[0] = 0

    #seq拼接,-1转为0,其余的保持原数值
    return "".join([str(n if n >= 0 else 0) for n in seq[::-1]])

#测试
if __name__ == '__main__':
    print(calcCNNumberValue("零"))   #0
    print(calcCNNumberValue("五"))   #5
    print(calcCNNumberValue("十"))   #10
    print(calcCNNumberValue("一十"))   #10
    print(calcCNNumberValue("十五"))   #15
    print(calcCNNumberValue("三十五"))   #35
    print(calcCNNumberValue("三百五"))   #350
    print(calcCNNumberValue("三千五"))   #3500
    print(calcCNNumberValue("三千零五"))   #3005
    print(calcCNNumberValue("三千五十"))   #3050
    print(calcCNNumberValue("三千五百五"))   #3550
    print(calcCNNumberValue("二百万"))   #2000000
    print(calcCNNumberValue("二百万零五十"))   #2000050
    print(calcCNNumberValue("一万一"))   #11000
    print(calcCNNumberValue("一万一十"))   #10010
    print(calcCNNumberValue("一万一百"))   #10100
    print(calcCNNumberValue("一万一百一"))   #10110
    print(calcCNNumberValue("一万一百零一"))   #10101
    print(calcCNNumberValue("一万零一"))   #10001
    print(calcCNNumberValue("二〇一九"))   #2019
    print(calcCNNumberValue("千万万"))   #100000000000
    print(calcCNNumberValue("一千万一"))   #11000000
    print(calcCNNumberValue("一千万零一"))   #10000001
            
          

 

说明

 

算法分几步。

以几个例子来说明。

 

第一步,将汉字转为数值,在系数map和基数map中搜索,非法字符在这里会直接被过滤。digs倒着循环,则原先数值的低位会存在tmp数组的低位中。

  例如:

    “一百万零六” ,转换后存tmp中,tmp为: [6, 0, 10000, 100, 1]

    "一百十一“, ->  tmp : [1, 10, 100, 1]

    "一万一",       ->  tmp : [1, 10000, 1]

 

第二步,将基数加入tmp2并在前补1,或者和前基数合并,系数直接加入tmp2。(解决“十一”, “十”这种基数前没系数的情况)

例如:

    “一百万零六”  -> tmp2 : [6, 0, 1000000, 1]    (10000 < 100,  10000被乘到下一个100上并被丢弃)

    "一百十一“, ->  tmp2 : [1, 10, 1, 100, 1]      (10<100,10前补1)

    "一万一",       ->  tmp2 : [1, 10000, 1]

 

第三步,基数变现,基数的存在是为了下一个系数能够在正确的位置上。遇到系数,直接丢入seq,遇到基数,丢弃或者,在中间补位 (此处补-1,为了和“零”作区别),让下一个系数位置符合这个基数的描述。

例如:

    “一百万零六” ->  seq : [6, 0, -1, -1, -1, -1, 1]    (1000000取log是6,下一个系数必须在第6+1位上(第一个是第1位),中间补-1,直到当前seq长度为6)

    "一百十一“, ->  seq : [1, 1, 1]      (10取log是1,直接丢弃,100取log是2,直接丢弃)

    "一万一",       ->  seq : [1, -1, -1, -1, 1]   (10000取log是4,中间补-1,直到当前seq长度为4,下一个1插到第5位上,表示“万”)

 

第四步,最低位非零数字满足条件可升高位,前面补-1而不补0的作用在此体现。(针对,一万二,两百二等情况,最低位的“二”应分别指代“二千”和“二十”,要尽可能往上升高位)

例如:

     “一百万零六”  ->  seq : [6, 0, -1, -1, -1, -1, 1]    (最低为6紧挨着0,说明中文描述时指定了“零”,不做处理)

      "一百十一“, ->  seq : [1, 1, 1]      (最低为1,相邻1,不做处理)

      "一万一",       ->  seq : [-1, -1, -1, 1, 1]  (最低位1,相邻着-1,则向高位找,直到非-1为止,找到第4位(第一个算第1位),将第1个和第4个数值交换,“1”由个位升至千位)

 

第五步,seq倒过来转为string。seq地位存数值地位,所以低位要放右侧,倒着循环。-1变成0,不小于0的保留原值。

例如:

      “一百万零六”  -> return : 1000006  

      "一百十一“,  ->  return : 111 

      "一万一",       ->  return : 11000 

 

 

汉字数字转阿拉伯数字。Python3实现。_第1张图片


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论