题目:
本题要求编写程序,计算 2 个有理数的和、差、积、商。
输入格式:
输入在一行中按照 a1/b1 a2/b2
的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前,分母不为 0。
输出格式:
分别在 4 行中按照 有理数1 运算符 有理数2 = 结果
的格式顺序输出 2 个有理数的和、差、积、商。注意输出的每个有理数必须是该有理数的最简形式 k a/b
,其中 k
是整数部分,a/b
是最简分数部分;若为负数,则须加括号;若除法分母为 0,则输出 Inf
。题目保证正确的输出中没有超过整型范围的整数。
输入样例 1:
2/3 -4/2
输出样例 1:
2/3 + (-2) = (-1 1/3)
2/3 - (-2) = 2 2/3
2/3 * (-2) = (-1 1/3)
2/3 / (-2) = (-1/3)
输入样例 2:
5/3 0/6
输出样例 2:
1 2/3 + 0 = 1 2/3
1 2/3 - 0 = 1 2/3
1 2/3 * 0 = 0
1 2/3 / 0 = Inf
思路:1、split()函数:将分数读入string变量中,将其分为分子和分母储存在long long变量中;
2、基于split(),再分别写四个加减乘除函数;
3、together_simple(), 输入分子分母部分,将其化为最简形式,并储存在string中。
难点:3中如何化为最简真分数。
a、从1循环至分子,分母的小者,找到其最大的公因子。复杂度较大。
b、辗转相除法。
注意:测试点3错误:用 int 存储加减乘除时可能存在数值越界,应该采用 long long
#include<iostream>
#include<string>
using namespace std;
void split(const string& a, long long& a1, long long& a2);
int largest_factor(int a, int b);
string& together_simple(string& ans, long long c1, long long c2);
string& add(string& ans, long long a1, long long a2, long long b1, long long b2);
string& subtract(string& ans, long long a1, long long a2, long long b1, long long b2);
string& mutiple(string& ans, long long a1, long long a2, long long b1, long long b2);
string& divided(string& ans, long long a1, long long a2, long long b1, long long b2);
void split(const string& a, long long& a1, long long& a2) //把分数拆分为分子和分母
{
long long i = 0; long long flag = 0;
if(a[0]=='-')
{
i++;
flag = 1;
}
a1 = a2 = 0;
while(a[i]!='/')
a1 = a1*10 + (a[i++]-'0');
i++;
while(a[i]!='\0')
a2 = a2*10 + (a[i++]-'0');
if(flag==1)
a1 = -a1;
}
int largest_factor(int a, int b) //辗转相除法求最大公因子
{
if(a==0 || b==0)
return 0;
int big, small;
if(a>b)
{
big = a;
small = b;
}
else
{
big = b;
small = a;
}
int bigyin, yu;
while(1)
{
if(big%small==0)
{
bigyin = small;
break;
}
else
{
yu = big%small;
big = small;
small = yu;
}
}
return bigyin;
}
string& together_simple(string& ans, long long c1, long long c2) //把分子分母化作最简形式储存在string中
{
long long flag = 0;
if(c1<0)
{
flag = 1;
c1 = -c1;
}
long long zheng, fen;
zheng = c1/c2; fen = c1%c2;
if(fen!=0)
{
int bigyin;
bigyin = largest_factor(fen, c2);
fen = fen/bigyin; c2 = c2/bigyin;
}
/* for(long long i=2; i<=fen && i<=c2; i++) //时间复杂度大,将分数部分化为最简;注意:i 从1开始, 而不能从0开始
{
if(fen%i==0 && c2%i==0)
{
fen = fen/i; c2 = c2/i; i=1; // i=1必须要有,否则化简不彻底,例如4/12 -> 2/6;
}
}*/
if(flag==1) //将符号,整数部分,分数部分拼接到string ans 中;注意括号和空格所加位置的逻辑
ans += "(-";
if(fen==0)
ans += to_string(zheng);
else if(fen!=0 && zheng!=0)
{
ans += to_string(zheng);
ans += " ";
}
if(fen!=0)
{
ans += to_string(fen);
ans += "/";
ans += to_string(c2);
}
if(flag==1)
ans += ")";
return ans;
}
string& add(string& ans, long long a1, long long a2, long long b1, long long b2)
{
ans = "";
a1=a1*b2; b1=a2*b1;
a2=a2*b2; b2=a2;
long long c1, c2;
c1=a1+b1; c2=a2;
together_simple(ans, c1, c2);
return ans;
}
string& subtract(string& ans, long long a1, long long a2, long long b1, long long b2)
{
ans = "";
b1 = -b1;
return add(ans, a1, a2, b1, b2);
}
string& mutiple(string& ans, long long a1, long long a2, long long b1, long long b2)
{
ans = "";
long long c1, c2;
c1 = a1*b1;
c2 = a2*b2;
return together_simple(ans, c1, c2);
}
string& divided(string& ans, long long a1, long long a2, long long b1, long long b2)
{
ans = "";
if(b1==0)
{
ans += "Inf";
return ans;
}
if(b1<0)
{
b1 = -b1;
b2 = -b2;
}
return mutiple(ans, a1, a2, b2, b1);
}
int main()
{
string a, b;
cin >> a >> b;
long long a1, a2, b1, b2;
split(a, a1, a2);
split(b, b1, b2);
string a_simple, b_simple;
together_simple(a_simple, a1, a2);
together_simple(b_simple, b1, b2);
string ans;
cout << a_simple << " + " << b_simple << " = " << add(ans, a1, a2, b1, b2) << endl;
cout << a_simple << " - " << b_simple << " = " << subtract(ans, a1, a2, b1, b2) << endl;
cout << a_simple << " * " << b_simple << " = " << mutiple(ans, a1, a2, b1, b2) << endl;
cout << a_simple << " / " << b_simple << " = " << divided(ans, a1, a2, b1, b2) << endl;
return 0;
}
来源:CSDN
作者:二战失败,底层爬起
链接:https://blog.csdn.net/Fgq080200198/article/details/104520944