博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
30-语言入门-30-分数加减法
阅读量:5084 次
发布时间:2019-06-13

本文共 3664 字,大约阅读时间需要 12 分钟。

题目地址:   
 
描述
编写一个
C
程序,实现两个分数的加减法
输入
输入包含多行数据
每行数据是一个字符串,格式是
"a/boc/d"
其中
a, b, c, d
是一个
0-9
的整数。
o
是运算符
"+"
或者
"-"
数据以
EOF
结束
输入数据保证合法
输出
对于输入数据的每一行输出两个分数的运算结果。
注意结果应符合书写习惯,没有多余的符号、分子、分母,并且化简至最简分数
样例输入
1/8+3/8
1/4-1/2
1/3-1/3
样例输出
1/2
-1/4
0
 
 
代码:
 
#include <stdio.h>
typedef struct _Fraction
{
     //分子
     int numerator;
     //分母
     int denominator;
}Fraction;
//处理数据,并打印结果
static void handlerData(Fraction *lhs,Fraction *rhs,char symbol);
//通分
static void commonDenominator(Fraction *lhs,Fraction *rhs);
//计算两个分数加
static Fraction subFraction(Fraction *lhs,Fraction *rhs);
//计算两个分数减
static Fraction plusFraction(Fraction *lhs,Fraction *rhs);
//计算a和b的最大公约数
static int calCommonDivisor(int a,int b);
//计算a和b的最小公倍数
static int calCommonMultiple(int a,int b);
int main()
{
     int x1,y1,x2,y2;
     char symbol;
    
     do
     {
          scanf("%d/%d%c%d/%d",&x1,&y1,&symbol,&x2,&y2);
    
          Fraction lhs = {x1,y1};
          Fraction rhs = {x2,y2};
          handlerData(&lhs,&rhs,symbol);
     }while(getchar() != EOF);
    
     return 0;
}
//处理数据,并打印结果
static void handlerData(Fraction *lhs,Fraction *rhs,char symbol)
{
     Fraction result;
     switch(symbol)
     {
          case '+':
               result = subFraction(lhs,rhs);
               break;
          case '-':
               result = plusFraction(lhs,rhs);
     }
    
     if(result.numerator != 0)
     {
          if(result.denominator != 1)
          {
               printf("%d/%d\n",result.numerator,result.denominator);
          }
          else
          {
               printf("%d\n",result.numerator);
          }
     }
     else
     {
          printf("0\n");
     }
}
//通分
static void commonDenominator(Fraction *lhs,Fraction *rhs)
{
     int commonNumber = calCommonMultiple(lhs->denominator,rhs->denominator);
    
     //分子乘以分母通分的倍数
     lhs->numerator *= commonNumber / lhs->denominator;
     rhs->numerator *= commonNumber / rhs->denominator;
    
          //分母通分
     lhs->denominator = commonNumber;
     rhs->denominator = commonNumber;
}
//计算两个分数加
static Fraction subFraction(Fraction *lhs,Fraction *rhs)
{
     //先通分
     commonDenominator(lhs,rhs);
    
     int tmpNumerator = lhs->numerator + rhs->numerator;
     int tmpDenominator = lhs->denominator;
    
     int tmpDivisor = calCommonDivisor(tmpNumerator,tmpDenominator);
    
     Fraction result;
     result.denominator = tmpDenominator/tmpDivisor;
     result.numerator = tmpNumerator / tmpDivisor;
    
     return result;
}
//计算两个分数减
static Fraction plusFraction(Fraction *lhs,Fraction *rhs)
{
     //先通分
     commonDenominator(lhs,rhs);
    
     int tmpNumerator = lhs->numerator - rhs->numerator;
    
     int tmpDenominator = lhs->denominator;
    
     int tmpSymbol = 1;
     if(tmpNumerator < 0)
     {
          tmpSymbol = -1;
          tmpNumerator *= -1;
     }
    
     int tmpDivisor = calCommonDivisor(tmpNumerator,tmpDenominator);
    
     Fraction result;
     result.denominator = tmpDenominator/tmpDivisor;
     result.numerator = tmpNumerator / tmpDivisor * tmpSymbol;
    
     return result;
}
//计算a和b的最大公约数
static int calCommonDivisor(int a,int b)
{
    int maxNum = a>b?a:b;
    int minNum = a<b?a:b;
   
    int midResult = 0;
    while(minNum != 0)
    {
         midResult = maxNum % minNum;
        maxNum = minNum;
        minNum = midResult;
    }
   
    return maxNum;
}    
//计算a和b的最小公倍数
static int calCommonMultiple(int a,int b)
{
     int maxCommonDivisor = calCommonDivisor(a,b);
    return a*b/maxCommonDivisor;
}        
 
 
本题出错的地方有:
1.输入数据判断EOF,按照代码方式,唯一不方便的是采用了do..while...的方式。
2.输入数据的格式,开始采用了读取一行字符串的方式,在转换字符到数字的时候出错,不能使用atoi,atoi要求参数是char*,直接字符变量 str[i] - '0' 即可。
3.分母通分,是求的最小公倍数。而约分,是分子分母同时除以最大公约数。
4.commonDenominator 方法中,先求得最小公倍数,
此时需要先修改分子的值,最后再给分母赋最小公倍数的值。
5.两个数相加和两个数相减的时候,首先都是进行了通分,然后只需要进行分子的加减,分母要保证不变。
6.两个数相减的时候,分子只差有可能是0和负数的情况,如果是0则之前笔者写的求最大公约数的方法就是错误的返回了0
如上图代码,0是最小值,midResult余数的结果是0,然后返回了0.
这样导致分子分母除以最小公倍数的时候出错,因为分母是0的除法运算是非法的
所以最小公倍数的求解方法里面不应该返回0,本题目中的代码进行了判断,但是也不保证返回的是0.
 
