题目
本题要求编写程序,计算 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
结尾无空行
解题思路
- 读入给定分数;
- 求解分母的最小公倍数;
- for循环进行加减乘除,对于每一种运算产生的运算结果和所使用的给定分数进行相同的“简化+格式化”输出(重复多次使用相同功能->调用函数);
难点
测试点2、3——测试点2答案错误,测试点3运行超时。
测试点2的解决:将所写的分式化简并输出的"simplify函数"中,判断分式符号的语句,由
if (a*b<0)
修改为
if ((a*1.0/b)<0)
这样可以避免a和b的积过大,超过了long int能够存储的范围而产生的错误,且乘法和除法在此所起到的功能相同。
测试点3的解决:将求解最大公因数的方法进行改变。由以下代码片的for遍历寻找的方法
long int i;
for (i=min(a,b);i>0;i--)
if (a%i==0 && b%i==0)
return i;
改为欧几里德算法(也叫辗转相除法)
long int y = a%b;
while (y!=0)
{
a = b;
b = y;
y = a%b;
}
return b;
代码
#include<stdio.h>
#include<math.h>
long int min(long int a, long int b)
{
if (a<b)
return a;
else
return b;
}
long int GCD(long int a, long int b)//最大公约数
{
long int y = a%b;
while (y!=0)
{
a = b;
b = y;
y = a%b;
}
return b;
}
long int LCM(long int a, long int b)//最小公倍数
{
long int c = GCD(a,b);
return (a*b/c);
}
void simplify(long int a, long int b)//化简分式并按照格式输出
{
int isNegative = 0;
long int zs;
if (b==0)
printf("Inf");
else if (a==0)
printf("0");
else //分母不是0
{
if ((a*1.0/b)<0)//将a*b修改为了a*1.0/b判断符号,因为前者可能超过long int的范围
isNegative = 1;
a = abs(a);
b = abs(b);
zs = a/b;
a%=b;
if (a!=0)
{
long int gcd = GCD(a,b);
a/=gcd;
b/=gcd;
}
if (isNegative==1)
{
printf("(-");
if (zs!=0)
{
printf("%ld",zs);
if (a!=0)
printf(" %ld/%ld)",a,b);
else
printf(")");
}
else
printf("%ld/%ld)",a,b);
}
else
{
if (zs!=0)
{
printf("%ld",zs);
if (a!=0)
printf(" %ld/%ld",a,b);
}
else
printf("%ld/%ld",a,b);
}
}
}
int main(){
int i;
long int fenzi[2],fenmu[2];//分子和分母全是整型范围内的整数
//这里写为long int是防止计算时相乘后长于long int的结果被存入int,造成错误
long int gbs,bs0,bs1;
char symbol[4] = {'+','-','*','/'};
scanf("%ld/%ld %ld/%ld",&fenzi[0],&fenmu[0],&fenzi[1],&fenmu[1]);
gbs = LCM(fenmu[0],fenmu[1]);
bs0 = gbs/fenmu[0];
bs1 = gbs/fenmu[1];
for (i=0;i<4;i++)
{
simplify(fenzi[0],fenmu[0]);
printf(" %c ",symbol[i]);
simplify(fenzi[1],fenmu[1]);
printf(" = ");
switch (i)
{
case 0:simplify(fenzi[0]*bs0+fenzi[1]*bs1,gbs);printf("\n");break;
case 1:simplify(fenzi[0]*bs0-fenzi[1]*bs1,gbs);printf("\n");break;
case 2:simplify(fenzi[0]*fenzi[1],fenmu[0]*fenmu[1]);printf("\n");break;
case 3:simplify(fenzi[0]*fenmu[1],fenzi[1]*fenmu[0]);printf("\n");break;
}
}
return 0;
}