1034 有理数四则运算 (20分)
本题要求编写程序,计算 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
思路解析:
把两个有理数的分子分母a1,b1,a2,b2都用整型定义;计算加法和减法时通分,计算乘法和除法时分子分母对应相乘,得到新的分子和新的分母;最后用一个化简函数对两个有理数及其运算结果化简,从而得到结果。
以下代码就是用函数分别将 加、减、乘、除 和 通分、化简 六个步骤封装,具体步骤参见以下代码
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
void add(long long n1_u,long long n1_d,long long n2_u,long long n2_d);
void sub(long long n1_u,long long n1_d,long long n2_u,long long n2_d);
void mul(long long n1_u,long long n1_d,long long n2_u,long long n2_d);
void div(long long n1_u,long long n1_d,long long n2_u,long long n2_d);
void tongfen(long long *pn1_u,long long *pn1_d,long long *pn2_u,long long *pn2_d);//分数的通分
void output_number(long long *a,long long *b); //输出有理数
int main(){
long long n1_u,n1_d,n2_u,n2_d;char c; // c吸收字符'/'
scanf("%lld%c%lld%lld%c%lld",&n1_u,&c,&n1_d,&n2_u,&c,&n2_d); // 数据输入
add(n1_u,n1_d,n2_u,n2_d);cout<<endl; //加法
sub(n1_u,n1_d,n2_u,n2_d);cout<<endl; //减法
mul(n1_u,n1_d,n2_u,n2_d);cout<<endl; //除法
div(n1_u,n1_d,n2_u,n2_d);cout<<endl; // 除法
return 0;
}
void add(long long n1_u,long long n1_d,long long n2_u,long long n2_d){
tongfen(&n1_u,&n1_d,&n2_u,&n2_d); //加法
long long nu,nd;
nd=n1_d;
nu=n1_u+n2_u;
output_number(&n1_u,&n1_d);printf(" + ");output_number(&n2_u,&n2_d);printf(" = ");output_number(&nu,&nd);
}
void sub(long long n1_u,long long n1_d,long long n2_u,long long n2_d){
tongfen(&n1_u,&n1_d,&n2_u,&n2_d); //减法
long long nu,nd;
nd=n1_d;
nu=n1_u-n2_u;
output_number(&n1_u,&n1_d);printf(" - ");output_number(&n2_u,&n2_d);printf(" = ");output_number(&nu,&nd);
}
void mul(long long n1_u,long long n1_d,long long n2_u,long long n2_d){
long long nu,nd; //乘法
nd=n1_d*n2_d;
nu=n1_u*n2_u;
output_number(&n1_u,&n1_d);printf(" * ");output_number(&n2_u,&n2_d);printf(" = ");output_number(&nu,&nd);
}
void div(long long n1_u,long long n1_d,long long n2_u,long long n2_d){
long long nu,nd; //除法
nd=n1_d*n2_u;
nu=n1_u*n2_d;
if(nd<0){
nu=-nu;
nd=-nd;
}
output_number(&n1_u,&n1_d);printf(" / ");output_number(&n2_u,&n2_d);printf(" = ");
if(n2_u==0)printf("Inf");
else output_number(&nu,&nd);
}
void tongfen(long long *pn1_u,long long *pn1_d,long long *pn2_u,long long *pn2_d)
{ //分数的通分
long long t1=*pn1_d,t2=*pn2_d;
if( *pn1_d != *pn2_d )
{
*pn1_u = *pn1_u * t2;
*pn1_d = *pn1_d * t2;
*pn2_u = *pn2_u * t1;
*pn2_d = *pn2_d * t1;
}
}
void output_number(long long *a,long long *b) //输出有理数
{
if(*a==0)
{
printf("0");
return ;
}
long long t,tt;
long long aa,bb=*b;
if(*a<0) aa=-*a;
else aa=*a;
while(bb!=0){ //辗转相除法取得最大公约数 ,测试点2,3超时原因
tt=aa;
aa=bb;
bb=tt%bb;
}
t=aa; //******************以下情况为 分子小于分母
if(t==*b) //输出情况为 "分子为 1 "
{
if(*a<0)
printf("(%lld)",*a / *b);
else
printf("%lld",*a/ *b);
}
else
{ //输出情况为分子不为 "1"
if(fabs(*a)<*b)
{
if(*a<0)
{
printf("(%lld/%lld)",*a /t,*b/t);
return;
}
else
{
printf("%lld/%lld",*a/t,*b/t);
return;
}
} //***************以下为分子大于分母的情况 ,需提取出整数部分
*a = *a/t,*b = *b/t;
int f=0; //输出是否有负号 的标志 f
if(*a<0)
{
f=1;
*a=-*a;
}
int sum=0; //sum记录整数部分
while(*a>*b) //提取整数部分
{
*a-=*b;
sum++;
}
if(f==1) //输出有整数部分的分数
{
printf("(%d ",-sum);
printf("%lld/%lld)",*a,*b);
}
else
{
printf("%d ",sum);
printf("%lld/%lld",*a,*b);
}
}
}