【问题描述】 任何小数都能表示成分数的形式,对于給定的小数,编写程序其化为最简分数输出,小数包括简单小数和循环小数。
【输入形式】 第一行是一个整数N,表示有多少组数据。\每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。【输出形式】 对每一个对应的小数化成最简分数后输出,占一行
【样例输入】
3
0.(4)
0.5
0.32(692307)
【样例输出】
4/9
1/2
17/52
我用的知识都是string里面的,没学过的话可以上b站看黑马程序员P189-196,新手也能学,而且很好用。
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin >> n;
cin.ignore();
while (n--)
{
int sum = 1, num = 0, num1 = 0, sum1 = 1;
//num用于记录分子,sum记录分母,num1和sum1的用处后面再讲
string s, t;
getline(cin, s);
无非三种情况,第1种简单小数,第2种括号紧跟小数点,第3种括号不紧跟小数点
size_t pos = s.find("(", 2);//判断是简单小数还是循环小数
if (pos == string::npos)//第一种情况
{
t = s.substr(2);//截取小数点后的数字
for (size_t i = 0; i < t.size(); i++)
{
num = num * 10 + t[i] - '0';//将分子化成整数
sum *= 10;//分母相应的变化
}
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
//判断是否可以约分
{
num /= j;
sum /= j;
}
}
}
else if (pos == 2)//第二种情况,括号紧跟着小数点
{
sum = 9;//因为分母都是9,99,999这种,所以我让sum=9
t = s.substr(3);//截取括号之后的一串字符串
for (size_t i = 0; i < t.size()-1; i++)//只遍历到右括号前的数字
{
num = num * 10 + t[i] - '0';
sum = sum*10+9;
}//相应的分子分母
sum /= 10;//因为我一开始就让它等于9,但它其实是0.9,所以后面除以10
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}
}
else
{
sum = 9;
t = s.substr(2, pos - 2);//截取小数点后和左括号前的一串数字
for (size_t i = 0; i < t.size(); i++)
{
num1 = num1 * 10 + t[i] - '0';
sum1 *= 10;
}//获得相应的分子分母
t = s.substr(pos + 1);//截取括号中的数字
for (size_t i = 0; i < t.size() - 1; i++)
{
num = num * 10 + t[i] - '0';
sum = sum * 10 + 9;
}
sum /= 10;
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}//求括号中数字的分子,分母
num = num1 * sum + num;
sum = sum * sum1;//然后再将两者整合,化成同一个分数
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}//再进行约分
}
cout << num << "/" << sum << endl;
}
return 0;
}
最后发现第2种情况和第3种情况可以整合,就相当于第2种情况括号前的数字截取的是一个空的字符串,并不会影响最后的结果。接下来展示最终的代码:
结合样例应该很好看懂,不会欢迎评论问我
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin >> n;
cin.ignore();
while (n--)
{
int sum = 1, num = 0, num1 = 0, sum1 = 1;
string s, t;
getline(cin, s);
size_t pos = s.find("(", 2);
if (pos == string::npos)
{
t = s.substr(2);
for (size_t i = 0; i < t.size(); i++)
{
num = num * 10 + t[i] - '0';
sum *= 10;
}
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}
}
else
{
sum = 9;
t = s.substr(2, pos - 2);
for (size_t i = 0; i < t.size(); i++)
{
num1 = num1 * 10 + t[i] - '0';
sum1 *= 10;
}
t = s.substr(pos + 1);
for (size_t i = 0; i < t.size() - 1; i++)
{
num = num * 10 + t[i] - '0';
sum = sum * 10 + 9;
}
sum /= 10;
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}
num = num1 * sum + num;
sum = sum * sum1;
for (int j = num; j >= 2; j--)
{
if (num % j == 0 && sum % j == 0)
{
num /= j;
sum /= j;
}
}
}
cout << num << "/" << sum << endl;
}
return 0;
}
当然,求最大公约数可以用辗转相除法
话不多说,上代码!!!(方法二)
#include <iostream>
#include <string>
using namespace std;
int gcd(int a, int b)//辗转相除求最大公约数
{
if (b == 0)return a;
return gcd(b, a % b);
}
int main()
{
int n;
cin >> n;
cin.ignore();
while (n--)
{
int sum = 1, num = 0, num1 = 0, sum1 = 1,result=0;
string s, t;
getline(cin, s);
size_t pos = s.find("(", 2);
if (pos == string::npos)
{
t = s.substr(2);
for (size_t i = 0; i < t.size(); i++)
{
num = num * 10 + t[i] - '0';
sum *= 10;
}
result=gcd(sum, num);
sum /= result;
num /= result;
}
else
{
sum = 9;
t = s.substr(2, pos - 2);
for (size_t i = 0; i < t.size(); i++)
{
num1 = num1 * 10 + t[i] - '0';
sum1 *= 10;
}
t = s.substr(pos + 1);
for (size_t i = 0; i < t.size() - 1; i++)
{
num = num * 10 + t[i] - '0';
sum = sum * 10 + 9;
}
sum /= 10;
result = gcd(sum, num);
sum /= result;
num /= result;
num = num1 * sum + num;
sum = sum * sum1;
result = gcd(sum, num);
sum /= result;
num /= result;
}
cout << num << "/" << sum << endl;
}
return 0;
}