[转载] python数字转换成中文/数字转换成汉字python:纯字符串方法最优

参考链接: Python中的类型转换

这几天做一个小程序的时候有了这样的需求:把阿拉伯数字转换成汉字,比如把‘101’转换成‘一百零一’,把‘10000’转换成‘一万’。 


做这样的程序的时候有以下几个技术难点: 



  1.加单位问题:比如需要加入‘十‘’百‘’千‘’万’ 





  2.去掉多余的‘零’的问题:因为汉语中超过两个单位为‘0‘,我们只会说一个‘零’。而且如果末尾位次也是零,则什么都不读。比如‘10001’读作‘一万零一’,而‘10000’就直接读作‘一万’。 





  3.保留较大单位的问题:在去零的过程中,我们需要保留‘万’、‘亿’这种单位,但是‘百’‘千’等就不需要。  





 为了解决问题,我设计了两套编程思路(不用现成库的情况): 




  1.采用字符串替换法: 



    第一步:把原来的数字str()再list(),用汉字‘零一二三四五六七八九’替换‘0123456789’。 

    第二步:在需要的位置加入单位。 

    第三步:删除多余的单位和零 




  2.采用数学计算法: 



    第一步:设计函数用原数字整除对应的10的次方数,比如200000就让它整除100000。得数即为对应单位的数值,比如这个就是十万位的2。 

    第二步:用原数字整除后的余数(%取余运算),继续和对应的10的次方数进行整除,然后取余……循环进行 

    第三步:在每一次整除后,都把得到的整数转换为中文并和对应位次的单位的中文连接成字符串。 

    第四步:如果取余后的数比原数字小两位或者以上,字符串连接上一个‘零’,并跳过对应单位,理论上不产生多余的‘零’和单位。 







        有趣的是,方法二是一个非常有精细编程思想的做法,而且在实现的过程中可以通过拆分数字(比如把100000拆为10+0000)而进一步简化程序(只用设计千位以内的程序即可,千以上的算完加个‘万’就好),对于多余‘零’的产生控制上可以说也是极其优秀,除了末尾外根本不会多出来没用的‘零’和‘单位’。 

       但是方法一,却是一个很符合python思想的办法:虽然会产生不计其数的多余‘零’和单位,但是在计算的过程中几乎没有用到数学,都是if或者del这样的简单语句。在最后的多余单位删除中,可以采用正则表达式来提高效率。  


       两种方法各有优缺点,对于两种变成思路,我分别设计了三种程序来完成任务,并对它们进行计时,对比效率: 


  任务内容:转换1-9999999所有的数字并产生一个对应列表。 

  程序一思路:采用数学计算法,整除对应10的次方数+取余,把整除得数转换成字符串,加上对应单位数,再次进行。如果余数和原数字差两位且不是零,则输出一个‘零’并连接。 


  程序二思路:采用字符串法并应用正则表达式,先把原数字打成列表 

  用汉字替换所有数字并在对应位次插入单位。如果对应位次汉字是‘零’,则不插入单位,改为再插入一个‘零’。之后用正则表达式识别‘零’+并替换为‘零’,再删除末尾‘零’后返回字符串。 


  程序三思路:采用纯字符串方法。先把原数字打成列表用汉字替换数字并插入单位。将列表倒置,在列表内搜索‘零’,再验证找到位置处i后面两位[i+2]处是否为单位或者‘零’,如果是,则删除[i+1],之后递归。这样的话零以后的所有多余单位和零就全部被删除了。然后进行搜索,删除所有‘零’左边的一位[i-1](就是它原有对应的单位),之后再删除末尾的‘零’即可。 



不废话,上代码: 

程序一: 

num=['零','一','二','三','四','五','六','七','八','九']

k=['零','十','百','千','万','十','百']

import time

def rankid():

    rank=[]

    for i in range(9999999):

        a=tstr(i)

        rank.append(a)

    return rank

#取整取余并连接,返回连接好的字符串和余数

def turn(x,y):

    if y>= 1:

        a=x//pow(10,y)

        b=x%pow(10,y)

        c=num[a]+k[y]

        if y>4 and b<pow(10,4):

            c+=k[4]

        if (len(str(x))-len(str(b))) >= 2 and b != 0:

            c+=k[0]

    else:

        a=x

        b=0

        c=num[a]

    return (c,b,)