7.最后反思求解的过程,
其实可以省去通分的步骤,学数学的时候,之所以先进行通分,是为了计算分子的时候,都是最小的数进行计算,但是计算机不在乎大数还是小数,只要保证在有效存储数值范围内即可,所以完全可以省略掉通分的过程以简化计算。直接将两个分母相乘进行最简单的通分运算来处理。
 
8.对测试数据的要求,至少需要3个数据,
a>b
a<b
a==b
 
9.容易忽略掉整数结果,比如
1/3+2/3
结果应该是
1
而如果不特殊处理的话,很容易输出为
1/1
也就是说分母是1的时候,要特殊处理
 

转载于:https://www.cnblogs.com/sharpfeng/p/5141890.html

你可能感兴趣的文章
nginx常见内部参数,错误总结
查看>>
对象与类
查看>>
《奸的好人2》财色战场----笔记
查看>>
BZOJ 1834网络扩容题解
查看>>
bzoj1878
查看>>
【Vegas原创】Mysql绿色版安装方法
查看>>
Thrift Expected protocol id ffffff82 but got 0
查看>>
分享《去哪儿网》前端笔试题
查看>>
2013-07-04学习笔记二
查看>>
CP15 协处理器寄存器解读
查看>>
【codeforces 787B】Not Afraid
查看>>
【9111】高精度除法(高精度除高精度)
查看>>
【hihocoder 1312】搜索三·启发式搜索(普通广搜做法)
查看>>
JavaFX中ObservableValue类型
查看>>
杭电 1097 A hard puzzle
查看>>
[转载]INFORMIX锁机制及如何剖析其锁申辩(第二部门)
查看>>
Andriod-项目stymqjlb-学习笔记2-原型
查看>>
Web AppDomain
查看>>
JQuery创建规范插件
查看>>
AD 域服务简介(三)- Java 对 AD 域用户的增删改查操作
查看>>