自由函数计算器.docx
- 文档编号:24549459
- 上传时间:2023-05-28
- 格式:DOCX
- 页数:23
- 大小:435.39KB
自由函数计算器.docx
《自由函数计算器.docx》由会员分享,可在线阅读,更多相关《自由函数计算器.docx(23页珍藏版)》请在冰豆网上搜索。
自由函数计算器
暑假实习结题论文
自由函数计算器
姓名:
曹晓亮
学校:
江西理工大学
专业:
自动化
导师:
李志勤
日期:
2011年8月21日
摘要
计算器在当今社会的应用无处不在,大到政府、公司,小到家庭个人,计算器已经广泛应用到了社会的方方面面。
。
但是,常用计算器的功能不够丰富,比如我们手机上的计算器程序,只能进行简单的加减乘除的运算,而且要一个数字一个数字的进行输入,功能差而且效率低。
本项目所设计的计算器叫做“自由函数计算器”,属于表达式计算器这一类,它可以任由你输入一串算式,其中可以包含加减乘除、括号、三角函数等各种运算符,而且括号可以多重嵌套,计算数据位双精度型,精确度较高。
更重要的是具有一定的拓展性。
关键词:
计算器表达式
Abstract
Calculatorsisusedwidelyinthemodernsociety.Itisusedinthegovernment,companies,andeveryoneofus.Wecan’tleavecalculatorsindailylife.
However,calculatorsweareusingaretoosimple.Forexample,thepocketcalculatorweuseonlycandealwithplus,minus,multiplyanddivide.What’smore,itcanonlyacceptthedigitweinputonebyone.
Thecalculatordesignedintheprojectiscalled“FreeFunctionCalculator”.Itisakindofexpressioncalculator,whichcanacceptanymathematicsexpressionsusersinput,andtheexpressionincludingofaddition,minus,multiply,anddivide,power,alsotrigonometricfunctionincluded.What’smore,userscaninputmanyparentheses,thecalculatorcanmakeit.Thetypeofdatacalculateinthecalculaorisdouble,soitisveryexactitude.Andthemostimportantisthatthecalculatorissamehowexpansibility.
keywords:
calculatorexpansibilityupdate
目录
1.引言1
1.1项目背景1
2.需求分析2
2.1功能要求2
2.2功能分析2
3.关键技术3
3.1字符串表达式的处理3
3.2优先级顺序3
3.3拓展性…………………………………………………………………………………...4
4.概要设计5
4.1主要构架5
4.2程序的主要模块设计5
4.2.1字符串处理模块5
4.2.2优先级处理模块6
4.2.3报错处理模块7
5.详细设计9
5.1数据结构9
5.2优先级的判断9
5.3表达式的运算10
5.4不同进制的运算12
6.设计结果13
7.总结14
7.1自我总结14
7.2软件总结14
8.致谢16
9.参考文献17
1.引言
随着经济的快速发展,计算机已经运用到很多的地方,特别是对于经济话的市场,统计
数据,都要用到计算器,这种计算器精度要求很高,运算也很复杂。
但相对于科学研究方面的计算机精度更是很高。
我们平常多使用只能够进行加减乘除的计算器,对学习方面也·很少用到计算器,主要是老师不准我们使用,要求不能靠工具。
暑假来到公司实习,给了我们自由函数计算器的题目,于是就开是了课题的设计。
1.1项目背景
现实生活中计算器无处不在,学校,商场等等,那些简单的计算器只能够进行一些简单的运算,如果要计算很长的运算则必须很谨慎才能够计算出结果出来。
但对于我们在生活中那种计算器还是可以染很多人满足的。
这种普通计算器不能满足数学方面的要求,并且输入时可能会出错,不容易检查,且在计算一些长的运算,需要先手写出结果,再用这些结果继续运算。
现在本项目的自由函数计算器能够把这些缺点弥补,只要输入你想计算的一个表达式,就会输出一个答案,并且在输入表达式错误的时候会给予提醒。
2.需求分析
2.1功能要求
1.能够进行加减乘除运算;
2.能够对sin,cos等三角函数进行计算;
3.能够判断运算的先后顺序;
4.能够对括号进行判断;
5.能够实现不同进制的运算;
5.具有一定的拓展性。
2.2功能分析
对于自由函数计算器的加减乘除可以很容易的实现,只要处理好相应的表达式,即可以输出结果。
在处理不同的运算符时,可以运用堆栈的处理方法对表达式中的操作数和运算符进行出栈和进栈的操作。
如下图是对一个表达式2*(1+3/3)的处理过程。
用堆栈的处理方法能够很容易的处理一些复杂的运算,特别是对有多层嵌套括号的运算。
图2.2表达式处理
3.关键技术
3.1字符串表达式的处理
输入任意的一个表达式,怎样让程序知道哪个是运算符,还是操作数。
这很好处理字符串大于‘0’,小于‘9’的肯定是数字了,只要将char型转换为double型即可,这需要调用atof这个函数。
操作数当然是‘+’,‘-’,‘*’,‘/’,’^’,sin等一些运算符了,只要记住这些运算符就可以了,当进行到某个运算时,直接进行运算就可以了。
但怎样存储操作数和运算符呢?
本项目采用堆栈的方法存储这两部分,从而需要建立两个堆栈,一个是操作数栈,一个是运算符栈,如图3.1。
图3.1运算符与操作数栈
3.2优先级顺序
对无括号的肯定是先进行一些特殊的运算,运算完之后肯定是再进行乘除,最后再进行加减了。
图3.2运算符先后顺序
对有括号,特别是有多层括号的,则可以先处理最里面的括号,而后依次减少括号。
用堆栈的处理方法就是,直到找到与之相匹配才进行出栈操作。
但按照这种方法,必须先找到最内层括号,而后看有没有特殊的运算符,最后看有没有乘除,这样的操作比较的麻烦,处理的效果不是很好。
于是可以用一种查表的方法来进行运算,所有的运算符都在一张运算符优先顺序表(如图3.2)中,当遇到运算符的话,优先级高的可以进行运算将结果进栈就可以了,优先级低的,就将运算数和操作数都入栈。
3.3拓展性
为了以后能够很方便的进行运算的拓展,在程序设计之前一定要进行设计好。
在此项目中,可以在运算符优先级表中进行增加一些新的运算符,重新绘制这个表,并在相关的地方改动一些就可以进行这种运算符的运算了。
4.概要设计
项目名称:
自由函数计算器
开发语言:
C/C++语言
基本功能:
1.能够进行加减乘除运算
2.能够对sin,cos等三角函数进行计算
3.能够判断运算的先后顺序
4.能够对括号进行判断
5.能够实现不同进制的运算
5.具有一定的拓展性
完整要求:
解决方案:
1.存储方案:
使用堆栈的存储结构方案进行存储
2.字符识别方案:
根据相对应的字符转化为数字和运算符,运算符通过匹配相应的字母来调用相对应的函数,可根据实际情况来判断需要匹配几个字母,
3.优先级分配解决方案:
先计算括号里面的运算,然后计算特殊的运算如三角函数等,而后就是乘除,最后是加减了。
4.提高扩展性解决方案:
处理好各种优先级的问题。
再添加一些新的运算时,可以先编写新的运算函数,而后在优先级表中添加即可。
4.1主要构架
设计自由函数的主要构架是先进行字符串表达式的处理,而后是对运算符的优先级判断,最后是对相应函数的调用。
对于字符串的处理可以直接进行判断,是数字字符串转化为数字就可以了,是运算符就进行相应的处理,可以是入栈或者是直接进行调用函数进行运算。
而对于运算符的优先级判断则可以利用查表的方法进行运算,最后就是运算数结果了。
4.2程序的主要模块设计
4.2.1字符串处理模块
对字符串处理的处理比较简单,只需要几个简单的判断语句就足够了。
由于用堆栈的存储结构来存储,可以不用单独的将运算符和操作数分离开来,只需要在入栈的时候进行判断就可以了,是操作符则进入操作符栈,是运算符栈则进入运算符栈,这样处理起来比较的简单,不需要对运算符和操作数进行很复杂的运算只需要有规律的出栈和进栈就可以。
如图4.2.1.
图4.2.1字符串处理图
⏹4.2.2优先级处理模块
对优先级的判断,只要清楚各运算符的运算顺序就能够进行非常正确的操作,因为本程序对于优先级的问题绘制了一张运算符操作顺序表,只需要通过查表就能够进行相对应的运算。
优先级问题是本程序的关键,特别是对有多层括号的表达式来说只要优先级分配好的话,其操作很简单。
开始使用链表的处理方法,但对于括号的问题很难解决,相反应用对栈的处理方法,很快就解决了,而且不管有多层的括号都会处理的非常的准确。
具示
图4.2.2优先级处理图
4.2.3报错处理模块
对于报错处理可以分为几个部分:
1.非法字符的报错;
2.括号的报错;
3.运算符重复的报错;
4.非十进制数的报错。
处理好了这四部分,报错处理已经很完善了,当然还有些错误,没有处理好,这还需要把各个报错处理的很好。
对于括号的处理不能够只看是否左括号和右括号的数目相等,而应该看括号是否完全的匹配。
对于报错处理的情况如图4.2.3所示
图4.2.3报错处理图
5.详细设计
对于程序的设计只要整体上思路出来了,下面的程序问题很快就会完成。
但对于有些细节方面的问题,在写程序之前没考虑好的话,可能会很难处理,即使处理好的话,可能还不是那么的理想。
下面将会具体的介绍各个问题的具体实现方法。
5.1数据结构
本程序采取堆栈的处理方式。
栈是限定在仅在表尾进行插入或删除操作的线性表。
因此,对栈来说,表尾端有其特殊含义,称为栈顶,表头端称为栈底。
栈中的元素按照一定的次序进栈,退栈的第一个元素应是栈顶元素。
可以说,栈的修改是按后进先出的原则进行的。
因此,栈又称为后进先出的线性表。
下面是定义了一个堆栈的结构体
typedefdoubleSElemType;//所指向指针的类型
//定义堆栈结构体
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
图5.1.1程序清单_堆栈结构体
对于一个堆栈的初始化,只要分配好内存就可以了,下面是对一个堆栈的初始化
/********************************************************************
**函数名称:
InitStack
**函数功能:
初始化堆栈,使其为空
**入口参数:
S(堆栈结构体)
**返回值:
初始化成功1,或失败0
*********************************************************************/
voidInitStack(SqStack&S)
{
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S.base)
{
printf("分配内存失败");
}
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
图5.1.2程序清单_堆栈初始化1
5.2优先级的判断
对于函数优先级的判断可以对运算符进行出栈和入栈的操作。
对优先级高的可以进行出栈的操作,优先级低的暂时不出栈,怎样让程序知道运算符优先级,在上面已经绘制了一张运算符优先级表,只要将其在程序中描述即可,如下定于了一个二维数组,来对应相应的运算优先级表。
其顺序和图3.2运算符先后顺序相对应,2代表>,1代表<,3代表=
inta[][12]=
{
2,2,1,1,1,2,1,1,1,1,1,2,
2,2,1,1,1,2,1,1,1,1,1,2,
2,2,2,2,1,2,1,1,1,1,1,2,
2,2,2,2,1,2,1,1,1,1,1,2,
1,1,1,1,1,3,1,1,1,1,1,2,
2,2,2,2,0,2,2,2,2,2,2,0,
2,2,2,2,1,2,2,2,1,1,1,2,
2,2,2,2,1,2,2,2,2,2,2,2,
2,2,2,2,1,2,2,2,2,2,2,2,
2,2,2,2,1,2,2,2,2,2,2,2,
2,2,2,2,1,2,2,2,2,2,2,2,
1,1,1,1,1,0,1,1,1,1,1,3
};
/********************************************************************
**函数名称:
Precedence
**函数功能:
进行优先级的判断
**入口参数:
运算符a1,a2
**返回值:
f返回结果
*********************************************************************/
intprecedence(SElemTypet,chart2)
{
chart1;
t1=(char)t;
returna[optrtoi(t1)][optrtoi(t2)];/*对应在二维数组中的位置*/
}
图5.1.3程序清单_优先级二维数组
5.3表达式的运算
对一个表达式,已经知道了各个运算符的优先级顺序,只要进行合理的进栈和出栈操作就可以了。
为了最后出栈的方便,在最开始的时候,先要将‘=’压入运算符栈,以便在结束的时候进行最后一次出栈,但前提要是要在表达式的最后一个字符是‘=’。
可以在最后不输入=,但可以另外再加=。
对数字和运算符出栈进栈的代码如下图程序清单。
/*************************************************************************
**函数名称:
expression
**函数功能:
对函数表达式进行处理
**入口参数:
*p
**返回值:
x返回结果
*************************************************************************/
SElemTypeexpression(char*p)
{
SqStackOPTR;
SqStackOPND;
charstr[256];
InitStack(OPTR);/*初始化运算符栈*/
Push(OPTR,'=');/*开始进栈'=',方便判断*/
InitStack(OPND);/*初始化操作数栈*/
c=*p++;/*开始第一个字符比较*/
GetTop(OPTR,x);
while(x!
='='||c!
='=')/*当遇到'=',就结束*/
{
if(In(c))
{
switch(precedence(x,c))/*优先级比较*/
{
case1:
{
Push(OPTR,c);
c=*p++;
}break;
case2:
{
Pop(OPTR,theta);
if(theta=='s'||theta=='c'||theta=='l'||theta=='e')
/*是sin,cos等只需入栈一个操作数*/
{
Pop(OPND,a);
Push(OPND,operateother(a,theta));
}
else
{
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,operate(a,b,theta));
}
}break;
case3:
{
Pop(OPTR,x);
c=*p++;
}break;
}
if((c>='0'&&c<='9'))/*操作数入栈*/
{
i=0;
do
{
str[i]=c;
i++;
c=*p++;
}while((c>='0'&&c<='9')
Push(OPND,d);
}
if(!
EmptyStack(OPTR))
GetTop(OPTR,x);/*得到栈顶运算符*/
}
GetTop(OPND,x);/*出栈最后结果*/
returnx;
}
图5.1.4程序清单_表达式处理代码
5.4不同进制的运算
不同进制的运算本质和十进制的运算是一样的,只要把非十进制转化为十进制,并且将此数入栈即可。
所以在输入不同进制的时候,一定要标记是哪个进制。
本项目规定是二进制的一定要在其后加上B八进制的在后面加O十六进制的后面加H。
6.
设计结果
图6.界面图1
图6.界面图2
7.总结
7.1自我总结
在广州学习的这段时间,有很多东西需要学习。
本打算可以学到很多,数据结构啊,很多c语言的算法啊。
事实上并没有学到那么多。
在这开的几次课程,是一些最基本的课程,文档规范课,代码规范课,ppt制作课,而其实这些最基本的自己都没有学好,怎样为以后做准备呢。
这些在学校的时候训练的很少,以后要在校要多多的训练,不然连自己写的东西都看不明白的话,在这个社会很难适应下去。
对于数据结构,现在是了解了链表和堆栈,本想学习树的,问了下导师,给我的意见是不需要学习。
但感觉学习是一定要的,只是掌握的情况罢了。
以后谁也不知道那个是要学或者不要学,只要自己感觉到能学到东西就可以了。
其实我们学了多么多东西,从小学到大学,我们学到了什么,是知识还是些其它的东西。
我们大家和导师们也导论过,导师们一致告诉我们,我们需要学习的是能力,而非只是本身,世界要有很多需要学习的东西,只要去哦懂得了学习的能力到老都可以学习,并且可以学习的很好。
这是肯定没有错的,但怎样提高自己的自学能力才是关键。
是思考吗?
那是肯定的,想想自己有没有想一个问题想过很久,没想很久就问别人,或者是上网查些资料,然后问题就差不多解决了。
我想以后对于相应的问题,如果不是很急需要解决的话,自己最好独自的解决。
不要总是依靠别人,如果在那样的话,我想自己大学毕业以后自学能力,学习能力没有任何的提高。
这点很重要的,特别是对于以后研究型的工作的话,这些能力不是很好的话,能就呆不下去了。
在这实习的一个月里,整天忙着自己的项目,当自己没有思路的时候,那是多么的煎熬,不过想出来了,那就没什么了。
也许,有句话说的没错:
“只要你去想的话,没有什么事是做不成的。
”这很有道理,想问题,思考问题那样的话才会有提高。
在写代码的时候遇到了一些问题,认为自己解决不了,但实际上还是解决了。
所以要相信自己,不要否认自己的能力,要敢于去想,而不要遇到一点问题就受不了。
所以在以后的学习中应该很是注意了,加油哦!
7.2软件总结
自由函数计算器这个项目有人说很简单,而实际对于接到这个项目的时候,自己是有点思路,但听说要用数据结构的知识,就不行了。
以前从来没真正看过数据结构,所以很是难办,因此在刚到公司的时候就抓紧练习链表的相关知识,练了一两天,差不多应该很是了解了,但怎样和项目对上关系呢?
想了想可以把表达式中的字符数字存放在链表当中,到运算的时候只要把链表删除掉即可。
想法很好,于是建立了两条链表一个是运算符链,一个是操作数链。
而后经过努力可以实现加减乘除的运算,一些三角函数,也能够计算,而后就是括号的问题,先处理了一个括号,而后是多个括号,但并没有嵌套的括号。
最后是处理嵌套了,但处理了嵌套的,就不能处理分离的括号了。
处理了很久,才模糊处理了三层嵌套,用了一个递归可能是占用的太多了。
想了很久,并且处理那些的时候,程序已经很复杂了,也不知道其究竟运行到哪个结点了。
看来自己不得不换另外一种方法了。
于是就考虑到了,堆栈,于是又花了几天时间学习堆栈,差不多了解以后,并且数据结构那本书上也有描述想类似的问题。
于是就开始编写了,几天以后查不多用可以了,加减乘除,多层嵌套括号,三角函数,等都可以了,并且具有一些拓展性。
一些小问题也在以后解决了。
但当要求能处理大数据的时候,自己已经无能下手了,而且此时差不多该写论文了,没办法,自己再想了想,可发现了很多问题,一改就需要改动整个程序,主要是定义堆栈结构的时候,定义了double类型的结构,如果定义了字符指针类型的话,那样就好解决了,只需要将大数据的运算函数写好,直接调用就好了,可是那样也很艰难,加法还容易些,乘法除法呢?
想出方法出来可能,但还要在程序中,改动很多的部分,于是只好不弄了。
在后来做了一个window界面,也是最后的结果了。
在这个项目中,深刻的体会到在做软件的时候一定要全局考虑,而不能想到哪写到哪,那样程序的拓展一点好处都没有。
可以说是垃圾了,以后在做项目的时候一定的考虑好,把思路理出来,要把接口留好,而不能只是看到一些结果,那样是没有用的。
以前认为在写程序的时候把整体思路想出来,没有必要。
但事实要是很有必要的。
所以以后写一些大程序前,一定的想好怎样写,而不能边写便想了,这次经历要记住了。
8.致谢
感谢广州致远电子公司对我们提供这么好的学习环境,让我们能够全身心去投入到学习当中。
在做项目的时候,感谢李志勤导师为我提供的帮助,她总是无微不致的关注着我们,每次总是问我们有没有问题,并且在学习上给了我们一些有用的建议,让我们要珍惜我们的大学时光,珍惜时间,做好事情。
其次感谢学校给我这次到广州实习的机会,让我提前知道自己以后该做什么。
在大学确实要学好东西,是思考与学习的能力。
感谢王老师为3+1班的付出,才会有机会学到很多。
9.参考文献
[1].谭浩强著,C程序设计(第三版).北京:
清华大学出版社,2005
[2].陈正冲著,C语言深度解剖,网络版
[3].严蔚敏等著,数据结构.北京:
清华大学出版社,2004
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 自由 函数 计算器