Python阿拉伯数字与中文互转

Python阿拉伯数字与中文互转

一、目标

(1)实现小数转换为中文的惯用读法。如:123.222读一百二十三点二二二。

(2)整十数和整百数等等,只读整的数位。如2000读两千,10读十。

(3)中间多个0只读一个零。如10086读一万零八十六。

(4)小于二十大于十的数习惯上不读前面的一。如12读十二。

二、源代码

对于代码的解析已写入代码的注释中,具体请参考注释。

# 数字转中文
class NTC:
    def __init__(self):
        self.dict       = {'0': '零', '1': '一', '2': '二', '3': '三', '4': '四', '5': '五', '6': '六', '7': '七',
                           '8': '八', '9': '九', '.': '点'}
        self.price      = ['元', '角', '分']
        self.base_unit  = ['千', '百', '十']
        self.level_unit = ['兆', '亿', '万']
        # 输出['千兆', '百兆', '十兆', '兆', '千亿', '百亿', '十亿', '亿', '千万', '百万', '十万', '万', '千', '百', '十']
        self.chapter_unit  = [i + j for j in self.level_unit for i in self.base_unit + ['']] + self.base_unit
        self.unit_values   = [10 ** (len(self.chapter_unit) - i) for i in range(len(self.chapter_unit))]

    # 大于0,以十进制形式输出。
    def Num_to_Chi(self, num, mode):
        change_list = []
        # 整数部分的列表
        chapter_list = []
        # 小数部分的列表
        decimal_list = []
        last_zeros = 0

        chapter = str(num)
        # ------ 分离先处理小数点后面。 ------#
        if '.' in chapter:
            # 小数部分的字符串。
            decimal = chapter[chapter.index('.') + 1:]
            # 整数部分的字符串
            integer = chapter[:chapter.index('.')]
            # 删除小数部分后的整数字符串。
            chapter = chapter[:chapter.index('.')]
            decimal_list.append(self.dict['.'])
            for d in decimal:
                decimal_list.append(self.dict[d])
        else:
            # 没有小数部分,那就只有整数部分。
            integer = num

            # ------ 将数字全部变为中文,后面再插入。 ------#
        # 这步可以不用,因为外接的函数支持整句话分离数字,已经有分离数字的设置。所以可以不用这步。
        for i in chapter:
            if i.isdigit():
                change_list.append(self.dict[i])
            else:
                pass
        # 如果是0的模式,是直接输出中文数字。
        if mode == 0:
            return ''.join(change_list)
        else:
            # ------ 得到最大位数的索引位置,该位数索引位置等于 位数的量 - (数字长度-1)。 ------#
            d = len(self.chapter_unit) - (len(change_list) - 1)
            # ------ 去除末尾多余的零。以实现100为一,110为,一一。 ------#
            if float(integer) % 10 == 0:
                for zero in change_list[::-1]:
                    if zero == '零':
                        last_zeros += 1
                    else:
                        break
                change_list = change_list[:-last_zeros]
            # ------ 筛选掉末尾的零的位数,即100为百,1000为千,1100为千百。而110为百十 ------#
            if last_zeros - 1 > 0:
                cu = self.chapter_unit[d:-(last_zeros - 1)]
            else:
                cu = self.chapter_unit[d:]
            # ------ 依次交叉录入,先录入数字再接位数。 ------#
            # 按照习惯,中间为零的时候是不读的。如10010,读成一万零一十。n作为录入过零后面还有零的提示参数,是过度变量。
            n = 0
            for i in range(len(cu)):
                if change_list[i] == '零':
                    if n == 0:
                        n += 1
                        chapter_list.append('零')
                    else:
                        pass
                else:
                    # 遇到数字后中间量归零。
                    n = 0
                    chapter_list.append(change_list[i])
                    chapter_list.append((cu[i]))
            # 如果最后一个是零则不需要把个位数录入,不是要录入个位。
            if last_zeros > 0:
                pass
            else:
                chapter_list.append(change_list[-1])
            # 按照习惯,像12,13,10这种读十二、十三、十,不读1。设置了model为2时关闭。
            if float(num) > 20 or mode == 2:
                pass
            elif float(num) > 10:
                chapter_list = chapter_list[1:]
            return ''.join(chapter_list + decimal_list)

    def Chi_to_Num(self, Chi):
        values = self.dict.values()
        cha_val_list = list(values)
        Chi_num_list = []
        for i in cha_val_list:
            if i in Chi:
                # 将所有中文数字和小数点替换成数字类。
                Chi = Chi.replace(i, [k for k, v in self.dict.items() if v == i][0])
        # 标记数字段的中间量
        start = 0
        end   = 0
        sign  = 0
        for i in range(len(Chi)):
            # 获取数字段的开始位置,如果是数位开始,一定是十位数为1的两位数。
            if Chi[i] in self.dict and sign == 0:
                start = i
                sign += 1
            # 当匹配到的数既不是数字也不是数位,且标志不为0,则是数字段的结束。
            elif Chi[i] not in self.dict and Chi[i] not in self.chapter_unit and sign != 0:
                sign  = 0
                end   = i
                Chi_num_list.append((Chi[start:end],(start,end)))
            # 匹配到数位开始的情况,即十位数为1的两位数。
            elif Chi[i] in self.chapter_unit and sign == 0:
                start = i
                end   = i+2
                Chi_num_list.append((Chi[start:end],(start,end)))
            # 整个字符串都是数字段的情况。
            elif i == len(Chi) - 1:
                end   = i + 1
                Chi_num_list.append((Chi[start:end], (start, end)))

        for c in Chi_num_list:
            # 分离小数部分。没有小数部分则为0。
            if '.' in c[0]:
                # 因为从这里分离了小数点,后面如果粘连了其他非数字,就得遍历判别,然后分离。
                decimal_list = c[0][c[0].index('.'):]
                for d in range( len(decimal_list) ):  # 小数点的位置开始。
                    if decimal_list[d].isdigit():f = d + 1  # 索引获取最后一个要加1。
                decimal = float(decimal_list[decimal_list.index('.'):f])
                # 个位数,针对整百等情况。
                if c[0][c[0].index('.') - 1].isdigit():bit = int(c[0][c[0].index('.') - 1])
                else:bit = 0
            else:
                decimal = 0
                # 个位数。
                if c[0][-1].isdigit():bit = int(c[0][-1])
                else:bit=0

            # 遍历位数,匹配到就直接开始运算和循环相加。
            result = 0  # 初始化最初结果。
            for i in range(len(self.chapter_unit)):
                if self.chapter_unit[i] in c[0]:
                    # 检索位数的位置
                    Chi_index = c[0].index(self.chapter_unit[i])
                    # 位数前一定是个数字,所以位数对应的值乘以这个数字。除了十,前面可能还要补一。
                    if Chi_index == 0:
                        result = self.unit_values[i]
                    else:
                        result = int(c[0][Chi_index - 1]) * self.unit_values[i] + result
            # print('1',result)
            result = result + bit + decimal
            # print('2', result)
            # print('3',Chi)
            Chi = Chi.replace(Chi[c[1][0]:c[1][1]],str(result))
            # print('4',Chi)
        return Chi



