题目链接
题目描述
本题要求编写程序,计算 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
题目大意
给你两个分数,做四则运算
解题思路
继科学计数法以后第二道恶心题,本题要注意的点非常多,当时题解也借鉴了柳婼大神的代码,下面我尽量将每一个要注意的点给读者剖析一下
- 首先是范围问题,题目中说
分子和分母全是整型范围内的整数,看似用int能满足,实则是不行的,因为会涉及到加法和乘法,所以我建议所有变量都用long long类型 - 然后是输入问题,
scanf输入有一个很好的特点,是可以通过提前在""内定义不需要输入的数据,例如本题的输入,但是别忘了scanf输入是要带&的
//直接将分数线 / 不存入,只保留两个数的分子分母
scanf("%lld/%lld %lld/%lld",&a1,&b1,&a2,&b2);
- 随后是分数的输出处理,我们可以看到,
真的非常麻烦,在注释中也给出了比较详细的说明,读者可自行阅读 - 然后是运算问题
- 加减可以直接暴力求解,不会超过
long long的范围 - 乘法不行,需要先约分再运算,因为两个
int最大值相乘long long还是顶不住 - 除法注意判断分母为零的情况
- 加减可以直接暴力求解,不会超过
题解
#include<bits/stdc++.h>
using namespace std;
void simp(long long a,long long b){
//首先判断是不是分子是不是0,如果是的话直接输出0,就不用分数形式了
if(a==0){
cout<<"0";
return;
}
bool f=false; //用于判断是不是负数,ture代表是负数
//主要用于判断后半边括号要不要输出
if(a<0&&b>0||a>0&&b<0){
//当分子分母符号不相同时,代表是负数
cout<<"(-"; //输出负数的半边括号
f=true;
}
//对ab取绝对值,便于后续的输出,因为已经判断好了符号了,就只需要单纯看数字怎么输出了
a=abs(a);
b=abs(b);
//如果能被整除就代表输出形式不是分数而是整数了,直接return
if(a%b==0){
cout<<a/b;
if(f)
cout<<")";
//是负数的话就输出后半边括号
return;
}
//__gcd函数是用来求两个数的最大公约数的
long long x=__gcd(a,b);
//对分子分母约分
a/=x;
b/=x;
//当分子小于分母(代表分数部分小于1),直接输出分数
if(a<b){
cout<<a<<"/"<<b;
}
//否则是带分数,需要输出 n又a分b几
else{
cout<<a/b<<" "<<a%b<<"/"<<b;
}
//输出后半边括号
if(f){
cout<<")";
}
}
//加减都可以用最暴力的方法,因为不会超过long long的范围
void sum(long long a1,long long b1,long long a2,long long b2){
simp(a1*b2+a2*b1,b1*b2);
}
//加减都可以用最暴力的方法,因为不会超过long long的范围
void sub(long long a1,long long b1,long long a2,long long b2){
simp(a1*b2-a2*b1,b1*b2);
}
//乘法需要先约分在输出,不然两个int的最大值相乘还是顶不住范围
void mul(long long a1,long long b1,long long a2,long long b2){
int x=__gcd(a1,b1);
int y=__gcd(a2,b2);
a1/=x;
b1/=x;
a2/=y;
b2/=y;
int x2=__gcd(a1,b2);
int y2=__gcd(a2,b1);
a1/=x2;
b2/=x2;
a2/=y2;
b1/=y2;
simp(a1*a2,b1*b2);
}
//除法需要额外判断两个分母为0的情况
void div(long long a1,long long b1,long long a2,long long b2){
if(a1==0||a2==0){
cout<<"Inf";
}
else{
simp(a1*b2,a2*b1);
}
}
int main(){
long long a1,a2,b1,b2;
//直接将分数线 / 不存入,只保留两个数的分子分母
scanf("%lld/%lld %lld/%lld",&a1,&b1,&a2,&b2);
simp(a1,b1); cout<<" + "; simp(a2,b2); cout<<" = "; sum(a1,b1,a2,b2); cout<<endl;
simp(a1,b1); cout<<" - "; simp(a2,b2); cout<<" = "; sub(a1,b1,a2,b2); cout<<endl;
simp(a1,b1); cout<<" * "; simp(a2,b2); cout<<" = "; mul(a1,b1,a2,b2); cout<<endl;
simp(a1,b1); cout<<" / "; simp(a2,b2); cout<<" = "; div(a1,b1,a2,b2); cout<<endl;
}

文章讲述了如何编写程序来计算两个有理数的加、减、乘、除,强调了输入输出格式、数据类型选择以及分数的最简形式和分母为零的特殊情况处理。解题策略包括使用longlong类型避免溢出,简化输出格式,以及在乘法和除法中进行约分操作。
1866

被折叠的 条评论
为什么被折叠?



