[轉(zhuǎn)載] python數(shù)字轉(zhuǎn)換成中文/數(shù)字轉(zhuǎn)換成漢字python:純字符串方法最優(yōu)

參考鏈接: Python中的類型轉(zhuǎn)換

這幾天做一個(gè)小程序的時(shí)候有了這樣的需求:把阿拉伯?dāng)?shù)字轉(zhuǎn)換成漢字,比如把‘101’轉(zhuǎn)換成‘一百零一’,把‘10000’轉(zhuǎn)換成‘一萬(wàn)’。?


做這樣的程序的時(shí)候有以下幾個(gè)技術(shù)難點(diǎn):?



? 1.加單位問(wèn)題:比如需要加入‘十‘’百‘’千‘’萬(wàn)’?





? 2.去掉多余的‘零’的問(wèn)題:因?yàn)闈h語(yǔ)中超過(guò)兩個(gè)單位為‘0‘,我們只會(huì)說(shuō)一個(gè)‘零’。而且如果末尾位次也是零,則什么都不讀。比如‘10001’讀作‘一萬(wàn)零一’,而‘10000’就直接讀作‘一萬(wàn)’。?





? 3.保留較大單位的問(wèn)題:在去零的過(guò)程中,我們需要保留‘萬(wàn)’、‘億’這種單位,但是‘百’‘千’等就不需要。??





?為了解決問(wèn)題,我設(shè)計(jì)了兩套編程思路(不用現(xiàn)成庫(kù)的情況):?




? 1.采用字符串替換法:?



? ? 第一步:把原來(lái)的數(shù)字str()再list(),用漢字‘零一二三四五六七八九’替換‘0123456789’。?

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

? ? 第三步:刪除多余的單位和零?




? 2.采用數(shù)學(xué)計(jì)算法:?



? ? 第一步:設(shè)計(jì)函數(shù)用原數(shù)字整除對(duì)應(yīng)的10的次方數(shù),比如200000就讓它整除100000。得數(shù)即為對(duì)應(yīng)單位的數(shù)值,比如這個(gè)就是十萬(wàn)位的2。?

? ? 第二步:用原數(shù)字整除后的余數(shù)(%取余運(yùn)算),繼續(xù)和對(duì)應(yīng)的10的次方數(shù)進(jìn)行整除,然后取余……循環(huán)進(jìn)行?

? ? 第三步:在每一次整除后,都把得到的整數(shù)轉(zhuǎn)換為中文并和對(duì)應(yīng)位次的單位的中文連接成字符串。?

? ? 第四步:如果取余后的數(shù)比原數(shù)字小兩位或者以上,字符串連接上一個(gè)‘零’,并跳過(guò)對(duì)應(yīng)單位,理論上不產(chǎn)生多余的‘零’和單位。?







? ? ? ? 有趣的是,方法二是一個(gè)非常有精細(xì)編程思想的做法,而且在實(shí)現(xiàn)的過(guò)程中可以通過(guò)拆分?jǐn)?shù)字(比如把100000拆為10+0000)而進(jìn)一步簡(jiǎn)化程序(只用設(shè)計(jì)千位以內(nèi)的程序即可,千以上的算完加個(gè)‘萬(wàn)’就好),對(duì)于多余‘零’的產(chǎn)生控制上可以說(shuō)也是極其優(yōu)秀,除了末尾外根本不會(huì)多出來(lái)沒(méi)用的‘零’和‘單位’。?

? ? ? ?但是方法一,卻是一個(gè)很符合python思想的辦法:雖然會(huì)產(chǎn)生不計(jì)其數(shù)的多余‘零’和單位,但是在計(jì)算的過(guò)程中幾乎沒(méi)有用到數(shù)學(xué),都是if或者del這樣的簡(jiǎn)單語(yǔ)句。在最后的多余單位刪除中,可以采用正則表達(dá)式來(lái)提高效率。??


? ? ? ?兩種方法各有優(yōu)缺點(diǎn),對(duì)于兩種變成思路,我分別設(shè)計(jì)了三種程序來(lái)完成任務(wù),并對(duì)它們進(jìn)行計(jì)時(shí),對(duì)比效率:?


