使用最熟悉的语言,实现一个简单的阿拉伯数字转换为中文大写人民币文字的算法。说明:
- 数字不超过10亿,单位是圆;
- 可能包含小数,小数部分不超过两位,一位时单位是角,两位是单位分别是角分,没有小数时应在最后加上“整”;
- 数字中间可能出现连续的0,应按照中文习惯只保留一个或者不保留零(均可)
- 阿拉伯数字的表示问题:
- 将int或float型的数字作为输入,这样方便验证输入的合法性。
- 将输入的数字转换为格式统一的字符串。可以使用
'%015.2f' % num
来进行格式化,来保证所有的合法输入都可以被转换为格式统一的字符串,方便后续处理。 - 将整数部分的数字字符以如下的方式保存:
(['0','0','0','0'],['0','0','0','0'],['0','0','0','0'])
例如'409685210.34'的整数部分就可以保存为:
(['0','0','0','4'],['0','9','6','8'],['5','2','1','0'])
将数字每4个分为1组的原因是在中文里我们将个十百千作为一个小的单位,然后在这些小的单位后加上万亿等更大的单位。这样我们可以用相同的方式来处理每个分组内的元素,最后再处理分组。 - 将小数部分的数字以
['0','0']
的形式保存。
- 阿拉伯数字与中文数字的对应问题:
建立一个字典,字典的key为'0''9',对应的值为'零'‘玖’。在后续问题中使用查表的方式将阿拉伯数字替换为中文数字。 - 由于整数部分和小数部分的单位不同,而且两部分的处理方式也不同,因此可以将整数部分和小数部分单独处理,再将处理结果合并。
我们已经将整数部分的数字字符存储于元组,3个元组对应的单位分别为('亿','万','')
,元组内列表对应的单位分别为('仟','佰','拾','')
。
- 根据建立的阿拉伯数字与中文数字对照字典,我们可以查到整数元组中所有元素的中文字符。
- 对于整数元组中列表中的每个字符,如果该字符不为零,则为其添加
('仟','佰','拾','')
单位。(因为零后面加单位是无意义的) - 对于整数元组中的每个列表,如果不是列表元素全为零,则为其添加
('亿','万','')
单位。 - 将所有替换后中文字符合成一个unicode字符串,并返回。
通过上面的步骤,我们可以得到一个整数部分的unicode字符,如(['0','0','0','0'],['3','0','1','0'],['3','0','3','0'])
经过上述步骤后将会得到零零零零叁仟零壹拾零叁仟零叁拾零
。
我们可以根据零所在的位置,来将零划分为如下的3种类型:
- 前导零
- 字符串开头的零
- 以
亿
,万
开头的零
- 后缀零
- 字符串结尾的零
- 以
亿
,万
结尾的零
- 普通零
除去上述两种情况的零
根据我们的书写习惯我们可以确定前导零、后缀零是没有任何意义的,连续的普通零只留1个即可。
所以我们可以先通过正则表达式来匹配前导零和后缀零并将其替换为空字符,再用正则表达式来匹配连续零并将其替换为单个零。
小数部分的处理要比整数部分简单很多。我们的小数部分是存储在链表['0','0']
中的,我们只需要判断链表中的元素是否为零,如果不为零则通过查表得到其中文字符并为其加上单位'('角','分')'后加入小数字符串即可。例:['0','0'] -> ''
['0','1'] -> 壹分
。
由于小数部分不存在多余零的情况,所以小数部分不需要做多余零的处理。
我们已经得到了整数部分和小数部分的中文字符串,接下来只需要经过简单的判断来合成一个字符串即可:
- 小数部分为空
返回 整数部分+'圆整'。 - 小数部分不为空
返回 整数部分+'圆'+小数部分。