数据结构课程设计报告长整数运算.doc

上传人:laozhun 文档编号:2389048 上传时间:2023-02-17 格式:DOC 页数:13 大小:134KB
返回 下载 相关 举报
数据结构课程设计报告长整数运算.doc_第1页
第1页 / 共13页
数据结构课程设计报告长整数运算.doc_第2页
第2页 / 共13页
数据结构课程设计报告长整数运算.doc_第3页
第3页 / 共13页
数据结构课程设计报告长整数运算.doc_第4页
第4页 / 共13页
数据结构课程设计报告长整数运算.doc_第5页
第5页 / 共13页
点击查看更多>>
资源描述

《数据结构课程设计报告长整数运算.doc》由会员分享,可在线阅读,更多相关《数据结构课程设计报告长整数运算.doc(13页珍藏版)》请在三一办公上搜索。

1、数据结构课程设计报告题目:长整数四则运算一、需求分析1.问题描述:由于工程上有时候需要对很大的数进行计算,但是计算机本身提供的数据类型无法保存几百位甚至几千位的数字,所以需要设计专门的算法对数据进行相应的计算。此程序的设计任务是:设计一个程序能够实现长整数运算的程序,而且能够对一些错误异常进行辨别调整,计算出正确的结果。程序输入格式是字符串,保存时需要用双向循环链表将字符串每四位保存在循环链表中的一个节点中,然后再计算后运行出结果。 2.基本功能 功能一:建立双向循环链表,计算链表个数,对链表的数据进行修改,能在链表中插入结点。功能二:将字符串转换成相应的数字存储在双向循环链表中功能三:对存入

2、双向循环链表的长整数进行相加,相减,相除。 3.输入输出程序输入以字符串的形式输入,数据的类型是字符串,包含元素的范围是数字,逗号,负号。输入时用字符串输入,输出时以一链表结点输出,而且每个结点表示四位。二、概要设计1.设计思路:由于计算机无法完成位数很大的数字计算,设计思路就是将很长的数据进行分割,一部分一部分的用计算机固有数据类型进行计算。将各部分的结果整合起来。由于计算机固有的整数类型存数的对大整数是215-1,所以为了方便,且符合中国人对长整数的表示习惯,建立一个双向循环链表,每个结点存储四位数字,以万为进制。从最低位开始加法,超过一万向上进位,所以每次加法应该是对应两个结点和进位数相

3、加,进位值初始为0;减法也是一个结点计算一次,每次计算应该是第一个链表对应的结点值减去第二个结点的值和借位值的和,借位值初始值为0;除法的计算可以借助减法,被减数被减数减一次则最终结果加一;直至被减数比减数小。 2.数据结构设计:因为计算的是一个连续的数字,需要桉顺序一次计算,所以采用的数据结构的逻辑结构是线性表。因为要求每一个结点只存储四位数字,为了将数字连接起来,采用的数据结构的存储结构是链式。1双向循环链表的抽象数据类型定义为:ADT Link数据对象:D=ai | aiCharSet,i=1,2,n,n0数据关系; R= | ai-1,aiD,i=2,n基本操作:InitLinkLis

4、t(&L,a) 操作结果:构造一个双向循环链表L ,用a判断是正数还是负数 DestroyList(&L) 初始条件:双向循环两已经存在操作结果:销毁有序表LInsert(&L,a)初始条件:双向循环链表已经存在操作结果:在循环链表的末尾插入一个结点,且此结点的数据值为aHeadInsert(&L,a)初始条件:双向循环链表已经存在操作结果:在循环链表的头结点后插入一个结点,且此结点的数据值为aCountNode(&L)初始条件:双向循环链表存在操作结果:计算出链表中结点的个数,并返回个数Compare(&L1, &L2)初始条件:L1和L2存在操作结果:比较两个双向循环链表的大小,用返回值1

5、表示L1大于L2,返回值-1标志L1小于L2,返回值0标志L1和L2相等ToNum(*s,i,&e) 初始条件:s为字符串中指向某个字符的指针操作结果:将s的前i个字符转换为数字,存入e中CreatNum(&L,&s)初始条件:s为某个字符串,双向循环链表L存在操作结果:将字符串s转换成数字存入到循环链表L中Add(L1,L2, op) 初始条件:双向循环链表L1和L2存在,op为结果的标识符操作结果:两个链表相加,求出结果。Sub(L1,L2, op) 初始条件:双向循环链表L1和L2存在操作结果:L1减去L2,求出结果 ,op为结果的标识符EraseZero(Link &L)初始条件:双向