? 任務(wù)內(nèi)容:轉(zhuǎn)換1-9999999所有的數(shù)字并產(chǎn)生一個(gè)對(duì)應(yīng)列表。?

? 程序一思路:采用數(shù)學(xué)計(jì)算法,整除對(duì)應(yīng)10的次方數(shù)+取余,把整除得數(shù)轉(zhuǎn)換成字符串,加上對(duì)應(yīng)單位數(shù),再次進(jìn)行。如果余數(shù)和原數(shù)字差兩位且不是零,則輸出一個(gè)‘零’并連接。?


? 程序二思路:采用字符串法并應(yīng)用正則表達(dá)式,先把原數(shù)字打成列表?

? 用漢字替換所有數(shù)字并在對(duì)應(yīng)位次插入單位。如果對(duì)應(yīng)位次漢字是‘零’,則不插入單位,改為再插入一個(gè)‘零’。之后用正則表達(dá)式識(shí)別‘零’+并替換為‘零’,再刪除末尾‘零’后返回字符串。?


? 程序三思路:采用純字符串方法。先把原數(shù)字打成列表用漢字替換數(shù)字并插入單位。將列表倒置,在列表內(nèi)搜索‘零’,再驗(yàn)證找到位置處i后面兩位[i+2]處是否為單位或者‘零’,如果是,則刪除[i+1],之后遞歸。這樣的話零以后的所有多余單位和零就全部被刪除了。然后進(jìn)行搜索,刪除所有‘零’左邊的一位[i-1](就是它原有對(duì)應(yīng)的單位),之后再刪除末尾的‘零’即可。?



不廢話,上代碼:?

程序一:?

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

k=['零','十','百','千','萬(wàn)','十','百']

import time

def rankid():

? ? rank=[]

? ? for i in range(9999999):

? ? ? ? a=tstr(i)

? ? ? ? rank.append(a)

? ? return rank

#取整取余并連接,返回連接好的字符串和余數(shù)

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,)

#調(diào)用上一個(gè)函數(shù),以保證進(jìn)行完所有的數(shù)并返回

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('程序共用時(shí):%0.2f'%end)


共用時(shí):362.93?

程序很精巧,可惜太慢。??


程序二:?

import re,time

#主程序

def ranki():

? ? rank=[]

? ? for i in range(9999999):

? ? ? ? i=turn(i)

? ? ? ? rank.append(i)

? ? return rank

#如果超過(guò)萬(wàn),則分為兩部分以節(jié)約代碼和運(yùn)行速度

def turn(x):

? ? i=str(x)

? ? if len(i) >4:

? ? ? ? i=tran(i[0:-4])+'萬(wàn)'+tran(i[-4:])

? ? else:

? ? ? ? i=tran(i[-4:])

? ? return i

#轉(zhuǎn)換數(shù)字并插入對(duì)應(yīng)單位,單位為‘零’則再插入一個(gè)‘零’以方便正則表達(dá)式替換

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

#進(jìn)行多余‘零’的刪除

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

#加上 if 語(yǔ)句 防止對(duì)不必要的數(shù)據(jù)進(jìn)行正則表達(dá)式檢測(cè)

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('程序共用時(shí):%0.2f'%end)

共用時(shí):181.69s


是第一個(gè)的兩倍快。?


程序三:?

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

kin=['十','百','千','萬(wàn)','零']

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 ['十','百','千','萬(wàn)','零']:

? ? ? ? ? ? ? ? if x[a+1] != '萬(wàn)':

? ? ? ? ? ? ? ? ? ? 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('程序共用時(shí):%0.2f'%end)

程序用時(shí):123.68s


雖然還有些多余代碼,但是運(yùn)行速度真是驚人。??

總結(jié):個(gè)人感覺(jué)python是字符串至上的語(yǔ)言,很多地方字符串都能被靈活運(yùn)用,程序還遠(yuǎn)遠(yuǎn)不完美,希望能更快一步。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容