本题要求编写程序,计算 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
原题链接:https://pintia.cn/problem-sets/994805260223102976/problems/994805287624491008
思路:此题还是有一定难度的。首先要搞清楚分数的几种形式:真分数(分子小于分母),假分数(分子大于分母的分数),最简分数(分子和分母不可再约分),带分数(几又几分之几的形式,例如:1 1/2等)。然后编程按题目要求的格式输出。
本题考察的知识点:
1.求两个数的最大公约数:辗转相除法,有模板代码,捋一遍思路记住即可,下次要会用。侧面说明了数学对于计算机来说是非常重要的!!!
2.格式化数据输入和输出。比如题目中要求的:正负号的处理,一些特殊符号输出(空格,"()",等);
#include
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b);
void cvt(ll x,ll y);
int main()
{
ll a,b,c,d;
while(scanf("%lld/%lld%lld/%lld",&a,&b,&c,&d)==4)
{
cvt(a,b);printf(" + ");cvt(c,d);printf(" = ");cvt(a*d+b*c,b*d);printf("\n");
cvt(a,b);printf(" - ");cvt(c,d);printf(" = ");cvt(a*d-b*c,b*d);printf("\n");
cvt(a,b);printf(" * ");cvt(c,d);printf(" = ");cvt(a*c,b*d);printf("\n");
cvt(a,b);printf(" / ");cvt(c,d);printf(" = ");cvt(a*d,b*c);printf("\n");
}
return 0;
}
ll gcd(ll a,ll b)
{//求两个数的最大公约数
if(b==0)
return a;
else
return gcd(b,a%b);
}
void cvt(ll x,ll y)
{
//1.有一个数为0,退出
if(x*y==0)
{
printf("%s",y==0?"Inf":"0");
return ;
}
//2.判断正负号,真假分数的化解
bool flag = (x<0&&y>0)||(y<0&&x>0);//flag:负号标记位
printf("%s",flag?"(-":"");
x = abs(x);
y = abs(y);
if(x%y==0)
{
printf("%lld%s",x/y,flag?")":"");
return;
}
ll pa = 0;
//化成最简分数
ll m = gcd(x,y);
x /= m;
y /= m;
if(x>y)
{//化成带分数
pa = x/y;
x = x%y;
}
if(pa>0)
{
printf("%lld",pa);
}
if(pa&&x)
{
printf(" ");
}
printf("%lld/%lld%s",x,y,flag?")":"");
}