30-语言入门-30-分数加减法

题目地址:?http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=111?

?

描述
编写一个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的时候,要特殊处理

?

时间: 2024-10-29 19:09:44

30-语言入门-30-分数加减法的相关文章

【转】正则表达式30分钟入门教程

首页 | 常用正则表达式 | 正则表达式测试工具 正则表达式30分钟入门教程 版本:v2.33 (2013-1-10) 作者:deerchao 转载请注明来源 目录 跳过目录 本文目标 如何使用本教程 正则表达式到底是什么东西? 入门 测试正则表达式 元字符 字符转义 重复 字符类 分枝条件 反义 分组 后向引用 零宽断言 负向零宽断言 注释 贪婪与懒惰 处理选项 平衡组/递归匹配 还有些什么东西没提到 联系作者 网上的资源及本文参考文献 更新纪录 本文目标 30分钟内让你明白正则表达式是什么,

HTML 30分钟入门教程

本文目标 30分钟内让你明白HTML是什么,并对它有一些基本的了解.一旦入门后,你可以从网上找到更多更详细的资料来继续学习. 什么是HTML HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,它规定了自己的语法规则,用来表示比"文本"更丰富的意义,比如图片,表格,链接等.浏览器(IE,FireFox等)软件知道HTML语言的语法,可以用来查看HTML文档.目前互联网上的绝大部分网页都是使用HTML编写的. HTML是什么样的 简单地来说,HT

正则表达式30分钟入门教程 都是复制的

正则表达式30分钟入门教程 来园子之前写的一篇正则表达式教程,部分翻译自codeproject的The 30 Minute Regex Tutorial. 由于评论里有过长的URL,所以本页排版比较混乱,推荐你到原处查看,看完了如果有问题,再到这里来提出. 一些要说的话: 如果你没有正则表达式的基础,请跟着教程“一步步来”.请不要大概地扫两眼就说看不懂——以这种态度我写成什么样你也看不懂.当我告诉你这是“30分钟入门教程”时,请不要试图在30秒内入门. 事实是,我身边有个才接触电脑,对操作都不是

正则表达式30分钟入门教程(转)

来园子之前写的一篇正则表达式教程,部分翻译自codeproject的The 30 Minute Regex Tutorial. 由于评论里有过长的URL,所以本页排版比较混乱,推荐你到原处查看,看完了如果有问题,再到这里来提出. 一些要说的话: 如果你没有正则表达式的基础,请跟着教程“一步步来”.请不要大概地扫两眼就说看不懂——以这种态度我写成什么样你也看不懂.当我告诉你这是“30分钟入门教程”时,请不要试图在30秒内入门. 事实是,我身边有个才接触电脑,对操作都不是很熟练的人通过自己学习这篇教

js正则表达式30分钟入门教程

2011-10-27 13:23:15 如何使用本教程 最重要的是——请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门——除非你是超人 :) 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有你 想像中的那么困难.当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的——我认为,没接触过正则表达式的人在看 完这篇教程后,能把提到过的语法记住80以上的可能性为零.这里只是让你明白基本的原理,以后你还需要多练习,

正则表达式30分钟入门

来源:http://deerchao.net/tutorials/regex/regex.htm#lookaround 正则表达式30分钟入门教程 版本:v2.33 (2013-1-10) 作者:deerchao 转载请注明来源 目录 跳过目录 本文目标 如何使用本教程 正则表达式到底是什么东西? 入门 测试正则表达式 元字符 字符转义 重复 字符类 分枝条件 反义 分组 后向引用 零宽断言 负向零宽断言 注释 贪婪与懒惰 处理选项 平衡组/递归匹配 还有些什么东西没提到 联系作者 网上的资源及

正则表达式30分钟入门教程 ——堪称网上能找到的最好的正则式入门教程

本教程堪称网上能找到的最好正则表达式入门教程 原地址:http://www.jb51.net/tools/zhengze.html 本文目标 30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它. 如何使用本教程 最重要的是——请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门——除非你是超人 :) 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有想像中的那么困难.当然,如果你看完了这篇教程之后,发现

转:正则表达式30分钟入门教程

来园子之前写的一篇正则表达式教程,部分翻译自codeproject的The 30 Minute Regex Tutorial. 由于评论里有过长的URL,所以本页排版比较混乱,推荐你到原处查看,看完了如果有问题,再到这里来提出. 一些要说的话: 如果你没有正则表达式的基础,请跟着教程“一步步来”.请不要大概地扫两眼就说看不懂——以这种态度我写成什么样你也看不懂.当我告诉你这是“30分钟入门教程”时,请不要试图在30秒内入门. 事实是,我身边有个才接触电脑,对操作都不是很熟练的人通过自己学习这篇教

DAX基础入门 – 30分钟从SQL到DAX — PowerBI 利器

看到漂漂亮亮的PowerBI报表,手痒痒怎么办?! 有没有面对着稀奇古怪的DAX而感到有点丈八金刚摸不着头脑或者干瞪眼?! 有没有想得到某个值想不出来DAX怎么写而直跳脚!? 看完这篇文章,你会恍然大悟,捂脸偷笑.呼呼呼~ 前言: 这篇文章对于具有一点SQL查询基础人会十分容易理解,譬如:掌握SELECT,SUM,GROUP BY等. 注:此文不涉及到Filter Context(筛选上下文)的介绍. 正文: 对于对SQL有一定了解的人来说,咋看DAX,怎么都不习惯. 但是,如果理解以下几个后,

PHP正则表达式30分钟入门教程

正则表达式30分钟入门教程 三个常用的知识点: 1.惰性匹配:正则引擎默认是贪婪的,若要最少重复的话,需要用到惰性匹配符 “?” 懒惰限定符 代码/语法 说明 *? 重复任意次,但尽可能少重复 +? 重复1次或更多次,但尽可能少重复 ?? 重复0次或1次,但尽可能少重复 {n,m}? 重复n到m次,但尽可能少重复 {n,}? 重复n次以上,但尽可能少重复 参考:http://deerchao.net/tutorials/regex/regex.htm#greedyandlazy 2.不捕获性匹配