1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
ch_num = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
ch_num = dict(zip('0123456789', ch_num))
ch_unit = ['', '万', '亿']
ch_unit = dict(zip(range(3), ch_unit))
def convert_int(intPart):
""" 转换整数部分
intPart: str
return: str
"""
if len(intPart) <= 4:
# 若长度小于 4, 则补足到 4 位。
ans = [ch_num[c] for c in '0'*(4-len(intPart))+intPart]
if ans[-1] == ch_num['0']:
ans = '{}仟{}佰{}拾'.format(*ans[:-1])
else:
ans = '{}仟{}佰{}拾{}'.format(*ans)
# 处理中间有 0 的情况
ans = ans.replace('零仟', ch_num['0'])
ans = ans.replace('零佰', ch_num['0'])
ans = ans.replace('零拾', ch_num['0'])
# 处理中间连续多个 0,末尾有零的情况
ans = re.sub('零+', ch_num['0'], ans)
ans = re.sub('零+$', ch_unit[0], ans)
# 若开头有 0 且整数部分长度小于 4,则丢弃开头的’零‘(只有 1 个)。
return ans[4!=len(intPart):]
else:
# 金额数字长度可以写成 n = 4 * u + r
u, r = len(intPart) // 4, len(intPart) % 4
# 若 r = 0,则 u = u - 1,至少先处理开头 4 位。之后再看 u,
# 若 u > 2,则先处理不包括最后 8 位的部分,否则就先只处理开头 4 位。
i = r * (r != 0) + 4 * (max(u - 2 - (r == 0), 0) + (r == 0))
# 于是分成两部分递归处理 intPart[:i] 和 intPart[i:]
left, right = convert_int(intPart[:i]), convert_int(intPart[i:])
# 若左部分返回空字符串 '',则不加单位,即 j = 0 and ch_unit[j] = ''。
# 又因为最大单位为“亿”,所以 0 <= j <= 2
j = min(u - (r == 0), 2) if left else 0
# 得到单位
unit = ch_unit[j]
# 返回最终结果
return '{}{}{}'.format(left, unit, right)
def convert_decimal(decimalPart):
""" 处理小数部分,容易多了
decimalPart: str
return: str
"""
ans = [ch_num[c] for c in decimalPart + '0' * (2 - len(decimalPart))]
ans = '{}角{}分'.format(*ans)
ans = ans.replace('零角', ch_num['0'])
ans = ans.replace('零分', ch_unit[0])
ans = re.sub('零+$', ch_unit[0], ans)
# 因为使用递归处理整数部分,所以整数部分单位“元”放在这里处理。
return '元{}'.format(ans or '整')
def convert_RMB(money):
""" 将浮点数转换为大写人民币规范读法
money: str
return: str
"""
if '.' in money:
intPart, decimalPart = money.split('.')
else:
intPart, decimalPart = money, ch_unit[0]
return '人民币{}{}'.format(convert_int(intPart), convert_decimal(decimalPart))
|