大数运算的代码

翻出一段大二时写的代码,大数运算,包括四则,阶乘,乘方。大数的数据结构是链表,每个节点存4位数,所以理论上可计算任意大的整数。

刚刚测试了一下,在GCC 4.2下可以正常编译运行,顿时内牛满面(VC 6.0下写的代码)。在此贴上源代码。

#include #include typedef int ElemType; typedef struct NodeType { ElemType data; NodeType *prior; NodeType *next; }NodeType,*LinkType; bool MakeNode(LinkType &p,ElemType e) { p=(LinkType)malloc(sizeof(NodeType)); if(!p) return false; p->data=e; p->prior=NULL; p->next=NULL; return true; } typedef struct { LinkType head; int size; }OrderedList; bool InitList(OrderedList &L) { if(MakeNode(L.head,0)) { L.size=0; return true; } else { L.head=NULL; return false; } } void DestroyList(OrderedList &L) { LinkType p,q; p=L.head; do{ q=p; if(L.size) p=p->next; free(q); }while(L.size--); L.head=NULL; } int GetLength(OrderedList &L) { LinkType p; int i; i=0; p=L.head; do{ p=p->next; i++; }while(p!=L.head); i--; return i; } void AddNodeTail(OrderedList &L,LinkType p) { if(!L.size) { L.head->next=p; L.head->prior=p; p->prior=L.head; } else { p->prior=L.head->prior; L.head->prior->next=p; L.head->prior=p; } p->next=L.head; L.size++; } void AddNodeHead(OrderedList &L,LinkType p) { if(L.size) { p->next=L.head->next; L.head->next->prior=p; } else { p->next=L.head; L.head->prior=p; } p->prior=L.head; L.head->next=p; L.size++; } void Delete0(OrderedList &L) { LinkType p,q; p=L.head->prior; while(!p->data&&L.size>1) { L.head->prior=p->prior; p->prior->next=L.head; L.size--; q=p; p=p->prior; free(q); } } bool CompareList(OrderedList &L1,OrderedList &L2) { LinkType p1,p2; int i; Delete0(L1); Delete0(L2); if(L1.size>L2.size) return true; else if(L1.sizeprior; p2=p2->prior; if(p1->data>p2->data) return true; else if(p1->datadata) return false; } return true; } } bool CopyList(OrderedList L1,OrderedList &L2) { int i; LinkType p1,p2,q1,q2; p1=L1.head; p2=L2.head; for(i=0;i<=L1.size;i++) { p2->data=p1->data; p1=p1->next; if(inext==L2.head)) { p2=NULL; if(MakeNode(p2,0)) AddNodeTail(L2,p2); else return false; } else p2=p2->next; } q1=p2->prior; while(L2.size>L1.size) { q2=p2; p2=p2->next; free(q2); L2.size--; if(L2.size==L1.size) { q1->next=L2.head; L2.head->prior=q1; } } return true; } bool Add(OrderedList &L1,OrderedList &L2,OrderedList &SumList) { LinkType pSum,p1,p2; int co,t; if(!InitList(SumList)) return false; Delete0(L1); Delete0(L2); co=0; p1=L1.head->next; p2=L2.head->next; while(p1!=L1.head&&p2!=L2.head) if(MakeNode(pSum,0)) { AddNodeTail(SumList,pSum); t=p1->data+p2->data+co; pSum->data=t%10000; co=t/10000; pSum=NULL; p1=p1->next; p2=p2->next; } else return false; while(p1!=L1.head) if(MakeNode(pSum,0)) { t=p1->data+co; pSum->data=t%10000; co=t/10000; AddNodeTail(SumList,pSum); pSum=NULL; p1=p1->next; } else return false; while(p2!=L2.head) if(MakeNode(pSum,0)) { t=p2->data+co; pSum->data=t%10000; co=t/10000; AddNodeTail(SumList,pSum); pSum=NULL; p2=p2->next; } else return false; if(co) if(MakeNode(pSum,co)) { AddNodeTail(SumList,pSum); pSum=NULL; } else return false; Delete0(SumList); return true; } bool Sub(OrderedList &L1,OrderedList &L2,OrderedList &SubList) { LinkType pSub,p1,p2; int co,t; if(!InitList(SubList)) return false; Delete0(L1); Delete0(L2); p1=L1.head->next; p2=L2.head->next; co=0; while(p1!=L1.head&&p2!=L2.head) if(MakeNode(pSub,0)) { AddNodeTail(SubList,pSub); t=p1->data-p2->data+co; pSub->data=(t+10000)%10000; co=t<0?-1:0; pSub=NULL; p1=p1->next; p2=p2->next; } else return false; while(p1!=L1.head) if(MakeNode(pSub,0)) { t=p1->data+co; pSub->data=(t+10000)%10000; co=t<0?-1:0; AddNodeTail(SubList,pSub); pSub=NULL; p1=p1->next; } else return false; Delete0(SubList); return true; } bool Mul(OrderedList &L1,OrderedList &L2,OrderedList &MulList) { LinkType p1,p2,pMul,pt,pnew; int co,t; if(!InitList(MulList)) return false; Delete0(L1); Delete0(L2); co=0; t=0; p2=L2.head->next; pMul=NULL; while(p2!=L2.head) { p1=L1.head->next; if(pMul==NULL&&MakeNode(pMul,0)) AddNodeTail(MulList,pMul); pt=pMul; while(p1!=L1.head) { t=pt->data+p1->data*p2->data+co; pt->data=t%10000; co=t/10000; if(pt->next==MulList.head&&MakeNode(pnew,0)) AddNodeTail(MulList,pnew); else if(pt->next==MulList.head) return false; pnew=NULL; p1=p1->next; pt=pt->next; } pt->data+=co; co=0; pMul=pMul->next; p2=p2->next; } if(co) { pt->data=co; co=0; } else if(co) return false; Delete0(MulList); return true; } bool Div(OrderedList &L1,OrderedList &L2,OrderedList &DivList) { int i,t; bool flag,x; LinkType pL1Left,pL1Right,pDiv,ptLeft,ptRight,pSingle; OrderedList MulList,L1Sub,SingleList; Delete0(L1); Delete0(L2); if(!InitList(DivList)||!InitList(SingleList)) return false; if(MakeNode(pSingle,0)) AddNodeTail(SingleList,pSingle); else return false; flag=false; pL1Right=L1.head; if(L1.size>L2.size) for(i=1;i<=L2.size;i++) pL1Right=pL1Right->prior; else pL1Right=L1.head->next; while(!flag) { pL1Left=L1.head->prior; if(MakeNode(pDiv,0)) AddNodeHead(DivList,pDiv); else return false; if(pL1Right->prior!=L1.head) { ptLeft=pL1Right->prior; ptRight=L1.head->next; pL1Right->prior=L1.head; L1.head->next=pL1Right; } else flag=true; L1.size=GetLength(L1); t=L1.size>L2.size?pL1Left->data*10000+pL1Left->prior->data:pL1Left->data; t=t>0?t-1:t; pSingle->data=t/(L2.head->prior->data+1); x=false; do{ if(x) DestroyList(MulList); x=true; if(!Mul(SingleList,L2,MulList)) return false; pSingle->data++; }while(CompareList(L1,MulList)); pSingle->data-=2; pDiv->data=pSingle->data; DestroyList(MulList); if(!Mul(SingleList,L2,MulList)||!Sub(L1,MulList,L1Sub)) return false; if(!CopyList(L1Sub,L1)) return false; DestroyList(L1Sub); if(!flag) { L1.head->next->prior=ptLeft; ptLeft->next=L1.head->next; ptRight->prior=L1.head; L1.head->next=ptRight; L1.size=GetLength(L1); pL1Right=pL1Right->prior; } pDiv=NULL; } Delete0(DivList); return true; } bool Factorial(OrderedList &L,OrderedList &Lt) { OrderedList L1,LSub,MulList; LinkType p1,pMul,pt; Delete0(L); if(L.size==1&&(!L.head->next->data||L.head->next->data==1)) { if(!InitList(Lt)) return false; if(MakeNode(pt,1)) AddNodeTail(Lt,pt); else return false; return true; } if(!InitList(L1)) return false; if(MakeNode(p1,1)) AddNodeTail(L1,p1); else return false; if(!InitList(Lt)) return false; if(!CopyList(L,Lt)) return false; do{ if(!Sub(L,L1,LSub)) return false; if(!Mul(Lt,LSub,MulList)) return false; if(!CopyList(MulList,Lt)) return false; DestroyList(MulList); if(!CopyList(LSub,L)) return false; DestroyList(LSub); }while(!(L.size==1&&L.head->next->data==1)); return true; } bool Involution(OrderedList L1,OrderedList &L2,OrderedList &ResultList) { OrderedList L3,LMul,LSub; LinkType p3; Delete0(L1); Delete0(L2); if(!InitList(L3)) return false; if(MakeNode(p3,1)) AddNodeTail(L3,p3); else return false; if(!InitList(ResultList)) return false; if(!CopyList(L3,ResultList)) return false; while(!(L2.size==1&&L2.head->next->data==0)) { if(!Mul(ResultList,L1,LMul)) return false; if(!CopyList(LMul,ResultList)) return false; DestroyList(LMul); if(!Sub(L2,L3,LSub)) return false; if(!CopyList(LSub,L2)) return false; DestroyList(LSub); } return true; } bool ReadInteger(OrderedList &L1,OrderedList &L2) { char elem; bool flag1,flag2,flag3; LinkType p; flag1=0; flag2=0; flag3=0; getchar(); while(true) { elem=getchar(); if(!flag1&&!flag2) if(InitList(L1)) { if(elem=='-') { L1.head->data=1; flag2=1; } else if(elem=='+') continue; else if(elem>='0'&&elem<='9') if(MakeNode(p,elem-'0')) { AddNodeHead(L1,p); p=NULL; flag2=1; flag3=1; } else return false; } else return false; else if(!flag1&&flag2&&!flag3) if(MakeNode(p,elem-'0')) { AddNodeHead(L1,p); p=NULL; flag3=1; } else return false; else if(!flag1&&flag3) { if(elem==',') flag3=0; else if(elem==' ') { flag1=1; flag2=0; flag3=0; } else if(elem>='0'&&elem<='9') { L1.head->next->data*=10; L1.head->next->data+=elem-'0'; } } else if(flag1&&!flag2) if(InitList(L2)) { if(elem=='-') { L2.head->data=1; flag2=1; } else if(elem=='+') continue; else if(elem>='0'&&elem<='9') if(MakeNode(p,elem-'0')) { AddNodeHead(L2,p); p=NULL; flag2=1; flag3=1; } else return false; } else return false; else if(flag1&&flag2&&!flag3) if(MakeNode(p,elem-'0')) { AddNodeHead(L2,p); p=NULL; flag3=1; } else return false; else if(flag1&&flag2&&flag3) if(elem==',') flag3=0; else if(elem==' ') return true; else if(elem>='0'&&elem<='9') { L2.head->next->data*=10; L2.head->next->data+=elem-'0'; } } } void InputStyle() { printf("输入长整数与运算符,如“123,4567 234,5678 *”\n"); } void Error() { printf("内存空间不足\n"); } void Output(OrderedList &L) { int i; bool flag; LinkType p; if(L.head->data==1) printf("-"); flag=false; p=L.head->prior; for(i=1;i<=L.size;i++) { if(!flag) flag=true; else if(p->data<10) printf("000"); else if(p->data<100) printf("00"); else if(p->data<1000) printf("0"); printf("%d",p->data); if(i!=L.size) printf(","); p=p->prior; } printf("\n"); } bool Control(OrderedList &L1,OrderedList &L2,OrderedList &ResultList) { int t1,t2,t; bool compare; char elem; elem=getchar(); t1=L1.head->data; t2=L2.head->data; t=L2.head->next->data; if((t1==t2&&elem=='+'||t1!=t2&&elem=='-')&&Add(L1,L2,ResultList)) ResultList.head->data=t1; else if(t1!=t2&&elem=='+') { compare=CompareList(L1,L2); if(compare&&Sub(L1,L2,ResultList)) ResultList.head->data=t1; else if(!compare&&Sub(L2,L1,ResultList)) ResultList.head->data=t2; else return false; } else if(t1==t2&&elem=='-') { compare=CompareList(L1,L2); if(compare&&Sub(L1,L2,ResultList)) ResultList.head->data=0; else if(!compare&&Sub(L2,L1,ResultList)) ResultList.head->data=1; else return false; } else if(elem=='*'&&Mul(L1,L2,ResultList)) { if(t1==t2) ResultList.head->data=0; else ResultList.head->data=1; } else if(elem=='/'&&Div(L1,L2,ResultList)) { if(t1==t2) ResultList.head->data=0; else ResultList.head->data=1; } else if(elem=='%'&&Div(L1,L2,ResultList)) { CopyList(L1,ResultList); if(t1==t2) ResultList.head->data=0; else ResultList.head->data=1; } else if(elem=='!'&&Factorial(L1,ResultList)){} else if(elem=='^'&&Involution(L1,L2,ResultList)) { if(!t1) ResultList.head->data=0; else { if(t%2==0) ResultList.head->data=0; else ResultList.head->data=1; } } else return false; if(ResultList.size==1&&!ResultList.head->next->data) ResultList.head->data=0; DestroyList(L1); DestroyList(L2); return true; } int main() { OrderedList L1,L2,ResultList; int times; printf("需要测试几组数据? "); scanf("%d",×); while(times--) { InputStyle(); if(!ReadInteger(L1,L2)) { Error(); return 0; } if(Control(L1,L2,ResultList)) { Output(ResultList); DestroyList(ResultList); } else Error(); } return 0; }
排版有点乱,作为一个macvim小白,不知道怎么才能re-indent,愿知者以闻。

现在看来,这段代码写得实在不咋的。从软件工程的角度看,用C++的语法写C代码,没把ADT封装成类,而写成了结构体和相关函数。从视觉美观的角度看,变量与运算符,行与行之间没有空格,空行,难看之极。从算法的角度看,乘法很朴素,没有用分治之类的优化,时间复杂度为O(n^2);阶乘更加不堪,从前往后算……

再往底层考虑优化,可以应用对象池技术,减少从堆区申请内存空间的次数。

你可能感兴趣的:(大数运算的代码)