P 1034 有理数四则运算
转跳点:🐏
本题要求编写程序,计算 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
这道题比较麻烦,因为需要考虑的东西较多所以,容易少考虑一些情况。
1、我们需要考虑两个分数化简之后分母为0的不合法的情况。
2、存在异号的时候,考虑符号的输出和异号的判断(千万别相乘小于0,这玩意会炸long long都塞不下,除非你想用大数运算,同余模好像也行)
3、假分数要化成带分数,整数部分记得有空格
4、括号输出,这玩意和负号共存,置一个flag,为1时输出(-1,最后要结束的时候宅检查一遍flag用于输出 )
5、要注意PTA上gcc的C评测机的long long只有32位,所以gcc的C怎么提交都会出错(好吧,我比较懒,不想在想其他方法了,这也是我无意之中交错的时候发现的)
第五点是错的,我当时浅显的认为是评测机的问题 U•ェ•*U
大佬们,给个AC的C语言代码呗
AC代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 5 long long GCD(long long x, long long y) { return (0 == y) ? x : GCD(y, x % y); } 6 void Simplify(long long Molecule, long long Denominator); 7 8 int main(void) 9 { 10 11 long long DivdMoce, DivdDenom, DivsMoce, DivsDenom; 12 13 scanf("%lld/%lld %lld/%lld", &DivdMoce, &DivdDenom, &DivsMoce, &DivsDenom); 14 15 Simplify(DivdMoce, DivdDenom); printf(" + "); Simplify(DivsMoce, DivsDenom); printf(" = "); Simplify(DivdMoce * DivsDenom + DivdDenom * DivsMoce, DivdDenom * DivsDenom); printf("\n"); 16 Simplify(DivdMoce, DivdDenom); printf(" - "); Simplify(DivsMoce, DivsDenom); printf(" = "); Simplify(DivdMoce * DivsDenom - DivdDenom * DivsMoce, DivdDenom * DivsDenom); printf("\n"); 17 Simplify(DivdMoce, DivdDenom); printf(" * "); Simplify(DivsMoce, DivsDenom); printf(" = "); Simplify(DivdMoce * DivsMoce, DivdDenom * DivsDenom); printf("\n"); 18 Simplify(DivdMoce, DivdDenom); printf(" / "); Simplify(DivsMoce, DivsDenom); printf(" = "); Simplify(DivdMoce * DivsDenom, DivdDenom * DivsMoce); 19 20 return 0; 21 } 22 23 void Simplify(long long Molecule, long long Denominator) 24 { 25 //分母是否合法 26 if (0 == Molecule * Denominator) 27 { 28 printf("%s", 0 == Denominator ? "Inf" : "0"); 29 return; 30 } 31 32 //正负号判定 33 int flag = ((Molecule > 0 && Denominator < 0) || (Molecule < 0 && Denominator > 0)); 34 //先输出符号 35 printf("%s", 0 == flag ? "" : "(-"); 36 37 //去除符号问题,简化最大公约数求取过程 38 Molecule = abs(Molecule); 39 Denominator = abs(Denominator); 40 41 //获取商,准备输出带分数整数部分 42 long long Interger = Molecule / Denominator; 43 //如果是假分数,那么化为带分数并输出整数部分 44 if (0 != Interger) 45 { 46 printf("%lld", Interger); 47 } 48 //检测能否被整除 49 if (0 == Molecule % Denominator) 50 { 51 if (1 == flag) 52 { 53 printf(")"); 54 } 55 return; 56 } 57 //补上带分数正整数部分的空格 58 if (0 != Interger) 59 { 60 printf(" "); 61 } 62 63 Molecule = Molecule - Denominator * Interger; 64 long long gcd = GCD(Molecule, Denominator); 65 66 printf("%lld/%lld%s", Molecule / gcd, Denominator / gcd, 1 == flag ? ")" : ""); 67 }
记得用C++提交
刚刚,小姐姐说我太懒了,嗯,赶紧改正,我写了一份C的AC代码,可以用GCC 的 C 交,而且我知道为什么原本的会错了,
上一个版本我用了abs,这个函数只能返回 int 大小的数据,所以返回后导致精度丢失,导致结果错误。
这是C语言AC的代码
#include <stdio.h> long long GCD(long x, long y) { return (0 == y) ? x : GCD(y, x % y); } long Simplify(long Molecule, long Denominator); int main(void) { long DivdMoce, DivdDenom, DivsMoce, DivsDenom; scanf("%ld/%ld %ld/%ld", &DivdMoce, &DivdDenom, &DivsMoce, &DivsDenom); Simplify(DivdMoce, DivdDenom);printf(" + ");Simplify(DivsMoce, DivsDenom);printf(" = ");Simplify(DivdMoce * DivsDenom + DivsMoce * DivdDenom, DivdDenom * DivsDenom);printf("\n"); Simplify(DivdMoce, DivdDenom);printf(" - ");Simplify(DivsMoce, DivsDenom);printf(" = ");Simplify(DivdMoce * DivsDenom - DivsMoce * DivdDenom, DivdDenom * DivsDenom);printf("\n"); Simplify(DivdMoce, DivdDenom);printf(" * ");Simplify(DivsMoce, DivsDenom);printf(" = ");Simplify(DivdMoce * DivsMoce, DivdDenom * DivsDenom);printf("\n"); Simplify(DivdMoce, DivdDenom);printf(" / ");Simplify(DivsMoce, DivsDenom);printf(" = ");Simplify(DivdMoce * DivsDenom, DivdDenom * DivsMoce); return 0; } /** * 非递归版辗转相除法(a>b) long GCD(long Molecule, long Denominator) { //辗转相除法求最大公约数 long gcd = Molecule % Denominator; while (gcd != 0) { Molecule = Denominator; Denominator = gcd; gcd = Molecule % Denominator; } return Denominator; } **/ long Simplify(long Molecule, long Denominator) { if (Denominator == 0) { printf("Inf"); return 0; } //符号判断 int flag = 1; //确定符号,取绝对值,避开abs if (Denominator < 0) { Denominator *= -1; flag *= -1; } if (Molecule < 0) { Molecule = -Molecule; flag *= -1; } if (flag == -1) { printf("(-"); } //约分为最简分数 long gcd = GCD(Molecule, Denominator); Molecule = Molecule / gcd; Denominator = Denominator / gcd; if (1 == Denominator) { //假分数 printf("%ld", Molecule); } else if (Molecule < Denominator) { //正常分数 printf("%ld/%ld", Molecule, Denominator); } else if (Molecule > Denominator) { //带分数 printf("%ld %ld/%ld", Molecule / Denominator, Molecule % Denominator, Denominator); } if (flag == -1) { printf(")"); } return 0; }
PTA不易,诸君共勉!