这两天一直在利用一些课余的琐碎时间在写C++大整数,昨天晚上终于基本完工了,利用到的思想就是:
用一个连续的int型的存储空间去表示大整数和进行运算。在运算时将该大整数拆分成一个多项式,然后按照
多项式的规则进行运算,最后在输出显示该大整数时再将该大整数的每一项进行调整到0到9之间。本程序的
缺点就是存储空间利用率较低,有待优化的地方还很多。嗯。。等过几天有时间了再来优化吧。
BigInt.h
#pragma once #include<iostream> const int LIST_INIT_SIZE =100; //初始分配量 const int LISTINC = 30; //增长量 using namespace std; class BigInt { public: //链表扩充函数 bool EnlargeList(); BigInt(void);//初始化一个空的大整数 BigInt(int p[],int n,bool IsPN);//用int(值为0到9之间)的数组初始化一个大整数,n代表数组长度,IsPN表示是否为正数 BigInt(char p[],int n,bool IsPN);//用字符数组初始化一个大整数 BigInt(BigInt &);//复制构造函数 BigInt(int);//用int型数据初始化一个大整数 int GetSize()const {return size;}//返回该大整数的位数 void SetSize(int t){size = t;} int GetSign() const {return sign;}//返回该大整数的符号位 void SetSign(int t){sign = t;} int * GetEP(){return elem;}//返回数据区的指针 int GetFirste(){return firste;}//返回 void SetFirste(int t){firste = t;}//设置第一个非零系数项的指数 int GetCapacity(){return capacity;} BigInt & operator=(BigInt&);//赋值操作符重载 friend ostream& operator<<(ostream& os,BigInt & bit ); //输入输出流重载,不是类的成员 // 调整系数项的函数 void Juist(); //两个大整数相加 friend BigInt operator+(BigInt&,BigInt&); //两个大整数相减 friend BigInt operator-(BigInt&,BigInt&); //两个大整数相乘 friend BigInt operator*(BigInt&,BigInt&); //两个大整数相除(只取整数商部分 friend BigInt operator/(BigInt&,BigInt&); //两个大整数取余运算 friend BigInt operator%(BigInt&,BigInt&); //只针对正数之间的取余 //两个大整数相加等 BigInt& operator+=(BigInt&); //两个大整数相减等 BigInt& operator-=(BigInt&); //两个大整数相乘等 BigInt& operator*=(BigInt&); //两个大整数相除等(只取整数商部分 BigInt& operator/=(BigInt&); //大整数与int型数据相加 friend BigInt operator+(BigInt&,int); //大整数与int型数据相减 friend BigInt operator-(BigInt&,int); //大整数与int型数据相乘 friend BigInt operator*(BigInt&,int); //大整数与int型数据相除 friend BigInt operator/(BigInt&,int); //大整数与int型数据取余运算 friend BigInt operator%(BigInt&,int); //只针对正数之间的取余 //大整数与int型数据相加等 BigInt& operator+=(int); //大整数与int型数据相减等 BigInt& operator-=(int); //大整数与int型数据相乘等 BigInt& operator*=(int); //大整数与int型数据相除等 BigInt& operator/=(int); //两个大整数之间的关系运算 bool operator<(BigInt&); bool operator>(BigInt&); bool operator==(BigInt&); bool operator!=(BigInt&); bool operator<=(BigInt&); bool operator>=(BigInt&); //大整数与int型数据关系运算 bool operator<(int); bool operator>(int); bool operator==(int); bool operator!=(int); bool operator<=(int); bool operator>=(int); ~BigInt(void); private: int *elem;//连续存储空间的指针 int size;//大整数的位数 int capacity;//连续存储空间的大小 int firste;//第一个非0系数项数据对应的指数项 --- 默认指数项系数为从大到小排列的 int sign;//符号位,其中1代表正数,-1代表该大整数为负数 void clear();//清空一个大整数 };
BigInt.cpp
#include "BigInt.h" #include<stack> #include<iostream> using namespace std; BigInt::BigInt(void) { elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); capacity = LIST_INIT_SIZE; size = 0; firste = 0; sign = 1; } BigInt::BigInt(int pd[],int n,bool IsPN)//用int数组初始化一个大整数 { elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); capacity = LIST_INIT_SIZE; size = 0; firste = n-1; if(IsPN) { sign = 1; } else { sign = -1; } for(int i = 0;i<n;i++) { if(size>=capacity)//如果容量不够则进行扩充 { EnlargeList(); } elem[i] = pd[i]; size++; } } BigInt::BigInt(char pd[],int n,bool IsPN)//用字符数组初始化一个大整数 { elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); capacity = LIST_INIT_SIZE; size = 0; firste = n-1; if(IsPN) { sign = 1; } else { sign = -1; } int i =0; for(;i<n;i++) { if(size>=capacity)//如果容量不够则进行扩充 { EnlargeList(); } if(pd[i]<‘0‘||pd[i]>‘9‘) { throw range_error("字符数组异常");//抛出字符数组异常 } elem[i] = pd[i]-‘0‘; size++; } } BigInt::BigInt(BigInt & bit)//赋值构造函数 { elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); capacity = LIST_INIT_SIZE; size = bit.GetSize(); sign = bit.GetSign(); firste = bit.GetFirste(); for(int i=0;i<size;i++) { if(size>=capacity)//如果容量不够则进行扩充 { EnlargeList(); } elem[i] = bit.GetEP()[i]; } } BigInt::BigInt(int t)//用int型数据初始化一个大整数 { if(t>=0) sign =1; else sign = -1; t = abs(t);//取正 int p = t%10; stack<int> sta; sta.push(p); t = t/10; while(t!=0) { p = t%10; sta.push(p); t = t/10; } elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); capacity = LIST_INIT_SIZE; size = 0; int i =0; int n = sta.size(); firste = n-1; for(;!sta.empty();i++) { if(size>=capacity)//如果容量不够则进行扩充 { EnlargeList(); } elem[i] = sta.top(); sta.pop(); size++; } } BigInt& BigInt::operator=(BigInt& bit)//赋值操作符重载 { clear(); size = bit.GetSize(); sign = bit.GetSign(); firste = bit.GetFirste(); for(int i=0;i<size;i++) { if(size>=capacity)//如果容量不够则进行扩充 { EnlargeList(); } elem[i] = bit.GetEP()[i]; } return *this; } void BigInt::clear()//清空一个大整数 { if(capacity>LIST_INIT_SIZE) { free(elem); elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int)); } capacity = LIST_INIT_SIZE; size = 0; firste = 0; sign = 1; } ostream& operator<<(ostream& os,BigInt & bit ) //输入输出流重载,不是类的成员 { bit.Juist();//先调整系数项 if(bit.GetSign()<0) { os<<"-"; } //在输出时忽略大整数开头的所有为0的位 int i = 0; while(i<bit.GetSize() && bit.GetEP()[i]==0) { i++; } for(;i<bit.GetSize();i++) { os<<bit.GetEP()[i]; } return os; } //两个大整数相加 TODO 考虑符号位 BigInt operator+(BigInt &list1,BigInt &list2) { if(1==list1.GetSign()&&-1==list2.GetSign()) { list2.SetSign(1); for(int i = 0;i<list2.GetSize();i++) { list2.GetEP()[i] = -1*(list2.GetEP()[i]); } } if(-1==list1.GetSign()&&1==list2.GetSign()) { list2.SetSign(-1); for(int i = 0;i<list2.GetSize();i++) { list2.GetEP()[i] = -1*(list2.GetEP()[i]); } } BigInt re;//用于保存相加的结果 if((1==list1.GetSign()&&1==list2.GetSign())||(-1==list1.GetSign()&&-1==list2.GetSign())) { int size = 0; re.SetSign(list1.GetSign()); int ia = 0; int ib = 0; int ea = list1.GetFirste(); int eb = list2.GetFirste(); re.SetFirste(ea>eb ? ea : eb); while(ia<list1.GetSize()&&ib<list2.GetSize()) { if(ea > eb) { if(size>=re.GetCapacity())//如果容量不够则进行扩充 { re.EnlargeList(); } re.GetEP()[size++] = list1.GetEP()[ia++]; ea--; } else { if(ea < eb) { if(size>=re.GetCapacity())//如果容量不够则进行扩充 { re.EnlargeList(); } re.GetEP()[size++] = list2.GetEP()[ib++]; eb--; } else{ if(size>=re.GetCapacity())//如果容量不够则进行扩充 { re.EnlargeList(); } int db = list1.GetEP()[ia++]+list2.GetEP()[ib++]; re.GetEP()[size++] = db; ea--; eb--; } } } if(ia == list1.GetSize()) { while(ib<list2.GetSize()) { if(size>=re.GetCapacity())//如果容量不够则进行扩充 { re.EnlargeList(); } re.GetEP()[size++] = list2.GetEP()[ib++]; } } else { while(ia<list1.GetSize()) { if(size>=re.GetCapacity())//如果容量不够则进行扩充 { re.EnlargeList(); } re.GetEP()[size++] = list1.GetEP()[ia++]; } } re.SetSize(size); } return re; } //调整系数项的函数 {0,-1,0,1,2,5}; void BigInt::Juist() { //考虑情形 //情形一:系数项为负数且大于-10 //处理方案 --- 判断该系数项是否存在前驱项,若存在,找到第一个大于0的前驱项,则前驱项减一,循环,该系数项加十。 // --- 若不存在,改变该大整数的符号位为-1,并将该大整数的所有系数全部取相反的符号。 // --- 递归调整 //情形二:系数项为负数且小于等于-10 //处理方案 --- 将该系数拆分为按位数组(注意不要个位项),并向该系数对应的前向进行减法运算,若前向系数不存在,则就创建该系数 // --- 递归调整 //情形三:系数项为正数且大于等于0小于10 //处理方案 --- 直接赋值(不用处理) //情形四:系数项为正数且大于等于10 //处理方案 --- 将该系数拆分为按位数组(注意不要个位项),并向该系数对应的前向进行加法运算,若前向系数不存在,则就创建该系数 // --- 递归调整 int i = 0; while(i<size) { //情形三 if(0<=(elem[i])&&(elem[i])<10){;} //情形四 if((elem[i])>=10) { int t = elem[i]; int pi = t%10; elem[i] = pi; stack<int> sta; //sta.push(pi); t = t/10; while(t!=0) { pi = t%10; sta.push(pi); t = t/10; } //创建一个临时的大整数对象 BigInt bi; bi.SetSign(sign); int in1 =0; int n = sta.size() + firste - i; bi.SetFirste(n); for(;!sta.empty();in1++) { if(in1>bi.GetCapacity()) { bi.EnlargeList(); } bi.GetEP()[in1] = sta.top(); sta.pop(); } bi.SetSize(in1); //相加 (*this) += bi; //递归调整 Juist(); return; } //情形一 //情形一:系数项为负数且大于-10 //处理方案 --- 判断该系数项是否存在前驱项,若存在,找到第一个大于0的前驱项,则前驱项减一,循环,该系数项加十。 // --- 若不存在,改变该大整数的符号位为-1,并将该大整数的所有系数全部取相反的符号。 // --- 递归调整 if((elem[i])>-10&&(elem[i])<0) { int ini = 0; //若不存在非0前驱 while(elem[ini]==0) { ini++; } if(ini==i) { sign = -1*sign; for(int ii = 0;ii<size;ii++) { elem[ii] = -1*(elem[ii]); } //测试内部“调整函数” Juist(); return; } else { //存在前驱项 ,找到顺序第一个非0前驱 ini = 0; while((ini<i)&&(elem[ini]==0)) { ini++; } //非0项减1所有p之间的后驱项加9,p项加10 elem[ini] -= 1; ini++; while(ini!=i) { elem[ini] += 9; ini++; } elem[i] += 10; //递归 Juist(); return; } } //情形二 if((elem[i])<-10) { int t =elem[i]; t = abs(t); int pi = t%10; stack<int> sta; elem[i] = pi;// 修改项。。。。。。。。。。。。。。 //sta.push(pi); t = t/10; while(t!=0) { pi = t%10; sta.push(pi); t = t/10; } //创建一个临时的大整数对象 BigInt bi; bi.SetSign(sign); int ini =0; int n = sta.size() + firste - i; bi.SetFirste(n); for(;!sta.empty();ini++) { if(ini>bi.GetCapacity()) { bi.EnlargeList(); } bi.GetEP()[ini] = sta.top(); sta.pop(); } bi.SetSize(ini); //相加 (*this)-=bi; //递归调整 Juist(); return; } i++; } } //两个大整数相减 BigInt operator-(BigInt &list1,BigInt &list2) { list2.SetSign(-1*list2.GetSign()); return list1+list2; } //两个大整数相乘 BigInt operator*(BigInt &list1,BigInt &list2) { //创建一个空对象用于保存最后的结果 BigInt bit; int i2 = 0; //BigInt::LNode *p = list2.GetHead().next; while(i2<list2.GetSize()) { BigInt li = list1; //保存每一项的乘积之和 int i1 = 0; for(;i1<li.GetSize();i1++) { li.GetEP()[i1] = (li.GetEP()[i1])*(list2.GetEP()[i2]); } //重新设置li的第一个非0系数项的指数 li.SetFirste(li.GetFirste() + list2.GetFirste() - i2); bit+=li; i2++; } bit.SetSign(list1.GetSign()*list2.GetSign()); return bit; } //两个大整数相除(只取整数商部分) BigInt operator/(BigInt &list1,BigInt &list2) { //除法当作减法来做 int size1 = list1.GetSize(); int size2 = list2.GetSize(); if(size1<size2) { return 0; } //需不需要先估算商的取值范围 int a = size1 - size2; int re; if(a==0||a==1) { re = 0; } else { re = (int)pow(10,a-1); } //做差求商 for(;;re++) { BigInt bi = list1 - list2*(re+1); bi.Juist(); if(bi.GetSign()<0) { re *=(list1.GetSign()*list2.GetSign()); return BigInt(re); } } } //两个大整数取余运算 BigInt operator%(BigInt &list1,BigInt &list2) //只针对正数之间的取余 { if(list1.GetSign()<0||list2.GetSize()<0) { return NULL; } BigInt re = list1/list2; return list1 - re*list2; } //两个大整数相加等 BigInt& BigInt::operator+=(BigInt& list2) { (*this) = (*this)+list2; return (*this); } //两个大整数相减等 BigInt& BigInt::operator-=(BigInt& list2) { (*this) = (*this)-list2; return (*this); } //两个大整数相乘等 BigInt& BigInt::operator*=(BigInt& list2) { (*this) = (*this)*list2; return (*this); } //两个大整数相除等(只取整数商部分 BigInt& BigInt::operator/=(BigInt& list2) { (*this) = (*this)/list2; return (*this); } //大整数与int型数据相加 BigInt operator+(BigInt& list1 ,int t) { return list1 + BigInt(t); } //大整数与int型数据相减 BigInt operator-(BigInt& list1 ,int t) { return list1 - BigInt(t); } //大整数与int型数据相乘 BigInt operator*(BigInt& list1 ,int t) { return list1 * BigInt(t); } //大整数与int型数据相除 BigInt operator/(BigInt& list1 ,int t) { return list1 / BigInt(t); } //大整数与int型数据取余运算 BigInt operator%(BigInt& list1 ,int t) //只针对正数之间的取余 { return list1 % BigInt(t); } //大整数与int型数据相加等 BigInt& BigInt::operator+=(int t) { (*this) = (*this)+BigInt(t); return (*this); } //大整数与int型数据相减等 BigInt& BigInt::operator-=(int t) { (*this) = (*this)-BigInt(t); return (*this); } //大整数与int型数据相乘等 BigInt& BigInt::operator*=(int t) { (*this) = (*this)*BigInt(t); return (*this)*BigInt(t); } //大整数与int型数据相除等 BigInt& BigInt::operator/=(int t) { (*this) = (*this)/BigInt(t); return (*this); } //两个大整数之间的关系运算 bool BigInt::operator<(BigInt& list2) { BigInt bit = (*this) - list2; bit.Juist(); if(bit.GetSign()<0&&bit.GetSize()!=0) { return true; } else { return false; } } bool BigInt::operator>(BigInt& list2) { BigInt bit = (*this) - list2; bit.Juist(); if(bit.GetSign()>0&&bit.GetSize()!=0) { return true; } else { return false; } } bool BigInt::operator==(BigInt& list2) { BigInt bit = (*this) - list2; bit.Juist(); if(bit.GetSize()==0) { return true; } else { return false; } } bool BigInt::operator!=(BigInt& list2) { if(*this==list2) { return false; } return true; } bool BigInt::operator<=(BigInt& list2) { if(*this<list2||*this==list2) { return true; } return false; } bool BigInt::operator>=(BigInt& list2) { if(*this>list2||*this==list2) { return true; } return false; } //大整数与int型数据关系运算 bool BigInt::operator<(int t) { return (*this)<BigInt(t); } bool BigInt::operator>(int t) { return (*this)>BigInt(t); } bool BigInt::operator==(int t) { return (*this)==BigInt(t); } bool BigInt::operator!=(int t) { return (*this)!=BigInt(t); } bool BigInt::operator<=(int t) { return (*this)<=BigInt(t); } bool BigInt::operator>=(int t) { return (*this)>=BigInt(t); } //链表扩充函数 bool BigInt::EnlargeList() { int * newbase; newbase = (int *)realloc(elem,(capacity + LISTINC)*sizeof(int)); if(!newbase) { return false; } elem = newbase; capacity += LISTINC; return true; } BigInt::~BigInt(void) { free(elem); }
test.h
#include<iostream> #include"BigInt.h" using namespace std; void Test() { //测试一:新建一个空对象,输出内容和大小。 BigInt bit1; cout<<bit1<<endl; cout<<"该整数的位数为:"<<bit1.GetSize()<<endl; //测试二:用int数组初始化一个大整数,初始化为-98765 int a[5] = {9,8,7,6,5}; BigInt bit2(a,5,false); cout<<bit2<<endl; cout<<"该整数的位数为:"<<bit2.GetSize()<<endl; //测试三:用字符数组初始化一个大整数 char c[] = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; BigInt bit3(c,6,true); cout<<bit3<<endl; cout<<"该整数的位数为:"<<bit3.GetSize()<<endl; //测试四:复制构造函数 BigInt bit4 = bit3; cout<<bit4<<endl; cout<<"该整数的位数为:"<<bit4.GetSize()<<endl; //测试五:用int型数据初始化一个大整数 int a1 = -1234567890; BigInt bit5(a1); cout<<bit5<<endl; cout<<"该整数的位数为:"<<bit5.GetSize()<<endl; //测试六:测试两个大整数的加法 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; char cc[] = {‘1‘,‘8‘,‘1‘,‘1‘,‘1‘,‘1‘}; BigInt bit7(cc,6,true); BigInt bit8 = bit3 + bit7; cout<<"测试两个大整数的加法:"<<bit8<<endl; //yA: 1 3 3 3 3 2 //YB: -1 0 1 2 5 //测试七:测试内部“调整函数” int a3[6] = {0,-1,0,1,2,5}; BigInt bit6(a3,6,true); cout<<endl; cout<<"测试内部“调整函数”"<<endl; cout<<bit6<<endl; //测试八:两个大整数相减 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; int c8[] = {10,1,1,1,1,1}; BigInt bita(c8,6,true); BigInt bitb = bit3 - bita; cout<<"测试两个大整数的减法:"<<bitb<<endl; //测试九:两个大整数相乘 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; int c9[] = {1,1,1,1,1,1}; BigInt bit9(c9,6,true); BigInt bit91 = bit3 * bit9; cout<<"测试两个大整数的乘法:"<<bit91<<endl; //测试十:两个大整数相除 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; int c10[] = {1,1,1,1,1}; BigInt bit10(c10,5,true); BigInt bit101 = bit3 / bit10; cout<<"测试两个大整数的除法:"<<bit101<<endl; //测试十一:两个大整数取余运算 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; int ca11[] = {1,1,1,1,1,1}; BigInt bit10a(ca11,6,true); BigInt bit101a = bit3 % bit10a; cout<<"测试两个大整数的取余运算:"<<bit101a<<endl; //测试十二:大整数与int型数据相加 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; BigInt bit101a = bit3 + yyc; cout<<"大整数与int型数据相加:"<<bit101a<<endl; } //测试十三:大整数与int型数据相减 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; BigInt bit101a = bit3 - yyc; cout<<"大整数与int型数据相减:"<<bit101a<<endl; } //测试十四:大整数与int型数据相乘 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; BigInt bit101a = bit3 * yyc; cout<<"大整数与int型数据相乘:"<<bit101a<<endl; } //测试十五:大整数与int型数据相除 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; BigInt bit101a = bit3 / yyc; cout<<"大整数与int型数据相除:"<<bit101a<<endl; } //测试十六:大整数与int型数据取余运算 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; BigInt bit101a = bit3 % yyc; cout<<"大整数与int型数据取余运算:"<<bit101a<<endl; } //测试十七:两个大整数之间的关系运算 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int ca11[] = {1,1,1,1,1,1}; BigInt bit10a(ca11,6,true); bool bit101a = bit3 < bit10a; cout<<"两个大整数之间的关系运算:"<<bit101a<<endl; } //测试十八:大整数与int型数据关系运算 //bit3 = {‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘7‘}; { int yyc = 111111; bool bit101a = bit3 > yyc; cout<<"两个大整数之间的关系运算:"<<bit101a<<endl; } }
源.cpp
#include<iostream> #include"BigInt.h" #include"test.h" using namespace std; int main() { //先对该大整数类进行各项测试 Test(); int a[8] = {1,2,3,4,5,5,6,7}; BigInt res(a,8,true); cout<<"2^10000 = "<<res<<endl; int b[45] = {9,7,6,3,0,2,0,4,7,6,4,4,9,3,0,0,6,0,0,0,4,6,5,6,0,8,2,8,3,4,4,0,4,9,5,7,4,3,8,6,2,4,5,7,2}; BigInt res1(b,45,true); res1*=res; cout<<"res1:"<<res1<<endl; //输出:12053002341437676266101501982589696307190688041472324结果正确 }