题目的主要信息:
- 将输入的两位小数的数字人民币转换成中文表示的人民币
- 中文大写金额数字前应标明“人民币”字样
- 中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写
- 中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如果小数为0
- 阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字
- 10应写作“拾”,100应写作“壹佰”
- 十万以上的数字接千不用加“零”
方法一:迭代
具体做法:
我们用字符串的形式来接收输入的数字(和将输入的double型数字转变成字符串一样),然后遍历字符串找到小数点的位置,根据小数点的位置截取字符串的整数部分和小数部分。
对于整数部分,我们用表示字符串每个字符的下标,从0开始,用表示该字符位于这个数字的哪一位,从s.length() - 1
开始,下标不断向右递增,而位数则相应递减。处理的时候我们依次处理,优先判断该位字符是否为0,不为0再输出,同时如果位数位于十位且该位为1,则不需要输出,因为我们不要壹拾。然后通过依次判断属于哪一位,根据所属哪一位输出相应的字符,如可以根据对8取余为0决定亿位,对4取余为0决定万位,对4取余为3决定千位,对4取余为2决定百位,对4取余为1决定十位,同时注意万千百后一位如果为零,需要接一个零。最后如果整数部分第一个字符就是0,那么就不用输出元了,没有整数部分,否则需要输出元。
对于小数部分,如果小数部分是两个0,则无小数,输出整,否则要相应判断小数角与分是否为0,输出或者不输出相应的项。
#include<iostream>
#include<string>
#include<vector>
using namespace std;
const vector<string> num = {"","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
int main(){
string money;
while(cin >> money){
int p = 0;
while(money[p] != '.') //根据小数点划分
p++;
string s = money.substr(0, p); //处理小数点前的
string res = "人民币";
for(int i = s.length() - 1, j = 0; i >= 0; i--, j++){ //i表示这是数字的第几位,j表示字符串下标
if(s[j] != '0'){ //不为0要输出
if(!(s[j] == '1' && i % 4 == 1)) //输出跳过一拾前面的1
res += num[s[j] - '0'];
}
if(i != 0){
if(i % 8 == 0 && i >= 8) //处理输出亿位
res += "亿";
if(i % 4 == 0 && i % 8 != 0){ //处理输出万位
res += "万";
if(s[j + 1] == '0') //处理千位为0的情况
res += "零";
}
if(i % 4 == 3 && s[j] != '0'){ //处理千位
res += "仟";
if(s[j + 1] == '0' && s[j + 2] != '0') //百位为0
res += "零";
}
if(i % 4 == 2 && s[j] != '0'){ //处理百位
res += "佰";
if(s[j + 1] == '0' && s[j + 2] != '0') //十位为0
res += "零";
}
if(i % 4 == 1 && s[j] != '0') //输出十位
res += "拾";
}
}
if(s[0] != '0') //整数部分有才输出元
res += "元";
s = money.substr(p + 1); //处理小数部分
if(s == "00") //小数全0,元整
res += "整";
else{
if(s[0] == '0'){ //角为0
res += num[s[1] - '0'];
res += "分";
}
else if(s[1] == '0'){ //分为0
res += num[s[0] - '0'];
res += "角";
}
else{ //角和分都有
res += num[s[0] - '0'] + "角";
res += num[s[1] - '0'] + "分";
}
}
cout << res << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为输入的字符串长度,遍历整个字符串
- 空间复杂度:,保存截取后的字符串长度最多为,res输出属于必要字符串
方法二:递归
具体做法:
可以将输入的数字转化成int就去掉了小数部分,用全部减去整数部分再乘上100就得到小数部分。
对于整数部分,可以对万连除取余,每四位为1组进行运算,每次运算完之后添加相应标识字符。计算的时候我们分情况讨论,数字到底是几位数,对于多位数把整百整千输出以后,剩余部分作为子问题可以递归地进入函数继续计算。
对于小数部分,我们乘100之后,得到的角与分其实两位数,如果是1位数说明没有角,如果整十说明没有分,否则都可以用除法和取余获取角和分。
#include<iostream>
#include<string>
#include<vector>
using namespace std;
const vector<string> helper1 = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
const vector<string> helper2 = {"元", "万", "亿", "万亿"};
const vector<string> helper3 = {"", "拾", "佰", "仟"};
string function(int num){
string str;
if(num > 0 && num <= 9) //只有个位
str += helper1[num];
else if(num >= 10 && num <= 19){ //10到19
if(num % 10 == 0) //整十
str += helper3[1];
else
str += helper3[1] + helper1[num%10];
}else if(num >= 20 && num <= 99){ //20到99
if(num % 10 == 0) //整十
str += helper1[num/10] + helper3[1];
else
str += helper1[num/10] + helper3[1] + helper1[num%10];
}else if(num >= 100 && num <= 999){ //三位数
if(num % 100 == 0) //整百
str += helper1[num/100] + helper3[2];
else if(num % 100 <= 9) //整十
str += helper1[num/100] + helper1[0] + helper1[num%100];
else //后续进入递归
str += helper1[num/100] + helper3[2] + function(num % 100);
}else if(num >= 1000 && num <= 9999){ //四位数
if(num % 1000 == 0) //整千
str += helper1[num/1000] + helper3[3];
else if(num % 1000 <= 99) //后续进入递归
str += helper1[num/1000] + helper3[3] + helper1[0] + function(num % 1000);
else //后续进入递归
str += helper1[num/1000] + helper3[3] + function(num % 1000);
}
return str;
}
int main(){
double money;
while (cin >> money){
money += 0.0001; // 此处+0.0001防止double转换int产生误差
int data = static_cast<int>(money); //处理整数
vector<int> vec;
string res = "人民币";
while(data){
vec.push_back(data % 10000); //四位一组
data /= 10000;
}
for(int i = vec.size() - 1; i >= 0; i--){
res += function(vec[i]); //从最高得4位得开始加
res += helper2[i]; //添加亿万等字符
if (i != 0 && i - 1 >= 0 && vec[i - 1] <= 999 && vec[i - 1] != 0)
res += helper1[0]; //添加后一位为0的情况
}
int deci = static_cast<int>((money - static_cast<int>(money)) * 100);// 第二步处理小数
if(deci == 0) //小数部分为0
res += "整";
else if(deci < 10) //没有角
res += helper1[deci] + "分";
else if(deci % 10 == 0) //没有分
res += helper1[deci / 10] + "角";
else //分角都有
res += helper1[deci / 10] + "角" + helper1[deci % 10] + "分";
cout << res << endl;
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为输入数字的位数,递归需要遍历所有位数
- 空间复杂度:,记录的临时数组都是常数空间