'''
mode = 0或n n指其他数字,为只将数字硬转成中文。
mode = 1 为日常的数字读法。
mode = 2 关闭十属数的习惯性纠正,11读为一十一。
'''

def Num_to_Chi(num, model=1):
    ntc = NTC()
    # 传入文段如果多个数字段。
    nums_list = []
    # 中间量
    num_list = []  # 用于存储一个数字段。
    no_num = 0  # 用于判断是否匹配了一个数字段。
    num = str(num)
    for i in num + 'e':  # 加个e作为结束的符号,防止输入只有数字,else阶段直接跳过没输入到nums_list里。
        # 将匹配到的数字放入列表中。
        if i in ntc.dict.keys():
            num_list.append(i)
            no_num = 1
        else:
            # 如果有数字段,添加到列表内,待转换。
            if no_num == 1:
                nums_list.append((''.join(num_list)))
                no_num = 0
                num_list = []
            else:
                pass
    if nums_list:
        for l in nums_list:
            chi_num = ntc.Num_to_Chi(l, model)
            num = num.replace(l, chi_num)
    return num


def Chi_to_Num(Chi):
    ntc  = NTC()
    NChi = Chi
    # ------ 筛选输入的字符串里的数字内容,排除数字干扰。 ------ #
    for i in Chi:
        if i.isdigit():
            NChi = NChi.replace(i,"|")
    if "|" in NChi:
        Chi_list = NChi.split("|")
    else:
        Chi_list = [Chi]
    for i in range(len(Chi_list)):
        _l = ntc.Chi_to_Num(Chi_list[i])
        if _l != '':
            Chi = Chi.replace(Chi_list[i],_l)
    return Chi


# 数字转中文测试
# print("********数字转中文测试********")
# # 日常模式。
# print("单个数字",Num_to_Chi(1))  # 单个数字
# print("单个字符数字",Num_to_Chi('1'))  # 单个字符数字
# print("十位数为1的数字",Num_to_Chi(12))
# print("整百数",Num_to_Chi(400))
# print("整百数小数",Num_to_Chi(400.202))
# print("附带其他的字符串",Num_to_Chi('s12.225元244了'))
# # 硬转模式
# print("十位数为1的数字",Num_to_Chi(12,0))
'''
结果
单个数字 一
单个字符数字 一
十位数为1的数字 十二
整百数 四百
整百数小数 四百点二零二
附带其他的字符串 s十二点二二五元二百四十四了
十位数为1的数字 一二
'''

# 中间多个零也无所谓,两者输出一样 100000200.448
print("********中文转数字测试********")
print("无输入",Chi_to_Num(''))
print("单个数字",Chi_to_Num('一'))
print("携带阿拉伯数字的字符串",Chi_to_Num('12一'))
print("十位数为1的两位数",Chi_to_Num('十一'))
print("普通的两位数",Chi_to_Num('四十一'))
print("整百",Chi_to_Num('四百'))
print("整百小数",Chi_to_Num('四十点二二'))
print("中间有零和周围有其他字符",Chi_to_Num('你好,总共一亿零二百零三点四四八元'))
print("中间多个零也没关系",Chi_to_Num('一共一亿零零二百零三点四四八元'))
'''
结果
无输入 
单个数字 1
携带阿拉伯数字的字符串 121
十位数为1的两位数 11
普通的两位数 41
整百 400
整百小数 40.22
中间有零和周围有其他字符 你好,总共100000203.448元
中间多个零也没关系 1共100000203.448元
'''

三、后续

对于想要实现中文大写与数字互转,请自行修改其中的中文对应的数。

而只是代码仍有一定的局限性,最好是打包成exe,更加方便于使用。后续笔者再进行打包。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值