# -*- coding:utf-8 -*-
'''中文财务数字转换程序.例如11111,可转换为:壹万壹仟壹佰壹拾壹"万仟佰拾"就是"单位","壹"就是"数值"'''
"""由于未涉及小数的处理,这里直接补上"""
flag = 0 #默认使用大写,如需使用小写,改成1即可
import re
unitArab=(2,3,4,5,9)
unitStr=u'十百千万亿' if flag else u'拾佰仟万亿'
#单位字典unitDic,例如(2,'十')表示给定的字符是两位数,那么返回的结果里面定会包含'十'.3,4,5,9以此类推.
unitDic=dict(zip(unitArab,unitStr))
numArab=u'0123456789'
numStr=u'零一二三四五六七八九' if flag else u'零壹贰叁肆伍陆柒捌玖'
#数值字典numDic,和阿拉伯数字是简单的一一对应关系
numDic=dict(zip(numArab,numStr))
yuan_dic = {0:"圆",1:"元"}
class Arab2chz(object):
def __init__(self,s):
self.__s =s #原始数值
@classmethod
def __wrapper(cls,v) -> str:
'''在口头表达中,针对整数部分多位连续0的简写规则设计的函数例如"壹佰零零"会变为"壹佰","壹仟零零壹"会变为"壹仟零壹"这里使用classmethod的意义在于本函数与对象无关系,不需要传入对象;下同'''
if u'零零' in v:
return Arab2chz.__wrapper(v.replace(u'零零', u'零'))
return v[:-1] if v[-1] == u'零' else v # 如果最后一位为0也应该去除'
@classmethod
def __recur(cls,s,bit)->str:
'''此函数接收2个参数:1.纯数字字符串2.此字符串的长度,相当于位数'''
#如果是一位数,则直接按numDic返回对应汉字
if bit==1:
return numDic[s]
#否则,且第一个字符是0,那么省略"单位"字符,返回"零"和剩余字符的递归字符串
if s[0]==u'0':
return Arab2chz.__wrapper(u'%s%s' % (u'零',Arab2chz.__recur(s[1:],bit-1)))
#否则,如果是2,3,4,5,9位数,那么返回最高位数的字符串"数值"+"单位"+"剩余字符的递归字符串"
if bit<6 or bit==9:
return Arab2chz.__wrapper(u'%s%s%s' % (numDic[s[0]],unitDic[bit],Arab2chz.__recur(s[1:],bit-1)))
#否则,如果是6,7,8位数,那么用"万"将字符串从万位数划分为2个部分.
#例如123456就变成:12+"万"+3456,再对两个部分进行递归.
if bit<9:
return u'%s%s%s' % (Arab2chz.__recur(s[:-4],bit-4),u"万",Arab2chz.__recur(s[-4:],4))
#否则(即10位数及以上),用"亿"仿照上面的做法进行划分.
if bit>9:
return u'%s%s%s' % (Arab2chz.__recur(s[:-8],bit-8),u"亿",Arab2chz.__recur(s[-8:],8))
@classmethod
def __deal_f(cls,s,dig:int)->str:
"""param dig: 保留小数点后面的位数"""
tar=""
if dig==0:
return tar
else:
tar+="点"
for e in s:
tar+=numDic[e]
return tar
def to_ora(self,dig:int =0)->str:
"""口头表达数字"""
s = str(round(float(self.__s),dig))
if "." in self.__s and dig!=0:
self.i,self.f = s.split(".")
else:
self.i, self.f = self.__s, "" #原本为整数
pattern = re.compile("零*$") # 去除末尾多余的零
pre = Arab2chz.__deal_f(self.f,dig)
pre_rem_ze = pattern.sub("",pre)
final = pre_rem_ze if not pre_rem_ze.endswith("点") else pre_rem_ze[:-1]
return Arab2chz.__recur(self.i,len(self.i)) + final
def to_money(self,dig:int = 2)->str:
""""加入货币单位"""
s = str(round(float(self.__s), dig)) #
if "." in s and dig != 0:
self.i, self.f= s.split(".") #整数、小数
if len(self.f) < dig:
self.f += self.f + "0"*(dig-len(self.f)) #补上0
else:
self.i,self.f = self.__s,"0" * dig #此时__s本身为整数
tar = ""
s_chz = "角分"
for i in range(dig):
tar += numDic[self.f[i]] + s_chz[i]
return Arab2chz.__recur(self.i, len(self.i)) +yuan_dic[flag] + tar +"整"
def to_print(self):
"""剔除小数点,根据字符串直接打印数字"""
return "".join([numDic(i) for i in self.__s.sub("",".")])
if __name__=="__main__":
for i in range(10):
v1='9'+'0'*(i+1)
v2='9'+'0'*i+'9'
print ('%s->%s\n%s->%s'% (v1,Arab2chz(v1).to_money(),
v2,Arab2chz(v2).to_money(0)))
print('%s->%s\n%s->%s' % (v1, Arab2chz(v1).to_ora(0),
v2,Arab2chz(v2).to_ora()))
print ("566949.58648 -->",Arab2chz("566949.58648").to_money(2),"\n",
"566949.58648 -->",Arab2chz("566949.58648").to_ora(2))
print("--"*20)
-----------------结果-----------
90->玖拾圆零角零分整
99->玖拾玖圆整
90->玖拾
99->玖拾玖
900->玖佰圆零角零分整
909->玖佰零玖圆整
900->玖佰
909->玖佰零玖
9000->玖仟圆零角零分整
9009->玖仟零玖圆整
9000->玖仟
9009->玖仟零玖
90000->玖万圆零角零分整
90009->玖万零玖圆整
90000->玖万
90009->玖万零玖
900000->玖拾万圆零角零分整
900009->玖拾万零玖圆整
900000->玖拾万
900009->玖拾万零玖
9000000->玖佰万圆零角零分整
9000009->玖佰万零玖圆整
9000000->玖佰万
9000009->玖佰万零玖
90000000->玖仟万圆零角零分整
90000009->玖仟万零玖圆整
90000000->玖仟万
90000009->玖仟万零玖
900000000->玖亿圆零角零分整
900000009->玖亿零玖圆整
900000000->玖亿
900000009->玖亿零玖
9000000000->玖拾亿圆零角零分整
9000000009->玖拾亿零玖圆整
9000000000->玖拾亿
9000000009->玖拾亿零玖
90000000000->玖佰亿圆零角零分整
90000000009->玖佰亿零玖圆整
90000000000->玖佰亿
90000000009->玖佰亿零玖
566949.58648 --> 伍拾陆万陆仟玖佰肆拾玖圆伍角玖分整
566949.58648 --> 伍拾陆万陆仟玖佰肆拾玖点伍玖
-------------结束----------------