您的位置:首页 > 其它

长整数相加运算(内含减法)。。= =

2010-11-12 08:27 267 查看
对长整数进行运算很变态,由于不能限制位数,所以一般采用链表进行计算,并且得自己设计进位退位的具体步骤,中间还有很多特殊情况和变态的情形得考虑进去。。。= =。WTF!

在之前的一篇blog中曾经探讨过这个问题,但是结果都不是很完善,这次的结果应该算是比较完美的了,理论上只要你的内存足够大,那么就能进行无限数位的长整数运算。

如有纰漏欢迎指出~~~

进行减法运算只需对被减的整数首位添加“-”即可

代码

/*
A,B均为整数,则运算时输入: A;B;
A,B中的隔位符号“,”可加可不加
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct Node                               //定义节点结构
{
int num;
struct Node *prev;
struct Node *next;
}Node;
Node *create();
Node *add(Node *A,Node *B);
Node *minus(Node *A,Node *B);
void main()
{
int i=0;
Node *P,*Q,*R,*TEMP,*r;
P=create();
Q=create();
if (P->num/Q->num==1)                     //对进行的运算进行分类,同号则相加,异号则相减
R=add(P,Q);
else
R=minus(P,Q);
if (R->num==-2||R->num==-4)               //结果是负数时在首位输出“-”
printf("-");
TEMP=R;                                   //在整数链表中插入“,”
while (TEMP->next)
TEMP=TEMP->next;
while (TEMP->prev)
{
if (i==3)
{
i=0;
r=(Node*)malloc(sizeof(Node));
r->next=TEMP;
r->num=',';
r->prev=TEMP->prev;
TEMP->prev->next=r;
TEMP->prev=r;
TEMP=r->prev;
continue;
}
else
{
i++;
TEMP=TEMP->prev;
}
}
R=R->next;
while (R)                              //输出结果,当因子为数字时以数字形式输出,否则以字符形式输出
{                                      //因而能够将之前插入的“,”成功输出
if (R->num!=',')
printf("%d",R->num);
else
{
if (R->prev->num>=0)             //排除在首位输出“,”的情况
printf("%c",R->num);
}
R=R->next;
}
printf("\n");
}
Node *create()                                      //创建整数动态链表,每个节点中存储一位数字
{
char c;
Node *A,*p,*temp;
A=(Node*)malloc(sizeof(Node));
A->num=-1;
A->prev=NULL;
p=A;
c=getchar();
while (c!=59)                                   //判断是否结束输入
{
if (c=='-')
{
A->num=-2;
c=getchar();
}
else                                                   //将输入的数字存储在动态链表中
{
if (c>='0'&&c<='9')
{
temp=(Node*)malloc(sizeof(Node));
temp->num=c-48;                                //此处将字符形态的数字转换为真实的数字
temp->prev=p;
p->next=temp;
p=temp;
c=getchar();
}
else
c=getchar();                                   //排除输入的字符“,”
}
}
p->next=NULL;
p=A;
return p;
}
Node *add(Node *A,Node *B)
{
Node *TEMP,*p,*q,*r;
int t=0;
p=A;
q=B;
while (p&&q)
{
if (p->next==NULL&&q->next!=NULL)
{
TEMP=A;
A=B;
B=TEMP;
break;
};
if (p->next==NULL&&q->next==NULL)
t=1;                                  //t为一个判断因子,用来判断是否是同位数的数字相加
p=p->next;
q=q->next;
}
p=A;
q=B;
while (p->next)                                 //分别存入两整数最后一位的节点地址,方便后面有低位到高位进行运算
{
p=p->next;
}
while (q->next)
{
q=q->next;
}
while(p->prev&&q->prev)
{
if ((p->num)>9)
{
if (p->prev==A)                            //如果最高位需要进位则创建一个新节点存储结果
{
r=(Node*)malloc(sizeof(Node));
r->prev=A;
r->num=1;
r->next=p;
p->num-=10;
p->prev=r;
A->next=r;
}
else
{
p->num-=10;
(p->prev->num)++;
}
}
p->num+=q->num;
if ((p->num)>9)                           //进位需要进行的操作
{
if (p->prev==A)
{
r=(Node*)malloc(sizeof(Node));
r->prev=A;
r->num=1;
r->next=p;
p->num-=10;
p->prev=r;
A->next=r;
}
else
{
p->num-=10;
(p->prev->num)++;
}
}
p=p->prev;
q=q->prev;
}
if (t!=1)                                      //不是同位数的数字相加则必须得将位数长的数字该进位的进位到底
{
while (p->prev->prev)
{
if (p->num>9)
{
p->num-=10;
p->prev->num++;
}
p=p->prev;
}
}
return A;
}
Node *minus(Node *A,Node *B)                     //大致思路同加法,只不过进位换成了退位
{
Node *TEMP,*p,*q;
int temp;
p=A;
q=B;
while (p&&q)
{
if (p->next==NULL&&q->next!=NULL)
{
TEMP=A;
A=B;
B=TEMP;
break;
}
if (p->next==NULL&&q->next==NULL)
{
if (A->num==-2)
{
TEMP=A;
A=B;
B=TEMP;
A->num=-3;
B->num=-4;
break;
}
else
{
A->num=-3;
B->num=-4;
break;
}
}
p=p->next;
q=q->next;
}
p=A;
q=B;
while (p->next)
{
p=p->next;
}
while (q->next)
{
q=q->next;
}
if (A->num!=-3)
{
while (p->prev&&q->prev)
{
temp=p->num;
p->num-=q->num;
if (p->num<0)
{
p->num=temp+10-q->num;
p->prev->num--;
}
p=p->prev;
q=q->prev;
}
while (p->prev->prev)
{
if (p->num<0)
{
p->num+=10;
p->prev->num--;
}
p=p->prev;
}
}
else
{
while (p->prev&&q->prev)
{
temp=p->num;
p->num-=q->num;
if (p->num<0&&p->prev!=A)
{
p->num=temp+10-q->num;
p->prev->num--;
}
if (p->num<0&&p->prev==A)
{
A->num=-4;
p->num=-p->num;
}
p=p->prev;
q=q->prev;
}
}
if (A->next->num==0)                           //最后将首位为0的从链表中舍去
{
p=A->next;;
while (p)
{
if (p->num==0&&p->next!=NULL)
{
A->next=p->next;
A->next->prev=A;
}
else
break;
p=p->next;
}
}
return A;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: