大整数计算器.docx
《大整数计算器.docx》由会员分享,可在线阅读,更多相关《大整数计算器.docx(32页珍藏版)》请在冰豆网上搜索。
![大整数计算器.docx](https://file1.bdocx.com/fileroot1/2023-1/27/b44d3647-087e-4327-aeb4-6c349aed25bd/b44d3647-087e-4327-aeb4-6c349aed25bd1.gif)
大整数计算器
目录
一.问题的概述、分析及研究意义;
二.流程图
三.算法设计
四.调试过程
五.源程序
一.问题的概述、分析及研究意义;
设计一个计算器实现两个任意长得整数的加、减、乘、除。
对数值很大,精度很高的数进行高精度大整数计算是一类十分常见的问题,但由于C语言中数据长度和范围受数据类型的限制,普通数学计算很难实现此问题,为尝试解决这个问题,专门设计一个C语言程序用于大整数的计算。
为了实现上述功能,采取双向循环链表表示长整数,每个结点含一个整型变量,仅绝对值不超过9999的整数,整个链表用十进制数表示。
利用头结点数据域的符号表示长整数的符号,相加过程不破坏两个操作数链表,对长整数位数不作上限。
为此需要两个结构数据类型:
双向循环链表和长整数。
本程序实现计算任意长的整数的四则运算.以用户和计算机对话的方式,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令,然后程序就计算并显示出这两个数的运算。
本演示程序中,数字字符限定为[‘0’~‘9’]和字符‘,’,输入字符可以任意长,输入形式以“回车符”为结束标志,串中字符顺序不限,且允许出现重复字符。
利用双向循环链表现实长整数的存储,每个结点含一个整形变量。
输入的形式以回车结束,可以直接输入正数或负数,每四位一组,除数字和位于首位置的负号外,其它一切字符都将作为分隔符,连续多个分隔符当一个处理,但不使用分隔符也不影响结果。
二.流程图
三.算法设计
1.定义全局变量
#defineLENsizeof(structNode)
#defineMAX1000
#defineOK1
#defineERROR0
#defineOVERFLOW-1
#defineTRUE1
#defineFALSE0
typedefintStatus;
2,主要函数
(1)主程序模块:
//intmain()
(2)双向循环链表处理模块:
//Statusconversion(charstr[],NodeList&oprh);
//intcmplinklen(NodeListopr1,NodeListopr2);
//StatusCreat(NodeList&oprr,intlen);
//intcompare(NodeListopr1,NodeListopr2);
(3)长整数四则运算模块:
//Statusadd_bas(NodeListopr1,NodeListopr2,NodeList&oprr);
//Statussub_bas(NodeListopr1,NodeListopr2,NodeList&oprr);
//Statusimul(NodeListopr1,NodeListopr2,NodeList&oprr);
//Statusidiv(NodeListopr1,NodeListopr2,NodeList&quti,NodeList&remand);
(4)界面模块:
//voidtitle();
//voidwelcome();
3,编写函数
(1)函数:
Statusconversion(charstr[],NodeList&oprh)
功能:
将字符串形式的操作数转换成所需的类型
(2)函数:
Statusinput(NodeList&opr1,NodeList&opr2,charstr[])
功能:
输入需要的操作数
(3)函数:
Statusoutput(NodeListoprr,charstr[])
功能:
输出需要的操作数以及判断其正确性
(4)函数:
Statusinitbuf(charstr[])
功能:
为数据对象或变量赋初值
(5)函数:
intcmplinklen(NodeListopr1,NodeListopr2)
功能:
比较两个输入数的大小,长返回1,短返回-1,否则返回0
(6)函数:
intlength(NodeListoprr)
功能:
求出链表长度
(7)函数:
StatusCreat(NodeList&oprr,intlen)
功能:
生成一个指定链表
(8)函数:
intcompare(NodeListopr1,NodeListopr2)
功能:
比较两个数的绝对值的大小
(9)函数:
Statusadd_bas(NodeListopr1,NodeListopr2,NodeList&oprr)
功能:
实现两个数相加
(10)函数:
Statussub_bas(NodeListopr1,NodeListopr2,NodeList&oprr)
功能:
实现两个数的相减
(11)函数:
Statusimul(NodeListopr1,NodeListopr2,NodeList&oprr)
功能:
实现两个数的相乘
(12)函数:
Statusidiv(NodeListopr1,NodeListopr2,NodeList&quti,NodeList&remand)
功能:
实现两个数的除法
四.调试过程
运行平台:
MicrosoftVisualC++6.0
1,欢迎界面
2,选择操作
3,加法运算
4,减法运算
5,乘法运算
6,除法运算
8,结束运行
五.源程序
#include
#include
#include
#defineLENsizeof(structNode)
#defineMAX1000
#defineOK1
#defineERROR0
#defineOVERFLOW-1
#defineTRUE1
#defineFALSE0
typedefintStatus;//自定义一个变量
typedefstructNode
{
intdata;
structNode*prior,*next;
}Node,*NodeList;//定义双向循环链表结构体
//===============输入模块===============
//求指数函数值
intaxp(inta,intk)
{
intr=1;
if(k==0)
return1;
for(;k>0;k--)
r=r*a;
returnr;
}
//输入转换函数
Statusconversion(charstr[],NodeList&oprh)
{//将字符串形式的操作数转换成所需的类型
NodeListp;
inti,k,buffer;
k=buffer=0;
oprh=(NodeList)malloc(LEN);
oprh->next=oprh;
oprh->prior=oprh;
for(i=strlen(str)-1;i>=0;i--)
{//若输入的数不合法就返回重新输入
if((i!
=0||(str[0]!
='-'&&str[0]!
='+'))&&(str[i]>'9'||str[i]<'0'))
returnERROR;
if(str[0]=='0'&&str[1]!
='\0')
returnERROR;
if((str[0]=='-'||str[0]=='+')&&str[1]=='0')
returnERROR;
if(str[i]!
='-'&&str[i]!
='+')
{
buffer=buffer+(str[i]-'0')*axp(10,k);
k++;
if(k==4||str[i-1]=='-'||str[i-1]=='+'||i==0)
{//将新建结点插入到头结点之后
p=(NodeList)malloc(LEN);
oprh->next->prior=p;
p->prior=oprh;
p->next=oprh->next;
oprh->next=p;
p->data=buffer;
buffer=k=0;
}
}
}
if(str[0]=='-')
oprh->data='-';
else
oprh->data='+';
returnOK;
}
//输入函数
Statusinput(NodeList&opr1,NodeList&opr2,charstr[])
{
intflag=OK,i,n=0,l;
charb[MAX];
printf("\n请输入第一个操作数:
\n");
scanf("%s",b);
getchar();
l=strlen(b);
for(i=0;iif(b[i]!
=',')
str[n++]=b[i];
str[n]='\0';
flag=conversion(str,opr1);
while(!
flag)
{
printf("ERROR!
Inputagain:
\n");
scanf("%s",str);
getchar();
flag=conversion(str,opr1);
}
printf("\n请输入第二个操作数:
\n");
scanf("%s",b);
getchar();
n=0;
l=strlen(b);
for(i=0;iif(b[i]!
=',')
str[n++]=b[i];
str[n]='\0';
flag=conversion(str,opr2);
while(!
flag)
{
printf("ERROR!
Inputagain:
\n");
scanf("%s",str);
getchar();
flag=conversion(str,opr2);
}
returnOK;
}
//==================输出模块======================
//输出函数
Statusoutput(NodeListoprr,charstr[])
{
Statusinitbuf(charstr[]);
NodeListp;
inti,j,num[4];
if(!
oprr)
returnERROR;
p=oprr;
i=j=0;
initbuf(str);
if(oprr->data=='-')
str[i++]='-';
p=p->next;
if(p->next==oprr&&p->data==0)//若要输出的数为0则执行
str[i++]='0';
else
while(p!
=oprr)
{
num[0]=p->data/1000;
num[1]=(p->data-num[0]*1000)/100;
num[2]=(p->data-num[0]*1000-num[1]*100)/10;
num[3]=p->data-num[0]*1000-num[1]*100-num[2]*10;
while(j<4)
{
if(num[j]!
=0||(str[0]=='-'&&str[1]!
='\0')||(str[0]!
='-'&&str[0]!
='\0'))
//此判断语句是为了避免输出诸如:
00123…的情况
str[i++]=num[j]+'0';
j++;
}
p=p->next;
j=0;
str[i++]=',';
}
if(str[--i]==',')
str[i]='\0';
printf("%s",str);
printf("\n");
returnOK;
}
//================预处理及杂项操作模块====================
//缓冲区部分初始化函数
Statusinitbuf(charstr[])
{
inti;
for(i=0;i<=10;i++)
str[i]='\0';
returnOK;
}
//比较链表长度函数
intcmplinklen(NodeListopr1,NodeListopr2)
{//opr1链比opr2链长则返回1,短则返回-1,否则返回0
NodeListp1,p2;
p1=opr1->prior;
p2=opr2->prior;
while(p1->prior!
=opr1&&p2->prior!
=opr2)
{
p1=p1->prior;
p2=p2->prior;
}
if(p1->prior!
=opr1)
return1;
if(p2->prior!
=opr2)
return-1;
return0;
}
//求链表长度
intlength(NodeListoprr)
{
intcount=0;
NodeListp=oprr->next;
while(p!
=oprr)
{
count++;
p=p->next;
}
returncount;
}
//生成指定长度链表
StatusCreat(NodeList&oprr,intlen)
{
NodeListp;
oprr=(NodeList)malloc(LEN);
p=oprr;
while(len>0)
{
p->next=(NodeList)malloc(LEN);
p->next->data='?
';
p->next->prior=p;
p=p->next;
len--;
}
p->next=oprr;
oprr->prior=p;
returnOK;
}
//比较opr1、opr2绝对值的大小
intcompare(NodeListopr1,NodeListopr2)
{
NodeListp1,p2;
p1=opr1->next;
p2=opr2->next;
if(cmplinklen(opr1,opr2)==1)//opr1比较长
return1;
elseif(cmplinklen(opr1,opr2)==-1)//opr2比较长
return-1;
else
{
while(p1->data==p2->data&&p1->next!
=opr1)//注意p1->next!
=opr1这条件
{
p1=p1->next;
p2=p2->next;
}
if(p1->data>p2->data)
return1;
elseif(p1->datadata)
return-1;
else
return0;
}
}
//=====================加减法模块==========================
//加法基本操作
Statusadd_bas(NodeListopr1,NodeListopr2,NodeList&oprr)
{//本算法实现A,B相加的操作。
intCF,buffer;
NodeListp1,p2,p3;
oprr=(NodeList)malloc(LEN);
oprr->next=oprr;
oprr->prior=oprr;
p1=opr1->prior;
p2=opr2->prior;
CF=buffer=0;
while(p1!
=opr1&&p2!
=opr2)
{
buffer=p1->data+p2->data+CF;
CF=buffer/10000;//若buffer的值大于9999则产生进位,赋给CF
//将新建结点插入到头结点之后
p3=(NodeList)malloc(LEN);
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=buffer%10000;//应该将buffer的第四位赋给p3->data
p1=p1->prior;
p2=p2->prior;
}
while(p1!
=opr1)
{//处理opr1链的剩余部分
buffer=p1->data+CF;
CF=buffer/10000;
p3=(NodeList)malloc(LEN);//将新建结点插入到头结点之后
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=buffer%10000;
p1=p1->prior;
}
while(p2!
=opr2)
{//处理opr2链的剩余部分
buffer=p2->data+CF;
CF=buffer/10000;
p3=(NodeList)malloc(LEN);//将新建结点插入到头结点之后
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=buffer%10000;
p2=p2->prior;
}
if(CF)
{
p3=(NodeList)malloc(LEN);
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=CF;
}
oprr->data='+';
returnOK;
}
//减法基本操作
Statussub_bas(NodeListopr1,NodeListopr2,NodeList&oprr)
{//本算法实现A,B相减的操作。
//将A链分成与B链长相等的底位部分,和剩余的高位部分,并做相应处理。
intCF,buffer,flag;
NodeListp1,p2,p3,qh,qt,qq;
oprr=(NodeList)malloc(LEN);
oprr->next=oprr;
oprr->prior=oprr;
p1=opr1->prior;
p2=opr2->prior;
CF=buffer=flag=0;
while(p2!
=opr2)
{//opr2链的长度小于等于opr1链的
if(p1->data<(p2->data+CF))
{
buffer=10000+p1->data-(p2->data+CF);
CF=1;
}
else
{
buffer=p1->data-(p2->data+CF);
CF=0;
}
p3=(NodeList)malloc(LEN);
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=buffer;
p1=p1->prior;
p2=p2->prior;
}
while(p1!
=opr1)
{//处理opr1链剩下的部分
if(p1->data{
buffer=10000+p1->data-CF;
CF=1;
}
else
{
buffer=p1->data-CF;
CF=0;
}
p3=(NodeList)malloc(LEN);
oprr->next->prior=p3;
p3->prior=oprr;
p3->next=oprr->next;
oprr->next=p3;
p3->data=buffer;
p1=p1->prior;
}
//处理链表开头结点值为0的无意义情况,若链表本身表示0,则不做如下处理
p3=oprr->next;
while(p3->data==0&&p3->next!
=oprr)
{
p3=p3->next;
flag=1;
}
if(flag)
{
qh=oprr->next;//保存无用结点的头尾指针
qt=p3->prior;//为释放做准备
oprr->next=p3;//重接next链
p3->prior=oprr;//重接prior链
qt->next=NULL;
while(qh!
=NULL)
{//重接prior链
qq=qh;
qh=qh->next;
free(qq);
}
}
oprr->data='+';
returnOK;
}
//---------------------带符号加法函数---------------------
Statusadd(NodeListopr1,NodeListopr2,NodeList&oprr)
{
if(opr1==NULL||opr2==NULL)
returnERROR;
if(opr1->data==opr2->data)
{//opr1,opr2符号相同
add_bas(opr1,opr2,oprr);
if(opr1->data=='+')
//opr1与opr2均为正数,即A+B的形式(A,B均是正数,下同)
oprr->data='+';
else//opr1与opr2均为负数,即(-A)+(-B)的形式
oprr->data='-';
}
else
{//符号不相同
if(opr1->data=='+')
{//A+(-B)的情况
if(compare(opr1,opr2)==-1)
{//A
sub_bas(opr2,opr1,oprr);
oprr->data='-';
}
else
{//A>=B的情况
sub_bas(opr1,opr2,oprr);
oprr->data='+';
}
}
else
{//(-A)+B的情况
if(compare(opr1,opr2)==1)