方法
将中文数字字符串识别为一个个片段,每个片段包含数字和数位两部分,例如:“三千七百五十二”将被识别成“3,1000”、“7,100”,“5,10”和“2, 1”,共4个片段,通过计算每个片段的结果(数字*数位),再进行累加即可得到最终值。
有下面两个问题要解决:
- 中文数字默认书写习惯:从左至右,数位从高到低排列。如果右侧的数位比左侧高,则左侧较低的数位都要提升。 例如“三千七百五十二万”,最后有一个数位“万”,比左侧的数位都高,所以左侧数位一律提升“一万”,变为“千万”、“百万”、“十万”和“万”;如果是“一亿三千万”,最后的“万”低于左侧的“亿”,只对“千”有提升作用。
- 对于连续出现的数位,先计算其乘积,再对左侧较低的片段进行提升。 例如“三万零四百千兆”,最后“千兆”对左侧“万”和“百”有提升作用。
代码
encoding = 'utf-8'
def num_c2a(chnum_str):
ch_nums = {'一':1, '二':2, '三':3, '四':4, '五':5, '六':6, '七':7, '八':8, '九':9,
'壹':1, '贰':2, '叁':3, '肆':4, '伍':5, '陆':6, '柒':7, '捌':8, '玖':9}
ch_digits = {'十':10, '百':100, '千':1000, '万':10000, '兆':1000000, '亿':100000000,
'拾':10, '佰':100, '仟':1000, '萬':10000}
specials = {'零':'', '两':'二', '廿':'二十', '卅':'三十'}
for x, y in specials.items(): # 替换特殊字
chnum_str = chnum_str.replace(x, y)
chnum_str = chnum_str.strip()
if chnum_str == '': return 0
segments = [] # 用于存储片段,片段=[数字,数位]
i = 0
while i < len(chnum_str):
num = 0
while i < len(chnum_str) and chnum_str[i] in list(ch_nums.keys()): # 获得数字
num = num*10 + ch_nums[chnum_str[i]]
i += 1
if num > 0:
segments.append([num,1])
if i < len(chnum_str) and chnum_str[i] in list(ch_digits.keys()): # 获得所在数位
digit = ch_digits[chnum_str[i]]
if segments == []:
segments.append([1,1])
for x in segments:
if x[1] < digit: # 低于目前数位的片段均做数位提升
x[1] *= digit
i += 1
digit = 1
while i < len(chnum_str) and chnum_str[i] in list(ch_digits.keys()):
digit *= ch_digits[chnum_str[i]] # 找出连续的数位并计算乘积,例如"百万","兆亿"
i += 1
if digit > 1:
for x in segments:
if x[1] < digit: # 低于目前数位的片段均做数位提升
x[1] *= digit
else:
i += 1 # 忽略无效字符
sum = 0
for x in segments: # 计算最终数值
sum += x[0] * x[1]
return sum
if __name__ == '__main__':
while True:
s = input('请输入中文数字:')
if s == '': break
print('Result =',num_c2a(s),'\n')
print("\n=== Program Exit ===")
测试结果
请输入中文数字:三二七六八
Result = 32768
请输入中文数字:千百万
Result = 1000000000
请输入中文数字:二千五百零三万九千八百二十亿六千七百二十三万九千五百二十五
Result = 2503982067239525
请输入中文数字:十万千兆
Result = 100000000000000
请输入中文数字:三兆亿五兆七千零玖十捌
Result = 300000005007098