chinapnr / fishbase

自主开发、整理的一套 Python 基础函数库,涵盖 system 系统增强包、logger 日志记录增强包、file 文件处理增强包、 date 日期处理函数包、data 数据信息处理函数包、csv 处理增强函数包、crypt 加密/编码增强包等,可减少程序开发工作量、降低引用复杂度。
MIT License
94 stars 29 forks source link

将阿拉伯金额数字转化为大写金额数据 #235

Closed jacsonking closed 5 years ago

jacsonking commented 5 years ago

例如: 12345.00->壹万贰仟叁佰肆拾伍圆整; 12.34->拾贰圆叁角肆分。

mindjun commented 5 years ago

做出如下限定:

mindjun commented 5 years ago

提供静态方法 an2cn 和 cn2an 实现阿拉伯数字金额和中文大写金额的相互转换。 实现代码如下:

class RMBConversion(object):
    arab_number_max_len = 19
    upper_chinese_number = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
    unit_dict = {'1': '拾',
                 '2': '佰',
                 '3': '仟'}
    # 需要倒序拼接,所以是 '亿万'
    unit_list = ['万', '亿', '亿万']

    unit_list1 = ['万', '亿', '万亿']

    an_2_cn_dict = {str(k): v for k, v in zip(range(10), upper_chinese_number)}
    cn_2_an_dict = dict(zip(an_2_cn_dict.values(), an_2_cn_dict.keys()))

    @staticmethod
    def an2cn(arabic_amount):
        try:
            float(arabic_amount)
            arabic_amount = str(arabic_amount)
        except ValueError as _:
            raise ValueError('error arabic_amount : {}'.format(arabic_amount))
        if len(arabic_amount) > RMBConversion.arab_number_max_len:
            raise ValueError('len of arabic_amount should less than {}'.
                             format(RMBConversion.arab_number_max_len))
        if '.' not in arabic_amount:
            arabic_amount += '.'
        integer, decimals = arabic_amount.split('.')

        if len(decimals) > 2:
            raise ValueError('decimals error')

        reverse_integer_str = ''
        unit_step = 0
        for index, item in enumerate(integer[::-1]):
            if index != 0 and index % 4 == 0:
                reverse_integer_str += RMBConversion.unit_list[unit_step]
                unit_step += 1
            if item != '0':
                reverse_integer_str += RMBConversion.unit_dict.get(str(index % 4), '')
            reverse_integer_str += RMBConversion.an_2_cn_dict.get(item)

        chinese_amount = reverse_integer_str[::-1]
        # 整数最后部分加 圆
        chinese_amount += '圆'

        if len(decimals) == 0 or decimals in ['0', '00']:
            chinese_amount += '整'
        else:
            chinese_amount += RMBConversion.an_2_cn_dict.get(decimals[0])
            chinese_amount += '角'
            if len(decimals) > 1 and decimals[1] != '0':
                chinese_amount += RMBConversion.an_2_cn_dict.get(decimals[1])
                chinese_amount += '分'
        return chinese_amount

    @staticmethod
    def cn2an(chinese_amount):
        all_unit = (RMBConversion.unit_list1 +
                    list(RMBConversion.unit_dict.values()) +
                    ['圆', '整', '角', '分'])
        arabic_amount = ''
        for i in chinese_amount:
            if i == '角':
                arabic_amount = ''.join([arabic_amount[:-1], '.', arabic_amount[-1]])
            if i in all_unit:
                continue
            try:
                arabic_amount += RMBConversion.cn_2_an_dict[i]
            except KeyError as _:
                raise ValueError('error chinese_amount {}'.format(chinese_amount))
        # 补充为两位小数表示
        if '.' not in arabic_amount:
            arabic_amount += '.00'
        if len(arabic_amount.split('.')[-1]) != 2:
            arabic_amount += '0'
        return arabic_amount
itaa commented 5 years ago

这个功能挺好,类名需要再考虑一下,功能是人民币的数字和大写的转换,AmountNotationConversion 表达的意思不对,参考:RMBConversion

mindjun commented 5 years ago

代码已更新,并修复大写中文转阿拉伯数字表示的错误

jacsonking commented 5 years ago

金额数字转大写时有点不符合逻辑。 例如: 输入:12000.01 实际输出:壹万贰仟零零零圆零角壹分 期待输出:壹万贰仟圆零角壹分