#调用上一个函数,以保证进行完所有的数并返回

def tstr(x):

    c=turn(x,(len(str(x))-1))

    a=c[0]

    b=c[1]

    while b != 0:

        a+=turn(b,(len(str(b))-1))[0]

        b=turn(b,(len(str(b))-1))[1]

    return a

start=time.time()

ranki=rankid()

end=time.time()-start

print('程序共用时:%0.2f'%end)


共用时:362.93 

程序很精巧,可惜太慢。  


程序二: 

import re,time

#主程序

def ranki():

    rank=[]

    for i in range(9999999):

        i=turn(i)

        rank.append(i)

    return rank

#如果超过万,则分为两部分以节约代码和运行速度

def turn(x):

    i=str(x)

    if len(i) >4:

        i=tran(i[0:-4])+'万'+tran(i[-4:])

    else:

        i=tran(i[-4:])

    return i

#转换数字并插入对应单位,单位为‘零’则再插入一个‘零’以方便正则表达式替换

def tran(x):

    num=['零','一','二','三','四','五','六','七','八','九']

    kin=['零','十','百','千']

    x=list(reversed(x))

    for i in x:

        x[(x.index(i))]=num[int(i)]

    if len(x) >= 2:

        if x[1]==num[0]:

            x.insert(1,kin[0])

        else:

            x.insert(1,kin[1])

        if len(x) >= 4:

            if x[3]==num[0]:

                x.insert(3,kin[0])

            else:

                x.insert(3,kin[2])

            if len(x) >= 6:

                if x[5]==num[0]:

                    x.insert(5,kin[0])

                else:

                    x.insert(5,kin[3])

    x=delz(x)

    return x

#进行多余‘零’的删除

#reversed()函数真是可以用在列表和字符串。

#加上 if 语句 防止对不必要的数据进行正则表达式检测

def delz(x):

    x=''.join(x)

    if '零零'in x:

        x=re.sub('零+','零',x)

    if x.startswith('零'):

        x=list(x)

        x.remove('零')

    x=reversed(x)

    x=''.join(x)

    return x

start=time.time()

rank=ranki()

end=time.time()-start

print('程序共用时:%0.2f'%end)

共用时:181.69s


是第一个的两倍快。 


程序三: 

num=['零','一','二','三','四','五','六','七','八','九']

kin=['十','百','千','万','零']

import time

def sadd(x):

    x.reverse()

    if len(x) >= 2:

        x.insert(1,kin[0])

        if len(x) >= 4:

            x.insert(3,kin[1])

            if len(x) >= 6:

                x.insert(5,kin[2])

                if len(x) >= 8:

                    x.insert(7,kin[3])

                    if len(x) >= 10:

                        x.insert(9,kin[0])

                        if len(x) >= 12:

                            x.insert(11,kin[1])

    x=fw(x)

    x=d1(x)

    x=d2(x)

    x=dl(x)

    return x



def rankis():

    rank=[]

    for i in range(9999999):

        i=list(str(i))

        for j in i:

            i[(i.index(j))]=num[int(j)]

        i=sadd(i)

        rank.append(i)

    return rank

def d1(x):

    if '零' in x:

        a=x.index('零')

        if a==0:

            del x[0]

            d1(x)

        else:

            if x[a+2] in ['十','百','千','万','零']:

                if x[a+1] != '万':

                    del x[a+1]

                    d1(x)     

    return x

def d2(x):

    try:

        a=x.index('零')

        if x[a-1] in ['十','百','千','零']:

            del x[a-1]

            d2(x[a+1])

    except:pass

    return x

def fw(x):

    if len(x) >= 9:

        if x[8] == '零':

            del x[8]

    return x

def dl(x):

    try:

        if x[0]=='零':

            del x[0]

            del1(x)

    except:pass

    x.reverse()

    x=''.join(x)

    return x

start=time.time()

rank=rankis()

end=time.time()-start

print('程序共用时:%0.2f'%end)

程序用时:123.68s


虽然还有些多余代码,但是运行速度真是惊人。  

总结:个人感觉python是字符串至上的语言,很多地方字符串都能被灵活运用,程序还远远不完美,希望能更快一步。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容