大整数计算实验报告.docx
《大整数计算实验报告.docx》由会员分享,可在线阅读,更多相关《大整数计算实验报告.docx(22页珍藏版)》请在冰豆网上搜索。
大整数计算实验报告
石家庄经济学院
实验报告
学院:
信息工程学院
专业:
计算机科学技术
1.计算机人论坛需求分析
1.1开发背景
在现实生活中不可避免地我们会遇到一些超大整数之间的运算,比如要计算马云的资产,以及国有银行的转账收入支出等一些数的存储等等类似的问题,而由于计算机整形数的最小值和最大值范围仅为-32768到32767,所以关于大整数的实验即呼之欲出,本实验就是针对数值很大、精度很高的大整数进行的加法减法以及乘法的计算。
数据需求
指针:
L1,L2:
分别为指向这两条存储要进行运算的链表头结点的指针;L3:
指向乘法的结果链表;L4:
在运算乘法的时候做中间量使用。
prior:
双向链表的头指针;next:
双向链表的尾指针。
data:
整形数,链表所存的数据。
功能需求
对一个进行运算的软件,加法和减法是最基本的运算,本实验又额外增加了大整数的乘法。
测试数据
第一个数:
9,568,974,512;
第二个数:
8,648,761,512;
2.概要设计
功能模块图
由需求分析可画出如下功能模块图。
图2-1功能模块图
各功能子程序定义
1.创建链表:
Statuscreat(DuLinkList&L,charstr[30]);
2.输出链表中结点内的数据:
Statusoutput(DuLinkListL);
3.加法:
DulNode*Add(DuLinkListL1,DuLinkListL2);
4.减法:
DulNode*Sub(DuLinkListL1,DuLinkListL2);
5.乘法:
DulNode*Mul(DuLinkListL1,DuLinkListL2);
计算机人论坛主界面截图
图2-3程序主界面
3.详细设计
数据结构设计
此款软件是基于线性表双向链表完成的,在每个分过程中都充分利用了链表指针灵活又不太易于掌控的特性,但若是全面理解指针以及链表的特点,也是很容易设计此款软件的。
在大整数加减乘法软件中主要有以下几种数据
(1)Status,ElemType都是宏定义的整形量;
(2)DulNode是结构体,包含三个域,data,prior,next,分别是整形数,左指针,右指针;
模块详细设计
由于加法和减法的操作易于实现,在此并不一一赘述。
乘法的实现:
(1)构思:
本函数又另设一个指针L3和L4,L3用于存储每一层的乘法结果,L4则每次都加上L3链表,直至结束,最后L4指向的链表即为乘法的结果。
(2)一级算法:
P1和p2分别指向L1和L2结点的下一个结点
遍历L1和L2,分别计算两链表的长度
若L2长于L1,则分别交换L1和L2,p1和p2。
新建结点L3和L4,p3和q分别指向L3指向的结点。
Do
{
计算L3链表
}
为L3加上头结点;把L3赋给L4;
P1重新置于L1尾部,p2前移一位;
Do
{
重新做一条L3链;
Do
{
计算L3链
}当p1->next为NULL
W指向L3链尾;
把L3加到L4上;
}当p2->prior为空
返回L4;
(3)二级求精:
L3->data=上一位的进位加上L1结点加上L2结点;
计算Prov;
新建L3->prior;
计算L3结点数据;
P1前移
计算机人论坛测试与运行
本程序是用C语言在VisualC++环境编译所完成,经部分数据验证无误,现将测试与运行结果展示如下:
(1)加法:
图3-3-1加法
(2)减法和乘法:
图3-3-2减法和乘法
(3)输入:
图3-3-3输入
4.计算机人论坛总结与展望
《数据结构》果然不是闹着玩的,要想学好,必须得下苦功夫!
!
!
5.参考文献
[1].严蔚敏.数据结构[M].北京:
清华大学出版社,2013。
6.计算机人论坛源代码清单
#include<>
#include<>
#include""
Statusinput(LinkList&p)
{
LinkListhead,s;
intv;
inttamp;
tamp=0;
head=(LinkList)malloc(sizeof(LNode));
p=head;
while(tamp==0)/*创建n个元素的双向链表*/
{
scanf("%d",&v);/*束三个三个输入*/
if(v>=0)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=v;/*赋值*/
p->next=s;/*连接*/
s->prior=p;
p=s;
}
else
tamp=1;/*为负数时结束*/
}
head=head->next;/*去掉头节点*/
head->prior=NULL;/*让双向链表前后都为空*/
p->next=NULL;
returnOK;
}
Statusoutput(LinkList&p,LinkList&head)/*输出*/
{
LinkLists;
s=head;
while(s!
=NULL)
{
if(s->data>=100)printf("%d",&s->data);
if(s->data>=10&&s->data<100)printf("0%d",&s->data);
if(s->data>0&&s->data<10)printf("00%d",&s->data);
s=s->next;
}
returnOK;
}
Statusmax_add(LinkList&head1,LinkList&head2,LinkList&p1,LinkList&p2)/*链表加法*/
{
LinkListp,q;
intn=0,m=0;
p=head1;
q=head2;
while(p!
=NULL)/*遍历链表然后记录链表长度*/
{
n=n+1;
p=p->next;
}
while(q!
=NULL)/*遍历链表然后记录链表长度*/
{
m=m+1;
q=q->next;
}
p=p->prior;
q=q->prior;
if(n>=m)/*当head1大于head2时*/
{
while(q!
=NULL)
{
p->data=p->data+q->data;/*两个链表相加直到其中一个走完或者全都走完结束*/
if(p->data>=1000)
{
p->prior->data=p->prior->data+1;
p->data=p->data%1000;
}
p=p->prior;
q=q->prior;
}
while(p!
=NULL)/*当出现进位但是前面却为空时需要申请一个空间然后放进去进的位数*/
{
if(p->data>=1000)
{
if(p->prior==NULL)
{
q=(LinkList)malloc(sizeof(LNode));
q->data=1;
p->prior=q;
q->next=p;
q->prior=NULL;
p=NULL;
}
else
{
p->prior->data=p->prior->data+1;
p->data=p->data%1000;
p=p->prior;
}
}
}
output(head1,p1);
}
if(n{
while(p!
=NULL)
{
q->data=q->data+p->data;
if(q->data>=1000)
{
q->prior->data=q->prior->data+1;
q->data=q->data%1000;
}
p=p->prior;
q=q->prior;
}
while(q!
=NULL)
{
if(q->data>=1000)
{
if(q->prior==NULL)
{
p=(LinkList)malloc(sizeof(LNode));
p->data=1;
q->prior=q;
p->next=p;
p->prior=NULL;
q=NULL;
}
else
{
q->prior->data=q->prior->data+1;
计算机人论坛q->data=q->data%1000;
q=q->prior;
}
}
}
output(head2,p2);
}
returnOK;
}
Statusmax_sub(LinkList&head1,LinkList&head2,LinkList&p1,LinkList&p2)/*链表减法*/
{
LinkListp,q;
intn=0,m=0;
p=head1;
q=head2;
while(p!
=NULL)/*遍历链表然后记录链表长度*/
{
n=n+1;
p=p->next;
}
while(q!
=NULL)/*遍历链表然后记录链表长度*/
{
m=m+1;
q=q->next;
}
p=p->prior;
q=q->prior;
if(n>=m)/*当head1大于head2时*/
{
while(q!
=NULL)
{
p->data=p->data-q->data;/*两个链表相加直到其中一个走完或者全都走完结束*/
if(p->data<0)
{
p->prior->data=p->prior->data-1;
p->data=p->data+1000;
}
p=p->prior;
q=q->prior;
}
output(head1,p1);
}
if(n{
while(p!
=NULL)
{
q->data=q->data-p->data;
if(q->data<0)
{
q->prior->data=q->prior->data-1;
q->data=q->data+1000;
}
p=p->prior;
q=q->prior;
}
output(head2,p2);
}
returnOK;
}
Statusmax_mul(LinkList&head1,LinkList&head2,LinkList&p1,LinkList&p2,LinkList&L)/*链表乘法*/
{
LinkLists;
LinkListb,d;
LinkListp,q;
LinkListh1,h2,tail1,tail2;
intn=0,m=0;
inti;
LinkListr,tail,tailr;
ElemTypemo,di,re,edi;
intc,flag;
p=head1;
q=head2;
while(p!
=NULL)/*遍历链表然后记录链表长度*/
{
n=n+1;
p=p->next;
}
while(q!
=NULL)/*遍历链表然后记录链表长度*/
{
m=m+1;
q=q->next;
}
h1=(LinkList)malloc(sizeof(LNode));/*要装拆分第一个双向链表后的链表*/
tail1=h1;
h1->prior=NULL;
i=0;
while(i<(3*n))
{
p=(LinkList)malloc(sizeof(LNode));
p=tail1->next;
tail1=p->prior;
tail1=p;
i=i+1;
}
tail1->next=NULL;
h2=(LinkList)malloc(sizeof(LNode));/*要装拆分第二个双向链表后的链表*/
tail2=h2;
h2->prior=NULL;
i=0;
while(i<(3*m))
{
q=(LinkList)malloc(sizeof(LNode));
q=tail2->next;
tail2=q->prior;
tail2=q;
i=i+1;
}
tail2->next=NULL;
s=head1;
b=h1->next;
while(s!
=NULL)
{
b->data=s->data/100;/*拆分head1链表然后放进刚刚建立好的h1双向链表中*/
b=b->next;
b->data=s->data/10%10;
b=b->next;
b->data=s->data%10;
b=b->next;
s=s->next;
}
s=head2;
d=h2->next;
while(s!
=NULL)
{
d->data=s->data/100;/*拆分head2链表然后放进刚刚建立好的h2双向链表中*/
d=d->next;
d->data=s->data/10%10;
d=d->next;
d->data=s->data%10;
d=d->next;
s=s->next;
}
/*要做pq两个链表相乘要考虑进位还有将所得结果放到哪个链表中等问题*/
L=(LinkList)malloc(sizeof(LNode));/*用L来装乘完后的数据*/
if(!
L)
exit(OVERFLOW);
L->next=NULL;
L->prior=NULL;
di=0;
edi=0;
tail=p;
while(p!
=NULL){
re=p->data*q->data;
mo=re%10;
if(L->prior==NULL){
r=L;
r->data=mo+di;
if(r->data>=10){
edi=r->data/10;
r->data=r->data%10;
}
else{
edi=0;
}
L->prior=L;
}
else{
r=(LinkList)malloc(sizeof(LNode));
r->data=mo+di;
if(r->data>=10){
edi=r->data/10;
r->data=r->data%10;
}
else{
edi=0;
}
L->prior=r;
r->next=L;
L=r;
}
di=edi+re/10;
edi=0;
p=p->prior;
}
while(di>0){
r=(LinkList)malloc(sizeof(LNode));
r->data=di%10;
di=di/10;
L->prior=r;
r->next=L;
L=r;
L->prior=NULL;
}
L->prior=NULL;
while(r->next!
=NULL)r=r->next;
tailr=r;
c=1;
q=q->prior;
while(q!
=NULL){
p=tail;
r=tailr;
flag=0;
di=0;
edi=0;
for(i=1;i<=c;i++){
if(r->prior!
=NULL)r=r->prior;
else{
r=(LinkList)malloc(sizeof(LNode));
r->data=0;
L->prior=r;
r->next=L;
L=r;
L->prior=NULL;
flag=1;
}
}
while(p!
=NULL){
re=p->data*q->data;
mo=re%10;
if(flag==0)r->data=r->data+mo+di;
elser->data=mo+di;
if(r->data>=10){
edi=r->data/10;
r->data=r->data%10;
}
di=edi+re/10;
edi=0;
p=p->prior;
if(r->prior!
=NULL)r=r->prior;
else{
r=(LinkList)malloc(sizeof(LNode));
r->data=0;
L->prior=r;
r->next=L;
L=r;
L->prior=NULL;
flag=1;
}
}
if(di>0){
r->data=di%10;
di=di/10;
}
q=q->prior;
c++;
}
returnOK;
}
Statusmain()
{
intchoose,i;
LinkListhead1,head2,p1,p2,L;
choose=0;
while(choose==0)
{
printf("1输入大整数\n");
printf("2输出大整数\n");
printf("3大整数之和\n");
printf("4大整数之差\n");
printf("5大整数之机\n");
printf("6退出\n");
scanf("%d",&choose);
switch(choose)
{
case1:
printf("请输入第一个大整数以负数代表结束\n");
input(head1);
printf("请输入第二个大整数以负数代表结束\n");
input(head2);
break;
case2:
printf("第一个大整数为\n");output(head1,p1);
printf("第二个大整数为\n");output(head2,p2);
break;
case3:
printf("两个大整数相加后结果为\n");
max_add(head1,head2,p1,p2);
break;
case4:
printf("两个大整数相减后结果为\n");
max_sub(head1,head2,p1,p2);
break;
case5:
printf("两个大整数相乘后结果为\n");
max_mul(head1,head2,p1,p2,L);
break;
case6:
choose=1;
break;
}
}
return(0);
}
计算机人论坛