zoukankan      html  css  js  c++  java
  • 30-语言入门-30-分数加减法

     
    描述
    编写一个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 ",result.numerator,result.denominator);
              }
              else
              {
                   printf("%d ",result.numerator);
              }
         }
         else
         {
              printf("0 ");
         }
    }

    //通分
    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的时候,要特殊处理
     
  • 相关阅读:
    吴恩达机器学习笔记——梯度下降算法(2)
    吴恩达机器学习笔记——梯度下降算法(1)
    Java面向对象
    实体框架
    Android Studio 3.4.1中使用com.android.support.v4.view.ViewPager提示不存在该类或程序闪退
    7、认识 Android Service
    安卓付费课程
    在Android Studio中如何添加GSON
    android studio 添加Volley
    android studio里面怎么看file explorer啊?
  • 原文地址:https://www.cnblogs.com/sharpfeng/p/5141890.html
Copyright © 2011-2022 走看看