字符串專(zhuān)題之中文大寫(xiě)金額數(shù)字轉(zhuǎn)換工具
說(shuō)在前面
《數(shù)據(jù)與數(shù)據(jù)結(jié)構(gòu)》是高中信息技術(shù)新教材選擇性必修的一個(gè)重要組成部分,最近筆者在研究其中的一些內(nèi)容,并嘗試編寫(xiě)了一些題目與大家分享。
由于新教材是塊新大陸,我們都是在摸索前行,加之本人水平有限,在描述題目用語(yǔ)和控制題目難度方面都存在不足,敬請(qǐng)大家批評(píng)指正。

12.(開(kāi)放題)中文大寫(xiě)金額數(shù)字轉(zhuǎn)換工具,可將輸入的阿拉伯?dāng)?shù)字轉(zhuǎn)換為中文大寫(xiě)金額數(shù)字。中文大寫(xiě)金額數(shù)字包括壹、貳、叁、肆、伍、陸、柒、捌、玖、拾、佰、仟、萬(wàn)、億、元、角、分、零、整等字樣。如下圖所示:

人民幣大寫(xiě)的正確寫(xiě)法:
一、中文大寫(xiě)金額數(shù)字前應(yīng)標(biāo)明“人民幣”字樣;
二、中文大寫(xiě)金額數(shù)字到“元”為止的,在“元”之后應(yīng)寫(xiě)“整”;在“角”和“分”后面不寫(xiě)“整”字;
三、阿拉伯?dāng)?shù)字小寫(xiě)金額數(shù)字中有“0”時(shí),中文大寫(xiě)應(yīng)按照漢語(yǔ)語(yǔ)言規(guī)律、金額數(shù)字構(gòu)成和防止涂改的要求進(jìn)行書(shū)寫(xiě)。舉例如下:
1、阿拉伯?dāng)?shù)字中間有“0”時(shí),中文大寫(xiě)要寫(xiě)“零”字,如¥1409.50應(yīng)寫(xiě)成人民幣壹仟肆佰零玖元伍角;
2、阿拉伯?dāng)?shù)字中間連續(xù)有幾個(gè)“0”時(shí)、中文大寫(xiě)金額中間可以只寫(xiě)一個(gè)“零”字,如¥6007.14應(yīng)寫(xiě)成人民幣陸仟零柒元壹角肆分。
3、阿拉伯金額數(shù)字萬(wàn)位和元位是“0”,或者數(shù)字中間連續(xù)有幾個(gè)“0”,萬(wàn)位、元位也是“0”,但千位、角位不是“0”時(shí),中文大寫(xiě)金額中可以只寫(xiě)一個(gè)零字,也可以不寫(xiě)“零”字,如¥1680.32應(yīng)寫(xiě)成人民幣壹仟陸佰捌拾元零叁角貳分,或者寫(xiě)成人民幣壹仟陸佰捌拾元叁角貳分;又如¥107000.53應(yīng)寫(xiě)成人民幣壹拾萬(wàn)柒仟元伍角叁分,或者寫(xiě)成人民幣壹拾萬(wàn)零柒仟元伍角叁分。
4、阿拉伯金額數(shù)字角位是“0”而分位不是“0”時(shí),中文大寫(xiě)金額“元”后面應(yīng)寫(xiě)“零”字,如¥16409.02應(yīng)寫(xiě)成人民幣壹萬(wàn)陸仟肆佰零玖元零貳分。
我們定義了一個(gè)自定義函數(shù)change (),它的功能是將輸入的金額小寫(xiě)數(shù)字轉(zhuǎn)換成人民幣中文大寫(xiě)金額數(shù)字,其函數(shù)頭說(shuō)明如下:
函數(shù)功能:將小寫(xiě)數(shù)字轉(zhuǎn)換成人民幣中文大寫(xiě)金額數(shù)字。
函數(shù)名:change(num)
參數(shù)表:num – 輸入的金額小寫(xiě)數(shù)字(整數(shù)或小數(shù)均可)。
返回值:人民幣中文大寫(xiě)金額數(shù)字。
示例1:num=2305時(shí),返回'人民幣貳仟叁佰零伍元整';
示例2:num=108000.03時(shí),返回'人民幣壹拾萬(wàn)捌仟元零叁分'或'人民幣壹拾萬(wàn)零捌仟元零叁分'。
請(qǐng)補(bǔ)充缺失的代碼,并思考是否有其他實(shí)現(xiàn)方法:
def change(num):max_num = 1000000000000 #最大轉(zhuǎn)換金額數(shù)if num >= max_num:return "數(shù)額太大,數(shù)字需低于一萬(wàn)億!"units = "元拾佰仟萬(wàn)拾佰仟億拾佰仟萬(wàn)拾佰仟"digits = "零壹貳叁肆伍陸柒捌玖"num = f'{num:0.2f}'integral, decimal =num.split(".") #分成整數(shù)和小數(shù)兩個(gè)部分ans = ""flag = ①for i, d in enumerate(integral): #處理整數(shù)部分n = len(integral) - 1 - i #數(shù)字下標(biāo)從高位開(kāi)始數(shù),單位下標(biāo)從低位開(kāi)始數(shù)if d == "0": #出現(xiàn)多個(gè)0時(shí),并非輸出所有的"零",需特殊處理"億"和"萬(wàn)"位if ((units[n]=="億" or units[n]=="萬(wà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 = Trueelse:if flag:ans += "零"ans += ②flag = Falseif ans != "" and integral[-1] =="0":#個(gè)位為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
答案:
解析:
其他解法(一):
算法思想與題目算法相似,程序顯示結(jié)果也一樣,區(qū)別在于存儲(chǔ)單位的數(shù)據(jù)結(jié)構(gòu)不一樣,本算法將倍率分成萬(wàn)以下單位和萬(wàn)以上單位,其中低倍率可以加在高倍率之前,例如拾萬(wàn)、佰億等。題目程序是直接使用下標(biāo)定位"億"和"萬(wàn)"位之前的低倍率單位,使用判斷語(yǔ)句決定輸出"億"和"萬(wàn)";本程序是利用divmod函數(shù)求出萬(wàn)以下單位和萬(wàn)以上單位對(duì)應(yīng)下標(biāo),再分別處理。
def change2(num):max_num = 1000000000000if num >= max_num:return "數(shù)額太大,數(shù)字需低于一萬(wàn)億!"digits = ["零","壹","貳","叁","肆","伍","陸","柒","捌","玖"]low_radices = ["","拾","佰","仟"]high_radices = ["","萬(wàn)","億"]num = f'{num:0.2f}'integral, decimal = num.split(".")ans = ""zero_count = 0for i, d in enumerate(integral): #處理整數(shù)部分ph, pl = divmod(len(integral) - 1 - i, 4)if d == "0":zero_count += 1else:if zero_count > 0:ans += "零"zero_count = 0ans += 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
其他解法(二):
算法思想較前面兩種更巧妙,但程序顯示結(jié)果略有不同(少了一些不必要的零)。程序的巧妙之處在于把零的讀法存儲(chǔ)在數(shù)組zero中,與單位數(shù)組units一一對(duì)應(yīng),這樣無(wú)需另外再做判斷,直接把單位或零拼接到結(jié)果字符串即可;除此以外,程序無(wú)需將整數(shù)和小數(shù)分開(kāi)處理,只需去掉小數(shù)點(diǎn),依次處理各個(gè)數(shù)字即可。由此付出的代價(jià)是需要在拼接結(jié)束后,專(zhuān)門(mén)處理多余的零或單位,較難理解,也容易出錯(cuò)。
def change3(num):max_num = 1000000000000 #最大轉(zhuǎn)換金額數(shù)if num >= max_num:return "數(shù)額太大,數(shù)字需低于一萬(wàn)億!"units = "分角元拾佰仟萬(wàn)拾佰仟億拾佰仟"digit = "零壹貳叁肆伍陸柒捌玖"zero = "整零元零零零萬(wàn)零零零億零零零" #零的讀法num = f'{num:0.2f}'.replace('.', '') #去掉小數(shù)點(diǎn)ans = ""for i, c in enumerate(num[::-1]):if c == '0': #按照零的讀法拼接零ans = zero[i] + anselse:ans = digit[int(c)] + units[i] + ans#print(ans)i = 1while i < len(ans): #消除多余的零if ans[i-1]=="零" and ans[i] in "億萬(wàn)零元整":ans = ans[:i-1] + ans[i:]else:i += 1ans = ans.replace('億萬(wàn)', '億') #消除'億萬(wàn)'的'萬(wàn)'ans = ans.replace('角整', '角') #消除'角整'的'整'if ans[0] == "元": ans = ans[1:]#消除多余的'元'return "人民幣" + ans
拓展思考:
本公眾號(hào)的原創(chuàng)文章都是本人平時(shí)工作和學(xué)習(xí)的一些心得體會(huì)文章,雖然經(jīng)過(guò)長(zhǎng)期認(rèn)真地思考方才下筆,但由于筆者水平有限,難免出現(xiàn)一些錯(cuò)漏,敬請(qǐng)批評(píng)指正。
無(wú)論是贊同還是反對(duì)我的看法,都請(qǐng)你給我留言。如果你有新的想法,千萬(wàn)不要憋在心里,請(qǐng)發(fā)出來(lái)大家一起討論。讓我們相互學(xué)習(xí),共同進(jìn)步!
需要本文word版和拓展思考答案的,可以加入“Python算法之旅”知識(shí)星球參與討論和下載文件,“Python算法之旅”知識(shí)星球匯集了數(shù)量眾多的同好,更多有趣的話(huà)題在這里討論,更多有用的資料在這里分享。
我們專(zhuān)注Python算法,感興趣就一起來(lái)!
相關(guān)優(yōu)秀文章:
