PAT乙级1034-----有理数四则运算 (20分)(错)

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:忘记把分子化为最简
View Code

想了很久找不到哪里出错了

只能去参考别人的代码进行改进

参考的代码:

 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 }
View Code

FROM:https://www.cnblogs.com/gh110/p/12158217.html

改进后的代码:

 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 }
View Code

换用成func函数后通过

改进后的思路(func函数):

  1. 首先判断分母是否为0决定输出Inf——此情况只有在除法才可能发生,因为除法交换除数的分子分母,而题设输入的分母不会为0
  2. 根据输入的分子a,分母b的符号判断最终的符号
  3. 根据分子分母的大小比较决定输出的结果

错误总结:

  1. 逻辑错误:input函数中的某种情况我可能没有考虑到
  2. 代码过于复杂不够简洁精炼导致后续检查花费时间太多
原文地址:https://www.cnblogs.com/a982961222/p/12357426.html