1034. 有理数四则运算(20)
时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue
本题要求编写程序,计算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
思路:本道题目的难点主要在于计算结果的规格化输出,更具体地说主要在于输出分数的最简形式,计算并不难。
注意一点,题目说的很隐晦,输入时分子分母为整型,但是计算过程中可能会超出整型的界限,所以此题变量最好全部采用long int。
还有在求最大公约数时逐个寻找会超时,利用辗转相除法即可
#include "stdio.h"
#include "math.h"
void calculate(long int a1, long int b1, int long a2, long int b2);//计算函数
void formulate(long int a,long int b);//化减函数
long int myAbs(long int a);//long int型绝对值函数
int main()
{
long int a1,b1,a2,b2;
scanf("%ld/%ld %ld/%ld",&a1,&b1,&a2,&b2);
calculate(a1,b1,a2,b2);
return 0;
}
void calculate(long int a1, long int b1, long int a2, long int b2)
{
//计算输出两个分数的加、减、乘、除
//加法
long int aOfSum, bOfSum;
aOfSum = a1 * b2 + a2 * b1;//和的分子
bOfSum = b1 * b2;//和的分母
formulate(a1,b1);
printf(" + ");
formulate(a2,b2);
printf(" = ");
formulate(aOfSum,bOfSum);
printf("\n");
//减法
long int aOfSub, bOfSub;
aOfSub = a1 * b2 - a2 * b1;//差的分子
bOfSub = b1 * b2;//差的分母
formulate(a1,b1);
printf(" - ");
formulate(a2,b2);
printf(" = ");
formulate(aOfSub,bOfSub);
printf("\n");
//乘法
long int aOfMul = 0, bOfMul = 0;
aOfMul = a1 * a2;//积的分子
bOfMul = b1 * b2;//积的分母
formulate(a1,b1);
printf(" * ");
formulate(a2,b2);
printf(" = ");
formulate(aOfMul,bOfMul);
printf("\n");
//除法
if(a2 == 0)
{
//如果除数为0,错误输出
formulate(a1,b1);
printf(" / 0");
printf(" = ");
printf("Inf\n");
}
else
{
//除数不为零
long int aOfDiv, bOfDiv;
aOfDiv = a1 * b2;//商的分子
bOfDiv = a2 * b1;//商的分母
//因为化简函数要求分子带符号,分母不带符号,所以在输出之前将分子符号确定,分母变为正
if(aOfDiv < 0 && bOfDiv < 0)
{
//除法结果分子分母都为负数的话,则进入化简函数之前都转化为正数
aOfDiv = myAbs(aOfDiv);
bOfDiv = myAbs(bOfDiv);
}
else if(aOfDiv > 0 && bOfDiv > 0)
{
//除法结果分子分母都为正数的话,什么都不用做
}
else
{
//一正一负,则进入化简函数之前分子为正,分母为负
aOfDiv = -myAbs(aOfDiv);
bOfDiv = myAbs(bOfDiv);
}
formulate(a1,b1);
printf(" / ");
formulate(a2,b2);
printf(" = ");
formulate(aOfDiv,bOfDiv);
printf("\n");
}
}
void formulate(long int a, long int b)
{
if(a == 0)
{
//分子为零,直接输出0
printf("0");
return;
}
//规范分数的输出
long int tmpA = myAbs(a);
long int tmpB = myAbs(b);
if(tmpA < tmpB)
{
//将tmpA置为大的数
long int tmp;
tmp = tmpA;
tmpA = tmpB;
tmpB = tmp;
}
long int left = tmpA % tmpB;
while(left != 0)
{
//辗转相除法找到最大公约数
tmpA = tmpB;
tmpB = left;
left = tmpA % tmpB;
}
long int Yue = tmpB;//找到最大公约数;
a = a / Yue;
b = b / Yue;
//在化为最简形式之前,要明确一点,因为输入形式的关系,只有a可能为负数,b一定为正数
if(a < 0)
{
//分子小于0,输出需要加括号
if(myAbs(a) > b)
{
//分子绝对值大于分母
if(myAbs(a) % b == 0)
{
//分子为分母的整数倍
printf("(%d)",a / b);
}
else
{
//分子不为分子的整数倍
printf("(%d %d/%d)",a / b, myAbs(a) % b, b);
}
}
else if(myAbs(a) == b)
{
//分子绝对值和分母相同
printf("(-1)");
}
else
{
//分子绝对值小于分母
printf("(%d/%d)",a, b);
}
}
else
{
//即为a > 0 ,输出不用带括号
if(a > b)
{
//分子绝对值大于分母
if(a % b == 0)
{
//分子为分母的整数倍
printf("%d",a / b);
}
else
{
//分子不是分母的整数倍
printf("%d %d/%d",a/b, a%b, b);
}
}
else if(a == b)
{
//分子的绝对值和分母相等
printf("1");
}
else
{
//分子的绝对值小于分母
printf("%d/%d",a, b);
}
}
}
long int myAbs(long int a)
{
if(a < 0)
return -a;
else
return a;
}