6、循环链表L存在操作结果:删去L链表头结点后,第一个数据不为零结点前的所有数据为零的结点。如果结点数据都为零,则保存一个结点。print(L)初始条件:双向循环链表L存在操作结果:从L头结点开始顺此打印每个结点中的数据3.软件结构设计:本程序包含四个模块:1.主程序模块Int main()接受命令While(“命令”!=“退出”)输入字符串建立双向循环链表将字符串转换为要求的格式存入链表的每个结点对链表中数据进行即兴操作数理再次接受命令2.双向链表操作模块-实现结点的插入、删除、修改3.字符串转换存储模块-实现将字符串转换为数字按格式存储在链表中4.数据计算模块-对存储在链表中的数据进行计算,得

7、到最终期望的结果各个模块调用的关系如下: 主程序模块数据运算模块双向链表操作模块字符串转换模块主程序模块中的函数原型:void Interface()-操作界面函数Status CreatNum(Link &L,char*s)-创建数字链表函数Link Compute(Link &L1,Link &L2,char Ope)-数据计算函数数据运算模块:Link Add(Link &L1,Link &L2,char op) -加法计算Link Sub(Link &L1,Link &L2,char op) -减法运算双向链表操作模块void InitLinkList(Link &L,char a)S

8、tatus DestroyList(Link &L)Status Insert(Link &L,Elemtype a)int CountNode(Link L)BOOL Compare(Link &L1,Link &L2)void EraseZero(Link &L)Status HeadInsert(Link &L,Elemtype a) 字符串转换模块Status CreatNum(Link &L,char*s)Status ToNum(char*s,int i,long &e)人机界面:三、 详细设计 1.根据分析和链表操作的特点,采用双向循环链表实现,这里头结点存储数字的符号。type

