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
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
long int GCD(long int x, long int y);
long int LCM(long int x, long int y);
int main() {
long int a1, b1, a2, b2, Z1 = 0, Z2 = 0, Sign1 = 1, Sign2 = 1, Mark = 1, Flag = 1; //Flag在整数部分为零时判断该数的正负
long int s1 = 1, s2 = 1, s3 = 1, s4 = 1; //Mark标志原始数是否有零
scanf("%ld/%ld %ld/%ld", &a1, &b1, &a2, &b2); //得到两个数
if (a1 < 0) { a1 = -a1; Sign1 = -1; }
else if (!a1) Mark = 0;
if (a2 < 0) { a2 = -a2; Sign2 = -1; } //正负问题
else if (!a2) Mark = 0;
if (Mark) { //两个原始数都不为零
long int Tmp1GCD = GCD(a1, b1); //得到第一个数分子与分母的最大公约数
a1 /= Tmp1GCD;
b1 /= Tmp1GCD; //得到第一个数的最简分数形式
long int doa1 = a1, dob1 = b1; //用于实际运算
if (b1 == 1) { Z1 = a1 * Sign1; a1 = 0; } //若分母为整数
else if (a1 > b1) { Z1 = a1 / b1 * Sign1; a1 = a1 % b1; } //若为假分数
long int Tmp2GCD = GCD(a2, b2); //得到第二个数分子与分母的最大公约数
a2 /= Tmp2GCD;
b2 /= Tmp2GCD; //得到第二个数的最简分数形式
long int doa2 = a2, dob2 = b2; //用于实际运算
if (b2 == 1) { Z2 = a2 * Sign2; a2 = 0; } //若分母为整数
else if (a2 > b2) { Z2 = a2 / b2 * Sign2; a2 = a2 % b2; } //若为假分数
/*-------------------原始两个数化简完毕-------------------*/
long int retZ, reta, retb; //最终结果的整数 分子 分母
/*-------------------开始加法运算-------------------*/
if ((Sign1 > 0 && Sign2 > 0) || (Sign1 < 0 && Sign2 < 0)) {
long int Tmpb = LCM(dob1, dob2); //得到两个分母的最小公倍数
long int Tmpa = doa1 * (Tmpb / dob1) + doa2 * (Tmpb / dob2);
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = reta * Sign1; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = reta / retb * Sign1; reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = (Sign1 > 0) ? 1 : 0; }
}
else { //一个正数 一个负数
long int Tmpb = LCM(dob1, dob2); //得到两个分母的最小公倍数
long int Tmpa = abs(doa1 * (Tmpb / dob1) - doa2 * (Tmpb / dob2));
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = -reta; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = -(reta / retb); reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = 0; }
}
/*-------------------开始格式输出加法结果-------------------*/
if (Z1 < 0) { //整数部分小于零时
if (a1) printf("(%ld %ld/%ld) + ", Z1, a1, b1);
else printf("(%ld) + ", Z1);
}
else if (Z1 > 0) { //整数部分大于零时
if (a1) printf("%ld %ld/%ld + ", Z1, a1, b1);
else printf("%ld + ", Z1);
}
else {
if (Sign1 > 0) printf("%ld/%ld + ", a1, b1); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) + ", -a1, b1);
}
if (Z2 < 0) { //整数部分小于零时
if (a2) printf("(%ld %ld/%ld) = ", Z2, a2, b2);
else printf("(%ld) = ", Z2);
}
else if (Z2 > 0) { //整数部分大于零时
if (a2) printf("%ld %ld/%ld = ", Z2, a2, b2);
else printf("%ld = ", Z2);
}
else {
if (Sign2 > 0) printf("%ld/%ld = ", a2, b2); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) = ", -a2, b2);
}
if (retZ < 0) { //整数部分小于零时
if (reta) printf("(%ld %ld/%ld)\n", retZ, reta, retb);
else printf("(%ld)\n", retZ);
}
else if (retZ > 0) { //整数部分大于零时
if (reta) printf("%ld %ld/%ld\n", retZ, reta, retb);
else printf("%ld\n", retZ);
}
else {
if (!reta) printf("0\n");
else {
if (Flag) printf("%ld/%ld\n", reta, retb);
else printf("(-%ld/%ld)\n", reta, retb);
}
} //整数部分为零 分数部分一定不为零
/*-------------------结束格式输出加法结果-------------------*/
/*-------------------开始减法运算-------------------*/
long int Com = 1;
if ((Sign1 > 0 && Sign2 > 0) || (Sign1 < 0 && Sign2 < 0)) {
long int Tmpb = LCM(dob1, dob2); //得到两个分母的最小公倍数
long int Tmpa = doa1 * (Tmpb / dob1) - doa2 * (Tmpb / dob2);
if (Tmpa < 0) { Tmpa = -Tmpa; Com = -1; } //考虑两数相减的正负
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = reta * Sign1 * Com; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = reta / retb * Sign1 * Com; reta = reta % retb; } //若为假分数
else {
retZ = 0;
if (Sign1 * Com < 0) Flag = 0;
else Flag = 1;
}
}
else { //一个正数 一个负数
long int Tmpb = LCM(dob1, dob2); //得到两个分母的最小公倍数
long int Tmpa = doa1 * (Tmpb / dob1) + doa2 * (Tmpb / dob2);
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (Sign1 < 0) {Com = -1; retZ = 0; Flag = 0; } //负数减整数结果为负数
if (retb == 1) { retZ = reta * Com; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = reta / retb * Com; reta = reta % retb; } //若为假分数
}
/*-------------------开始格式输出减法结果-------------------*/
if (Z1 < 0) { //整数部分小于零时
if (a1) printf("(%ld %ld/%ld) - ", Z1, a1, b1);
else printf("(%ld) - ", Z1);
}
else if (Z1 > 0) { //整数部分大于零时
if (a1) printf("%ld %ld/%ld - ", Z1, a1, b1);
else printf("%ld - ", Z1);
}
else {
if (Sign1 > 0) printf("%ld/%ld - ", a1, b1); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) - ", -a1, b1);
}
if (Z2 < 0) { //整数部分小于零时
if (a2) printf("(%ld %ld/%ld) = ", Z2, a2, b2);
else printf("(%ld) = ", Z2);
}
else if (Z2 > 0) { //整数部分大于零时
if (a2) printf("%ld %ld/%ld = ", Z2, a2, b2);
else printf("%ld = ", Z2);
}
else {
if (Sign2 > 0) printf("%ld/%ld = ", a2, b2); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) = ", -a2, b2);
}
if (retZ < 0) { //整数部分小于零时
if (reta) printf("(%ld %ld/%ld)\n", retZ, reta, retb);
else printf("(%ld)\n", retZ);
}
else if (retZ > 0) { //整数部分大于零时
if (reta) printf("%ld %ld/%ld\n", retZ, reta, retb);
else printf("%ld\n", retZ);
}
else {
if (!reta) printf("0\n");
else {
if (Flag) printf("%ld/%ld\n", reta, retb);
else printf("(-%ld/%ld)\n", reta, retb);
}
}//整数部分为零 分数部分一定不为零
/*-------------------结束格式输出减法结果-------------------*/
/*-------------------开始乘法运算-------------------*/
if ((Sign1 > 0 && Sign2 > 0) || (Sign1 < 0 && Sign2 < 0)) {
long int Tmpa = doa1 * doa2;
long int Tmpb = dob1 * dob2;
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = reta; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = reta / retb; reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = 1; }
}
else { //一个正数 一个负数
long int Tmpa = doa1 * doa2;
long int Tmpb = dob1 * dob2;
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = -reta; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = -(reta / retb); reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = 0; }
}
/*-------------------开始格式输出乘法结果-------------------*/
if (Z1 < 0) { //整数部分小于零时
if (a1) printf("(%ld %ld/%ld) * ", Z1, a1, b1);
else printf("(%ld) * ", Z1);
}
else if (Z1 > 0) { //整数部分大于零时
if (a1) printf("%ld %ld/%ld * ", Z1, a1, b1);
else printf("%ld * ", Z1);
}
else {
if (Sign1 > 0) printf("%ld/%ld * ", a1, b1); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) * ", -a1, b1);
}
if (Z2 < 0) { //整数部分小于零时
if (a2) printf("(%ld %ld/%ld) = ", Z2, a2, b2);
else printf("(%ld) = ", Z2);
}
else if (Z2 > 0) { //整数部分大于零时
if (a2) printf("%ld %ld/%ld = ", Z2, a2, b2);
else printf("%ld = ", Z2);
}
else {
if (Sign2 > 0) printf("%ld/%ld = ", a2, b2); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) = ", -a2, b2);
}
if (retZ < 0) { //整数部分小于零时
if (reta) printf("(%ld %ld/%ld)\n", retZ, reta, retb);
else printf("(%ld)\n", retZ);
}
else if (retZ > 0) { //整数部分大于零时
if (reta) printf("%ld %ld/%ld\n", retZ, reta, retb);
else printf("%ld\n", retZ);
}
else {
if (Flag) printf("%ld/%ld\n", reta, retb);
else printf("(-%ld/%ld)\n", reta, retb);
} //整数部分为零 分数部分一定不为零
/*-------------------结束格式输出乘法结果-------------------*/
/*-------------------开始除法运算-------------------*/
if ((Sign1 > 0 && Sign2 > 0) || (Sign1 < 0 && Sign2 < 0)) {
long int Tmpa = doa1 * dob2; //得到分子
long int Tmpb = dob1 * doa2; //得到分母
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = reta; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = reta / retb; reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = 1; }
}
else { //一个正数 一个负数
long int Tmpa = doa1 * dob2; //得到分子
long int Tmpb = dob1 * doa2; //得到分母
long int TmpGCD = GCD(Tmpa, Tmpb);
reta = Tmpa / TmpGCD;
retb = Tmpb / TmpGCD; //得到结果的最简分数形式
if (retb == 1) { retZ = -reta; reta = 0; } //若分母为整数
else if (reta > retb) { retZ = -(reta / retb); reta = reta % retb; } //若为假分数
else { retZ = 0; Flag = 0; }
}
/*-------------------开始格式输出除法结果-------------------*/
if (Z1 < 0) { //整数部分小于零时
if (a1) printf("(%ld %ld/%ld) / ", Z1, a1, b1);
else printf("(%ld) / ", Z1);
}
else if (Z1 > 0) { //整数部分大于零时
if (a1) printf("%ld %ld/%ld / ", Z1, a1, b1);
else printf("%ld / ", Z1);
}
else {
if (Sign1 > 0) printf("%ld/%ld / ", a1, b1); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) / ", -a1, b1);
}
if (Z2 < 0) { //整数部分小于零时
if (a2) printf("(%ld %ld/%ld) = ", Z2, a2, b2);
else printf("(%ld) = ", Z2);
}
else if (Z2 > 0) { //整数部分大于零时
if (a2) printf("%ld %ld/%ld = ", Z2, a2, b2);
else printf("%ld = ", Z2);
}
else {
if (Sign2 > 0) printf("%ld/%ld = ", a2, b2); //整数部分为零 分数部分一定不为零
else printf("(%ld/%ld) = ", -a2, b2);
}
if (retZ < 0) { //整数部分小于零时
if (reta) printf("(%ld %ld/%ld)\n", retZ, reta, retb);
else printf("(%ld)\n", retZ);
}
else if (retZ > 0) { //整数部分大于零时
if (reta) printf("%ld %ld/%ld\n", retZ, reta, retb);
else printf("%ld\n", retZ);
}
else {
if (Flag) printf("%ld/%ld\n", reta, retb);
else printf("(-%ld/%ld)\n", reta, retb);
}//整数部分为零 分数部分一定不为零
/*-------------------结束格式输出除法结果-------------------*/
}
else { //两个原始数至少有一个为零
if (a1 && !a2) { //第二个数为零
long int Tmp1GCD = GCD(a1, b1); //得到第一个数分子与分母的最大公约数
a1 /= Tmp1GCD;
b1 /= Tmp1GCD; //得到第一个数的最简分数形式
long int doa1 = a1, dob1 = b1; //用于实际运算
if (b1 == 1) { Z1 = a1 * Sign1; a1 = 0; } //若分母为整数
else if (a1 > b1) { Z1 = a1 / b1 * Sign1; a1 = a1 % b1; } //若为假分数
if (Z1 < 0) { //整数部分小于零时
if (a1) {
printf("(%ld %ld/%ld) + 0 = (%ld %ld/%ld)\n", Z1, a1, b1, Z1, a1, b1);
printf("(%ld %ld/%ld) - 0 = (%ld %ld/%ld)\n", Z1, a1, b1, Z1, a1, b1);
printf("(%ld %ld/%ld) * 0 = 0\n", Z1, a1, b1); s3 = 0;
printf("(%ld %ld/%ld) / 0 = Inf\n", Z1, a1, b1); s4 = 0;
}
else {
printf("(%ld) + 0 = (%ld)\n", Z1, Z1); s1 = 0;
printf("(%ld) - 0 = (%ld)\n", Z1, Z1); s2 = 0;
printf("(%ld) * 0 = 0\n", Z1); s3 = 0;
printf("(%ld) / 0 = Inf\n", Z1); s4 = 0;
}
}
else if (Z1 > 0) { //整数部分大于零时
if (a1) {
printf("%ld %ld/%ld + 0 = %ld %ld/%ld\n", Z1, a1, b1, Z1, a1, b1);
printf("%ld %ld/%ld - 0 = %ld %ld/%ld\n", Z1, a1, b1, Z1, a1, b1);
printf("%ld %ld/%ld * 0 = 0\n", Z1, a1, b1);
printf("%ld %ld/%ld / 0 = Inf\n", Z1, a1, b1);
}
else {
printf("%ld + 0 = %ld\n", Z1, Z1);
printf("%ld - 0 = %ld\n", Z1, Z1);
printf("%ld * 0 = 0\n", Z1);
printf("%ld / 0 = Inf\n", Z1);
}
}
else {
printf("%ld/%ld + 0 = %ld/%ld\n", a1, b1, a1, b1); //整数部分为零 分数部分一定不为零
printf("%ld/%ld - 0 = %ld/%ld\n", a1, b1, a1, b1); //整数部分为零 分数部分一定不为零
printf("%ld/%ld * 0 = 0\n", a1, b1); //整数部分为零 分数部分一定不为零
printf("%ld/%ld / 0 = Inf\n", a1, b1); //整数部分为零 分数部分一定不为零
}
}
else if (!a1 && a2) { //第一个数为零
long int Tmp2GCD = GCD(a2, b2); //得到第二个数分子与分母的最大公约数
a2 /= Tmp2GCD;
b2 /= Tmp2GCD; //得到第二个数的最简分数形式
long int doa2 = a2, dob2 = b2; //用于实际运算
if (b2 == 1) { Z2 = a2 * Sign2; a2 = 0; } //若分母为整数
else if (a2 > b2) { Z2 = a2 / b2 * Sign2; a2 = a2 % b2; } //若为假分数
if (Z2 < 0) { //整数部分小于零时
if (a2) {
printf("0 + (%ld %ld/%ld) = (%ld %ld/%ld)\n", Z2, a2, b2, Z2, a2, b2);
printf("0 - (%ld %ld/%ld) = %ld %ld/%ld\n", Z2, a2, b2, -Z2, a2, b2);
printf("0 * (%ld %ld/%ld) = 0\n", Z2, a2, b2);
printf("0 / (%ld %ld/%ld) = 0\n", Z2, a2, b2);
}
else {
printf("0 + (%ld) = (%ld)\n", Z2, Z2);
printf("0 - (%ld) = %ld\n", Z2, -Z2);
printf("0 * (%ld) = 0\n", Z2);
printf("0 / (%ld) = 0\n", Z2);
}
}
else if (Z2 > 0) { //整数部分大于零时
if (a2) {
printf("0 + %ld %ld/%ld = %ld %ld/%ld\n", Z2, a2, b2, Z2, a2, b2);
printf("0 - %ld %ld/%ld = (%ld %ld/%ld\n)", Z2, a2, b2, -Z2, a2, b2);
printf("0 * %ld %ld/%ld = 0\n", Z2, a2, b2);
printf("0 / %ld %ld/%ld = 0\n", Z2, a2, b2);
}
else {
printf("0 + %ld = %ld\n", Z2, Z2);
printf("0 - %ld = (%ld)\n", Z2, -Z2);
printf("0 * %ld = 0\n", Z2);
printf("0 / %ld = 0\n", Z2);
}
}
else {
printf("0 + %ld/%ld = %ld/%ld\n", a2, b2, a2, b2); //整数部分为零 分数部分一定不为零
printf("0 - %ld/%ld = (-%ld/%ld)\n", a2, b2, a2, b2); //整数部分为零 分数部分一定不为零
printf("0 * %ld/%ld = 0\n", a2, b2); //整数部分为零 分数部分一定不为零
printf("0 / %ld/%ld = 0\n", a2, b2); //整数部分为零 分数部分一定不为零
}
}
else {
printf("0 + 0 = 0\n"); //两个数都是零
printf("0 - 0 = 0\n"); //两个数都是零
printf("0 * 0 = 0\n"); //两个数都是零
printf("0 / 0 = Inf\n"); //两个数都是零
}
}
return 0;
}
long int GCD(long int x, long int y) {
return (!y) ? x : GCD(y, x % y);
}
long int LCM(long int x, long int y) {
return x * y / GCD(x, y);
}