字符串专题之中文大写金额数字转换工具
共 5335字,需浏览 11分钟
·
2021-06-11 11:13
说在前面
《数据与数据结构》是高中信息技术新教材选择性必修的一个重要组成部分,最近笔者在研究其中的一些内容,并尝试编写了一些题目与大家分享。
由于新教材是块新大陆,我们都是在摸索前行,加之本人水平有限,在描述题目用语和控制题目难度方面都存在不足,敬请大家批评指正。
12.(开放题)中文大写金额数字转换工具,可将输入的阿拉伯数字转换为中文大写金额数字。中文大写金额数字包括壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样。如下图所示:
人民币大写的正确写法:
一、中文大写金额数字前应标明“人民币”字样;
二、中文大写金额数字到“元”为止的,在“元”之后应写“整”;在“角”和“分”后面不写“整”字;
三、阿拉伯数字小写金额数字中有“0”时,中文大写应按照汉语语言规律、金额数字构成和防止涂改的要求进行书写。举例如下:
1、阿拉伯数字中间有“0”时,中文大写要写“零”字,如¥1409.50应写成人民币壹仟肆佰零玖元伍角;
2、阿拉伯数字中间连续有几个“0”时、中文大写金额中间可以只写一个“零”字,如¥6007.14应写成人民币陆仟零柒元壹角肆分。
3、阿拉伯金额数字万位和元位是“0”,或者数字中间连续有几个“0”,万位、元位也是“0”,但千位、角位不是“0”时,中文大写金额中可以只写一个零字,也可以不写“零”字,如¥1680.32应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分;又如¥107000.53应写成人民币壹拾万柒仟元伍角叁分,或者写成人民币壹拾万零柒仟元伍角叁分。
4、阿拉伯金额数字角位是“0”而分位不是“0”时,中文大写金额“元”后面应写“零”字,如¥16409.02应写成人民币壹万陆仟肆佰零玖元零贰分。
我们定义了一个自定义函数change (),它的功能是将输入的金额小写数字转换成人民币中文大写金额数字,其函数头说明如下:
函数功能:将小写数字转换成人民币中文大写金额数字。
函数名:change(num)
参数表:num – 输入的金额小写数字(整数或小数均可)。
返回值:人民币中文大写金额数字。
示例1:num=2305时,返回'人民币贰仟叁佰零伍元整';
示例2:num=108000.03时,返回'人民币壹拾万捌仟元零叁分'或'人民币壹拾万零捌仟元零叁分'。
请补充缺失的代码,并思考是否有其他实现方法:
def change(num):
max_num = 1000000000000 #最大转换金额数
if num >= max_num:
return "数额太大,数字需低于一万亿!"
units = "元拾佰仟万拾佰仟亿拾佰仟万拾佰仟"
digits = "零壹贰叁肆伍陆柒捌玖"
num = f'{num:0.2f}'
integral, decimal =num.split(".") #分成整数和小数两个部分
ans = ""
flag = ①
for i, d in enumerate(integral): #处理整数部分
n = len(integral) - 1 - i #数字下标从高位开始数,单位下标从低位开始数
if d == "0": #出现多个0时,并非输出所有的"零",需特殊处理"亿"和"万"位
if ((units[n]=="亿" or units[n]=="万") and ((i>=1 and integral[i-1]!='0') or (i>=2 andintegral[i-2]!='0') or (i>=3 and integral[i-3]!='0'))):
ans += units[n]
flag = True
else:
if flag:
ans += "零"
ans += ②
flag = False
if ans != "" and integral[-1] =="0":#个位为0的特殊情况
ans += "元"
if decimal == "00":
ans += "整"
elif decimal[1] == "0":
ans += digits[int(decimal[0])] + "角"
elif decimal[0] == "0":
ans += "零" + digits[int(decimal[1])] + "分"
else:
ans += ③
return "人民币" + ans
答案:
解析:
其他解法(一):
算法思想与题目算法相似,程序显示结果也一样,区别在于存储单位的数据结构不一样,本算法将倍率分成万以下单位和万以上单位,其中低倍率可以加在高倍率之前,例如拾万、佰亿等。题目程序是直接使用下标定位"亿"和"万"位之前的低倍率单位,使用判断语句决定输出"亿"和"万";本程序是利用divmod函数求出万以下单位和万以上单位对应下标,再分别处理。
def change2(num):
max_num = 1000000000000
if num >= max_num:
return "数额太大,数字需低于一万亿!"
digits = ["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"]
low_radices = ["","拾","佰","仟"]
high_radices = ["","万","亿"]
num = f'{num:0.2f}'
integral, decimal = num.split(".")
ans = ""
zero_count = 0
for i, d in enumerate(integral): #处理整数部分
ph, pl = divmod(len(integral) - 1 - i, 4)
if d == "0":
zero_count += 1
else:
if zero_count > 0:
ans += "零"
zero_count = 0
ans += digits[int(d)] + low_radices[pl]
if pl == 0 and zero_count < 4:
ans += high_radices[ph]
if ans != "":
ans += "元"
if decimal == "00":
ans += "整"
elif decimal[1] == "0":
ans += digits[int(decimal[0])] + "角"
elif decimal[0] == "0":
ans += "零" + digits[int(decimal[1])] + "分"
else:
ans += digits[int(decimal[0])] + "角" + digits[int(decimal[1])] + "分"
return "人民币" + ans
其他解法(二):
算法思想较前面两种更巧妙,但程序显示结果略有不同(少了一些不必要的零)。程序的巧妙之处在于把零的读法存储在数组zero中,与单位数组units一一对应,这样无需另外再做判断,直接把单位或零拼接到结果字符串即可;除此以外,程序无需将整数和小数分开处理,只需去掉小数点,依次处理各个数字即可。由此付出的代价是需要在拼接结束后,专门处理多余的零或单位,较难理解,也容易出错。
def change3(num):
max_num = 1000000000000 #最大转换金额数
if num >= max_num:
return "数额太大,数字需低于一万亿!"
units = "分角元拾佰仟万拾佰仟亿拾佰仟"
digit = "零壹贰叁肆伍陆柒捌玖"
zero = "整零元零零零万零零零亿零零零" #零的读法
num = f'{num:0.2f}'.replace('.', '') #去掉小数点
ans = ""
for i, c in enumerate(num[::-1]):
if c == '0': #按照零的读法拼接零
ans = zero[i] + ans
else:
ans = digit[int(c)] + units[i] + ans
#print(ans)
i = 1
while i < len(ans): #消除多余的零
if ans[i-1]=="零" and ans[i] in "亿万零元整":
ans = ans[:i-1] + ans[i:]
else:
i += 1
ans = ans.replace('亿万', '亿') #消除'亿万'的'万'
ans = ans.replace('角整', '角') #消除'角整'的'整'
if ans[0] == "元": ans = ans[1:]#消除多余的'元'
return "人民币" + ans
拓展思考:
本公众号的原创文章都是本人平时工作和学习的一些心得体会文章,虽然经过长期认真地思考方才下笔,但由于笔者水平有限,难免出现一些错漏,敬请批评指正。
无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!
需要本文word版和拓展思考答案的,可以加入“Python算法之旅”知识星球参与讨论和下载文件,“Python算法之旅”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注Python算法,感兴趣就一起来!
相关优秀文章: