?
可能有些情況沒有考慮到。
?
?
源碼?
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?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