9、def long Elemtype ;typedef int Status;typedef int BOOL;typedef struct LNodeElemtype data;LNode *next;LNode *prior;Node,*Link;void InitLinkList(Link &L,char a)/对一个双向循环链表进行初始化,分配头结点L = (Link)malloc(sizeof(Node);/动态分配存储空间 If(!L) return FALSE;if(a = -) L-data = -1;/L-data存放符号节点,如果是-则为,否则为0else L-data =

10、1;L-prior = L;L-next = L;Status DestroyList(Link &L)/销毁链表Lif(!L)return ERROR;/链表不存在p = L-prior;/p指向链表头节点的前驱while(p!=L)/删除节点节点pq = p-prior;free(p);/释放节点p的空间p = q;free(L);/释放链表L的存储空间return OK;Status Insert(Link &L,Elemtype a)/分配一个结点,并将其数据值存为a,插入到链表的末尾p=(Link)malloc(sizeof(LNode);if(!p)exit(OVERFLOW);p

11、-next=p-prior=NULL;p-data=a;Link q=L-prior;q-next=p;p-prior=q;p-next=L;L-prior=p;return OK;Status HeadInsert(Link &L,Elemtype a) /分配一个结点,并将其数据值存为a,按头插入法插入p=(Link)malloc(sizeof(LNode);if(!p)exit(OVERFLOW);p-data=a; Link q=L-next;q-prior=p;p-next=q;L-next=p;p-prior=L;return OK;Status ToNum(char*s,int

12、i,long &e)/将字符串s的前i位转换为正数,并由e保存sum=0;for(m=1,n=1;mnext;while(p!=L)i+;p=p-next;return i;BOOL Compare(Link &L1,Link &L2)/比较链表L1和L2的大小,如果L1大于L2,返回1,如果L2大于L1,返回-1,如果相等,返回0if(CountNode(L1)CountNode(L2) / L1大于L2else if(CountNode(L1)next,p2=L2-next;while(p1!=L1&p2!=L2)if(p1-datap2-data) / L1大于L2if(p1-datad

13、ata)return -1;p1=p1-next;p2=p2-next;L1和L2相等Link Add(Link &L1,Link &L2,char op) 主要函数/将字符串L1和L2的数据相加,得到的结果链表头结点指针返回Int c=0,tempLink p1,p2,p3p1=p1-prior,p2=p2-priorInitLinkList(L3)p1!=L1&p2!=L2Temp=p1-data+p2-data+c是否temp=10000是否temp=temp-10000HeadInsert(L3,temp)c=0HeadInsert(L3,temp) c=1P1=p1-prior p2

14、=p2-priorp1!=L1temp=p1-data+c c=temp/10000是否temp=10000是否temp=temp-10000HeadInsert(L3,temp)HeadInsert(L3,temp)p1=p1-priorp2!=L2temp=p2-data+c c=temp/10000是否temp=10000是否temp=temp-10000HeadInsert(L3,temp)HeadInsert(L3,temp)p2=p2-prior是否c=1是否HeadInsert(L3,c)Link Sub(Link L1,Link L2,char op) 主要函数/将字符串L1和

15、L2的数据相减,得到的结果链表的头结点指针返回Int c=0,tempLink p1,p2,p3p1=p1-prior,p2=p2-priorInitLinkList(L3)p1!=L1&p2!=L2Temp=p1-data-p2-data-c是否tempprior p2=p2-priorp1!=L1temp=p1-data-c 是否temppriorp2!=L2temp=p2-data-c是否temp=10000是否temp=temp+10000 c=1HeadInsert(L3,temp)c=0HeadInsert(L3,temp) p2=p2-prior是 否 c=1是否HeadInse

16、rt(L3,c)void EraseZero(Link &L)/删除链表L的无效零元素结点 p=L-next,q;while(p-data=0&p-next!=L)q=p;p=p-next;p-prior=q-prior;free(q);L-next=p;Link Compute(Link &L1,Link &L2,char Ope) /主要函数/对链表L1和链表L2进行计算,即相加,相减等等EraseZero(L1) EraseZero(L2) p1=L1-prior p2=L2-prior;op=+L1-data=1&L2-data=1 L3=Add(L1,L2,+) L1-data=-1

17、&L2-data=1 是否L1和L2相等是 否L3=Sub(L1,L2,+)是否L1大于L2是否L3=Sub(L1,L2,-)L3=Sub(L2,L1,-)L1-data=1&L2-data=-1是否L1和L2相等是否L3=Sub(L1,L2,+)是否L1大于L2是否L3=Sub(L1,L2,+)L3=Sub(L2,L1,-)L1-data=-11&L2-data=-1L3=Add(L1,L2,-)op=-L1-data=1&L2-data=1是否L1大于L2是否L3=Sub(L1,L2,+)L3=Sub(L2,L1,-)L1-data=1&L2-data=-1L3=Add(L1,L2,+);

18、L1-data=-1&L2-data=1L3=Add(L1,L2,-);L1-data=-1&L2-data=-1是否L1大于L2是否L3=Sub(L1,L2,-)L3=Sub(L2,L1,+)void Interface() /界面函数,显示操作的主界面Status print(Link L)/顺次打印链表L中的数据EraseZero(L);if(*s57) /第一个不是数字也不是-,则出错return ERROR;if(*s=-) k=0;else k=1;i=1;while(*(s+i)!=0)if(*(s+i)!=,&(*(s+i)57|*(s+i)5)return ERROR;if(

19、*(s+i)=0)return OK;k=4;while(*(s+i)!=0)if(*(s+i)=,)if(k!=4)return ERROR;k=-1; /此时逗号字符不能在四个数字的计算之中k+;i+;if(k!=4) /最后一个逗号后必须有四个数return ERROR;return OK;函数调用关系图: mainInterfaceInputJudegCreatNumComputeprintDestroyListInsertTonumeraseZeroAddCompareSubCountnodeHeadInsert四、 调试分析 1.实际完成的功能有:长整数的加法和减法,支持的数据类型

20、是整形,能够对异常输入进行判断,打印和计算的时候能够消除可能出现的前置零。2.程序的主要函数compute时间复杂度为O(n),其实n为计算的两个链表的结点个数的较大值。物理存储使用的是双向链表,有两个指针域,空间消耗在合理范围之内3.调试中由于是双向链表,在插入时应该注意将prior域进行考虑,刚开始写程序时忘记,导致输出结果错误。清楚前置零的时候开始没有考虑输入数据全是零的时候,结果将全部的数据结点都给删除,最后没有结果输出,调试中发现这个问题,应该将每个链表至少保存一个数据结点。4.由于时间仓促,而且长整数四则运算的乘法一直没有想到好的办法,如果再有几天时间,乘法这个功能完全可以加上。随

21、之就可以完成乘方的计算5.本程序还有很大的扩充地方,应该可以将程序由正数扩充为浮点数,能够运行更复杂的数据,如求阶乘,开方等功能。如果实现了,则这个计算器的功能方面就可以和windows系统自带的计算器媲美了。五、测试结果列出你的测试结果,包括输入和输出。注意测试数据应该完整和严格,至少给出2组测试结果(含合法数据与非法数据)。输入0;0,输出0输入1,0001,0001;-1,0001,0001;输出0输入1,0001,0001;-1,0001,0000;输出1输入-9999,9999;-9999;9999;输出-1,9999,9998非法数据1,000;000,1;输出“输入错误”六、用户

22、手册说明如何使用你编写的程序,详细列出每一步的具体操作步骤。这里可以有适当的运行结果抓图。用户手册与开发过程无关,只与使用有关,必须是Step by Step的。 所有运行结果截图均要求有实际数据的内容,截图尺寸要求按页宽排版两张大小,且要求有每张图下面有规范的标题说明如何使用你编写的程序,详细列出每一步的操作步骤。1.进入操作主界面2按照命令提示操作选1,进入加法运算输入第一个操作数:并且按照提示格式输入如果输入错误,比如1,000,则程序会提示错误,重新输入如果输入正确,比如输入1,0000,输入下一个数输入正确,如输入9999,9999 则计算出结果输出每个链表中的结点值,便于观察比较输

23、出结果1,0000,9999选2,进入减法运算输入第一个操作数,并按照提示的格式输入如果输入错误,比如,10,000,程序会提示输入错误,重新输入如果输入正确,比如9999,9999,输入下一个数。第二个数也输入正确,比如输入10,0000,输出结果提示是否继续计算,选择Y或者y退出,其他任意键继续操作七、体会与自我评价 长整数四则运算的一些思考这次的课程设计中,长整数四则运算这个实验给了我很大的挑战,在设计中遇到了很多的困难,比如如何用如何将字符数据分割成很多部分存储进双向循环链表,如何判断输入的字符串是否是正确的;在输入特殊数据买比如0000,00000时,程序能够消除无用的前置零得出正确

24、的结果,我在这些问题上都考虑的很久,一点点的攻破难题,而在这次实验中我对长正数的各种运算也有了一定的认识,对于特别长的数的计算,只能先求局部结果,最后将局部结果综合起来,得到最终结果。比如加法就是从最低位开始计算,判断进位后再一次向高位计算,最终得到结果。计算加法的时候,由于是每四位一个结点,所以是以万位为进制。输出时如果一个结点中数据是以为,则前面输出三个零,如果是两位,则输出两个零,如果是三位,则输出一个零,四位数直接输出。如果节点数据为零,则按第一种情况输出是前面加三个零即可。为了程序的健壮性,应该考虑负数和正数相加的情况,如果一个较大的正数加上一个数值较小的负数,应该是大数减去去掉振幅符号的小数,即可。如果是一个较小的正数加上一个数值较大的负数,则应该是去掉正负号的负数减去正数,最后在结果里加上一个负号即可。乘法的基本思想是相加,但是在双向循环链表中,如果乘数很大的时候,单纯的相加要进行很多次,效率上完全不够满足要求,一般是用字符串直接按位相乘,按竖式结构计算。除法的实现可以用减法,但是问题还是和乘法一样,如果数字太大的话,用双向循环链表,要进行的减法次数也是很庞大的。以上是我对长整数四则运算的一点思考,本次实验中学到的很多的知识,对循环链表的操作也更加的熟悉,更让我增长了许多的编程经验,我相信以后的编程学习中我会表现的更加出色。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号