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
思路1:
1.将输入的分数分成 整数 分子 分母 符号 并将分子分母通分
2.根据符号确定输出格式即为负要加()和负号
3.判断分母是否为1决定是否只有整数
4.判断整数是否为0决定是否加入整数
首次代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 //辗转相除法求两个数的最大公因数 5 long long hcf(long long a,long long b){ 6 long long r=a%b; 7 while(r!=0){ 8 a=b; 9 b=r; 10 r=a%b; 11 } 12 return b>1?b:1; 13 } 14 //输出分数 15 void input(long long k1,long long a1,long long a2,int flag){ 16 //符号为负 17 if(flag){ 18 if(k1==0) printf("(-%lld/%lld)",a1,a2); 19 else { 20 if(a2==1) printf("(-%lld)",k1); 21 else printf("(-%lld %lld/%lld)",k1,a1,a2); 22 } 23 } 24 else { 25 if(a1==0) printf("0"); 26 else if(a2==1) printf("%lld",k1); 27 else if(k1!=0) printf("%lld %lld/%lld",k1,a1,a2); 28 else printf("%lld/%lld",a1,a2); 29 } 30 } 31 int main(){ 32 long long f1,f2,g1,g2;//输入的分子分母 33 int flag1=0,flag2=0;//进行运算的两个数的符号 0为正 1为负 34 scanf("%lld/%lld %lld/%lld",&f1,&f2,&g1,&g2); 35 if(f1<0) flag1=1; 36 if(g1<0) flag2=1; 37 long long k1=0,k2=0;//整数部分 38 long long a1=abs(f1),a2=f2,b1=abs(g1),b2=g2;//a1 b1为分子 a2 b2为分母 39 long long h1=hcf(a1,a2);//a1 a2最大公因数 40 long long h2=hcf(b1,b2);//b1 b2最大公因数 41 a1/=h1;a2/=h1;b1/=h2;b2/=h2;//上下通分 42 k1=a1/a2;//提出整数部分 43 k2=b1/b2; 44 a1=a1%a2;//分子化为最简 45 b1=b1%b2;//分子化为最简 46 for(int i=0;i<4;i++){ 47 input(k1,a1,a2,flag1); 48 //输出运算符号 49 switch(i){ 50 case 0:printf(" + ");break; 51 case 1:printf(" - ");break; 52 case 2:printf(" * ");break; 53 case 3:printf(" / ");break; 54 } 55 input(k2,b1,b2,flag2); 56 printf(" = "); 57 switch(i){ 58 //加法 59 case 0:{long long c1=f1*g2+f2*g1;long long c2=f2*g2;//用初始的分子分母通分进行计算 60 int flag3=0;if(c1<0) flag3=1;c1=abs(c1); 61 long long h3=hcf(c1,c2);c1/=h3;c2/=h3;long long k3=c1/c2;c1=c1%c2; 62 input(k3,c1,c2,flag3);printf(" ");break;} 63 //减法 64 case 1:{long long c1=f1*g2-f2*g1;long long c2=f2*g2; 65 int flag3=0;if(c1<0) flag3=1;c1=abs(c1); 66 long long h3=hcf(c1,c2);c1/=h3;c2/=h3;long long k3=c1/c2;c1=c1%c2; 67 input(k3,c1,c2,flag3);printf(" ");break;} 68 //乘法 69 case 2:{long long c1=f1*g1;long long c2=f2*g2; 70 int flag3=0;if(c1<0) flag3=1;c1=abs(c1); 71 long long h3=hcf(c1,c2);c1/=h3;c2/=h3;long long k3=c1/c2;c1=c1%c2; 72 input(k3,c1,c2,flag3);printf(" "); break;} 73 //除法 74 case 3:{long long c1=f1*g2;long long c2=f2*g1; 75 if(!c2) {printf("Inf");break;} 76 int flag3=0;if((c1<0&&c2>0)||(c1>0&&c2<0)) flag3=1;c1=abs(c1);c2=abs(c2); 77 long long h3=hcf(c1,c2);c1/=h3;c2/=h3;long long k3=c1/c2;c1=c1%c2; 78 input(k3,c1,c2,flag3);break;} 79 } 80 } 81 return 0; 82 } 83 84 //错误1:忘记把分子化为最简
想了很久找不到哪里出错了
只能去参考别人的代码进行改进
参考的代码:
1 #include <stdio.h> 2 long gcd(long a,long b){//辗转相除法求最大公约数 3 long r=a%b; 4 while(r!=0){ 5 a=b; 6 b=r; 7 r=a%b; 8 } 9 return b; 10 } 11 long func(long a,long b){ 12 if(b==0){ 13 printf("Inf"); 14 return 0; 15 } 16 int sam=1; 17 if(a<0){ 18 a=-a; 19 sam=sam*(-1); 20 } 21 if(b<0){ 22 b=-b; 23 sam=sam*(-1); 24 } 25 //约分为最简分数 26 long r=gcd(a,b); 27 a=a/r; 28 b=b/r; 29 if(sam==-1){ 30 printf("(-"); 31 } 32 if(b==1){ 33 printf("%ld",a); 34 }else if(a<b){ 35 printf("%ld/%ld",a,b); 36 }else if(a>b){ 37 printf("%ld %ld/%ld",a/b,a%b,b); 38 } 39 if(sam==-1){ 40 printf(")"); 41 } 42 return 0; 43 } 44 int main(){ 45 long c,d,e,f; 46 scanf("%ld/%ld %ld/%ld",&c,&d,&e,&f); 47 //加法 48 func(c,d); 49 printf(" + "); 50 func(e,f); 51 printf(" = "); 52 func(c*f+e*d,d*f); 53 printf(" "); 54 //减法 55 func(c,d); 56 printf(" - "); 57 func(e,f); 58 printf(" = "); 59 func(c*f-e*d,d*f); 60 printf(" "); 61 //乘法 62 func(c,d); 63 printf(" * "); 64 func(e,f); 65 printf(" = "); 66 func(c*e,d*f); 67 printf(" "); 68 //除法 69 func(c,d); 70 printf(" / "); 71 func(e,f); 72 printf(" = "); 73 func(c*f,d*e); 74 return 0; 75 }
改进后的代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 //辗转相除法求两个数的最大公因数 5 long long hcf(long long a,long long b){ 6 long long r=a%b; 7 while(r!=0){ 8 a=b; 9 b=r; 10 r=a%b; 11 } 12 return b>1?b:1; 13 } 14 //输出分数 15 long func(long a,long b){ 16 if(b==0){ 17 printf("Inf"); 18 return 0; 19 } 20 int sam=1; 21 if(a<0){ 22 a=-a; 23 sam=sam*(-1); 24 } 25 if(b<0){ 26 b=-b; 27 sam=sam*(-1); 28 } 29 //约分为最简分数 30 long r=hcf(a,b); 31 a=a/r; 32 b=b/r; 33 if(sam==-1){ 34 printf("(-"); 35 } 36 if(b==1){ 37 printf("%ld",a); 38 }else if(a<b){ 39 printf("%ld/%ld",a,b); 40 }else if(a>b){ 41 printf("%ld %ld/%ld",a/b,a%b,b); 42 } 43 if(sam==-1){ 44 printf(")"); 45 } 46 return 0; 47 } 48 int main(){ 49 long long f1,f2,g1,g2;//输入的分子分母 50 scanf("%lld/%lld %lld/%lld",&f1,&f2,&g1,&g2); 51 for(int i=0;i<4;i++){ 52 func(f1,f2); 53 //输出运算符号 54 switch(i){ 55 case 0:printf(" + ");break; 56 case 1:printf(" - ");break; 57 case 2:printf(" * ");break; 58 case 3:printf(" / ");break; 59 } 60 func(g1,g2); 61 printf(" = "); 62 switch(i){ 63 //加法 64 case 0:{long long c1=f1*g2+f2*g1;long long c2=f2*g2;//用初始的分子分母通分进行计算 65 func(c1,c2);printf(" "); 66 break;} 67 //减法 68 case 1:{long long c1=f1*g2-f2*g1;long long c2=f2*g2; 69 func(c1,c2);printf(" ");break;} 70 //乘法 71 case 2:{long long c1=f1*g1;long long c2=f2*g2; 72 func(c1,c2);printf(" "); break;} 73 //除法 74 case 3:{long long c1=f1*g2;long long c2=f2*g1; 75 func(c1,c2);break;} 76 } 77 } 78 return 0; 79 }
换用成func函数后通过
改进后的思路(func函数):
- 首先判断分母是否为0决定输出Inf——此情况只有在除法才可能发生,因为除法交换除数的分子分母,而题设输入的分母不会为0
- 根据输入的分子a,分母b的符号判断最终的符号
- 根据分子分母的大小比较决定输出的结果
错误总结:
- 逻辑错误:input函数中的某种情况我可能没有考虑到
- 代码过于复杂不够简洁精炼导致后续检查花费时间太多