# 【片段集】大数运算

BigNumber.h

#pragma once
#include <iostream>
using namespace std;
#define DIGITS_OF_BIG_NUMBER 50

class CBigNumber
{
public:

//operators
friend ostream& operator <<(ostream &cout,CBigNumber& bignumber);
friend istream& operator >>(istream &cin,CBigNumber& bignumber);

friend bool operator >(CBigNumber &bgn1,CBigNumber &bgn2);
friend bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2);
friend bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2);
friend bool operator <(CBigNumber &bgn1,CBigNumber &bgn2);
friend bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2);

friend CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2);
friend CBigNumber& operator +(int n,CBigNumber &bgn2);
friend CBigNumber& operator +(CBigNumber &bgn1,int n);

friend CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2);//没有进行符号处理

friend CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2);

friend CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2);

public:
CBigNumber();
CBigNumber(char* number);
CBigNumber(int n);
CBigNumber(long n);
private:
char m_cSign;//符号'+' or '-' 【未实现】
int m_Number[DIGITS_OF_BIG_NUMBER];//存储数据，栈式存储
int m_nDigits;//记录位数,由于数据是从高到低存储，初始值为DIGITS_OF_BIG_NUMBER，表示没有数位。
};

ostream& operator <<(ostream &cout,CBigNumber& bignumber);
istream& operator >>(istream &cin,CBigNumber& bignumber);

bool operator >(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator <(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2);

CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2);
CBigNumber& operator +(int n,CBigNumber &bgn2);
CBigNumber& operator +(CBigNumber &bgn1,int n);

CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2);

CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2);//bgn1为被乘数，bgn2为乘数

CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2);bgn1为被除数，bgn2为除数

BigNumber.cpp

#include <iostream>
#include "BigNumber.h"

using namespace std;

CBigNumber::CBigNumber()
{
m_cSign='+';
m_nDigits=DIGITS_OF_BIG_NUMBER;
memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
}
CBigNumber::CBigNumber(char* number)
{
m_nDigits=DIGITS_OF_BIG_NUMBER;
memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
char c=*number;
if(c!='-') m_cSign='+';//如果以'-'开头就认为是负数，否则都认为是正数
else m_cSign='-';
while(c!='\0')
{
if(c>='0'&&c<='9')
{
m_nDigits--;
m_Number[m_nDigits]=c-'0';
if(m_nDigits==0)
break;
}
number++;
c=*number;
}
//翻转成从低到高的阅读顺序
int d=(DIGITS_OF_BIG_NUMBER-1-m_nDigits)/2;
for(int i=0;i<=d;i++)
{
char c=m_Number[m_nDigits+i];
m_Number[m_nDigits+i]=m_Number[DIGITS_OF_BIG_NUMBER-1-i];
m_Number[DIGITS_OF_BIG_NUMBER-1-i]=c;
}
}
CBigNumber::CBigNumber(long n)
{
m_nDigits=DIGITS_OF_BIG_NUMBER;
memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
while(n>0)//n=0时不用操作，因为BigNumber初始化就是0
{
m_nDigits--;
m_Number[m_nDigits]=n%10;
n=n/10;
}
}
CBigNumber::CBigNumber(int n)
{
m_nDigits=DIGITS_OF_BIG_NUMBER;
memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
while(n>0)//n=0时不用操作，因为BigNumber初始化就是0
{
m_nDigits--;
m_Number[m_nDigits]=n%10;
n=n/10;
}
}
ostream& operator <<(ostream& cout,CBigNumber &bignumber)
{
if(bignumber.m_nDigits==DIGITS_OF_BIG_NUMBER)
cout<<0;
for(int i=bignumber.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)
cout<<bignumber.m_Number[i];
return cout;
}
istream& operator >>(istream &cin,CBigNumber &bignumber)
{
char c;
c=getchar();
while(c>='0'||c<=9)
{
bignumber.m_nDigits--;
bignumber.m_Number[bignumber.m_nDigits]=c-'0';
c=getchar();
if(bignumber.m_nDigits==0) break;
}
return cin;
}
bool operator >(CBigNumber &bgn1,CBigNumber &bgn2)
{
if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
return true;
else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
return false;
for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
{
if(bgn1.m_Number[i]>bgn2.m_Number[i])//
{
return true;
}
else if(bgn1.m_Number[i]<bgn2.m_Number[i])
{
return false;
}
}
//执行到这里说明是等于
return false;
}
bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2)
{
if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
return true;
else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
return false;
for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
{
if(bgn1.m_Number[i]>bgn2.m_Number[i])//
{
return true;
}
else if(bgn1.m_Number[i]<bgn2.m_Number[i])
{
return false;
}
}
//执行到这里说明是等于
return true;
}
bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2)
{
if(bgn1.m_nDigits!=bgn2.m_nDigits)//二者位数不相同
return false;
for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
{
if(bgn1.m_Number[i]!=bgn2.m_Number[i])
{
return false;
}
}
//执行到这里说明是等于
return true;
}
bool operator <(CBigNumber &bgn1,CBigNumber &bgn2)
{
if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
return false;
else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
return true;
for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
{
if(bgn1.m_Number[i]<bgn2.m_Number[i])//
{
return true;
}
else if(bgn1.m_Number[i]>bgn2.m_Number[i])
{
return false;
}
}
//执行到这里说明是等于
return false;
}
bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2)
{
if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
return false;
else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
return true;
for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
{
if(bgn1.m_Number[i]<bgn2.m_Number[i])//
{
return true;
}
else if(bgn1.m_Number[i]>bgn2.m_Number[i])
{
return false;
}
}
//执行到这里说明是等于
return true;
}

CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2)
{
static CBigNumber bgnSum;//较大的数作为被加数，和放在较大的数里
if(bgn1.m_nDigits<bgn2.m_nDigits)
{
bgnSum=bgn1;
}
else
{
bgnSum=bgn2;
}

int carry=0;
for(int i=DIGITS_OF_BIG_NUMBER-1;i>=bgnSum.m_nDigits;i--)
{
if(carry>=10)//如果大于10的话向前进位
{
bgnSum.m_Number[i]=carry-10;
carry=1;
}
else
{
bgnSum.m_Number[i]=carry;
carry=0;
}
break;
}
//bgnSum.m_nDigits=t;
if(carry&&bgnSum.m_nDigits>0)//加完了还有进位且不会溢出（被加数加完了），就补上
{
bgnSum.m_nDigits--;
bgnSum.m_Number[bgnSum.m_nDigits]=1;
}
return bgnSum;
}

CBigNumber& operator +(int n,CBigNumber &bgn2)
{
CBigNumber bgn1(n);
return bgn1+bgn2;
}
CBigNumber& operator +(CBigNumber &bgn1,int n)
{
CBigNumber bgn2(n);
return bgn1+bgn2;
}

CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2)
{
static CBigNumber bgnDif;//较大的数作为被减数，差放在被减数中
static CBigNumber *pBgnSubtractor;//较小的数作为减数
if(bgn1>bgn2)
{
bgnDif=bgn1;
pBgnSubtractor=&bgn2;
}
else
{
bgnDif=bgn2;
pBgnSubtractor=&bgn1;
}
int carry=0;
for(int i=DIGITS_OF_BIG_NUMBER-1;i>=bgnDif.m_nDigits;i--)
{
bgnDif.m_Number[i]-=carry;
carry=0;
if(bgnDif.m_Number[i]<pBgnSubtractor->m_Number[i])
{
carry=1;
bgnDif.m_Number[i]=bgnDif.m_Number[i]+10-pBgnSubtractor->m_Number[i];
}
else
{
bgnDif.m_Number[i]=bgnDif.m_Number[i]-pBgnSubtractor->m_Number[i];
}
if(carry==0&&pBgnSubtractor->m_nDigits>=i)//如果进位为0且减数减完了就结束
break;
}
//被减数减到头了还没减完，这种情况不存在
carry=0;
while(!bgnDif.m_Number[carry]) carry++;//重新计算位数
bgnDif.m_nDigits=carry;

return bgnDif;
}

CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2)
{
static CBigNumber bgnProduct;//积放在这里面
static CBigNumber *pBgn;
memset(&bgnProduct,0,sizeof(CBigNumber));
int carry=0;
int i,j;
for(i=DIGITS_OF_BIG_NUMBER-1;i>=bgn2.m_nDigits;i--)//乘数去成被乘数，循环的次数是乘数的位数
{
carry=0;
for(j=DIGITS_OF_BIG_NUMBER-1;j>=bgn1.m_nDigits;j--)//乘以被乘数的每一位
{
carry=bgn2.m_Number[i]*bgn1.m_Number[j]+carry+bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)];
if(carry>=10)
{
bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]+=carry%10;
carry/=10;
}
else
{
bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]=carry;
carry=0;
}
}
if(carry!=0)//被乘数乘空了还有进位
{
bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]=carry;
}
}
i=0;
while(bgnProduct.m_Number[i]==0) i++;
bgnProduct.m_nDigits=i;
return bgnProduct;
}

CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2)
{
static CBigNumber bgnQuotient;//商
static CBigNumber bgnTemp;//除法的中间量
memset(&bgnQuotient,0,sizeof(CBigNumber));
memset(&bgnTemp,0,sizeof(CBigNumber));
bgnQuotient.m_nDigits=DIGITS_OF_BIG_NUMBER;
if(bgn1<bgn2)//小于的话结果为0
return bgnQuotient;

int nIndex=bgn1.m_nDigits-1;//当前取到除数的第几位，指向上一次读的位置

//取被除数的前n个数放进temp，n为除数的位数
for(int i=DIGITS_OF_BIG_NUMBER-bgn2.m_nDigits;i>0;i--)
{
nIndex++;
bgnTemp.m_Number[DIGITS_OF_BIG_NUMBER-i]=bgn1.m_Number[nIndex];
}
bgnTemp.m_nDigits=bgn2.m_nDigits;
//cout<<bgnTemp<<endl;

bgnQuotient.m_nDigits=0;
while(nIndex<DIGITS_OF_BIG_NUMBER-1)//被除数的所有位都取完结束运算
{
//如果temp小于除数，再取一个数放进去
while(bgnTemp<bgn2&&nIndex<DIGITS_OF_BIG_NUMBER-1)
{
for(int i=bgnTemp.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//temp中数据左移
bgnTemp.m_Number[i-1]=bgnTemp.m_Number[i];

bgnTemp.m_nDigits--;
nIndex++;
bgnTemp.m_Number[DIGITS_OF_BIG_NUMBER-1]=bgn1.m_Number[nIndex];
bgnQuotient.m_nDigits++;//准备迎接下一个商，如果是继续去数放进temp，那么商中会增加一个0
}

//计算temp/除数的结果，以及余数放进temp
while(bgnTemp>=bgn2)
{
bgnQuotient.m_Number[bgnQuotient.m_nDigits]++;
bgnTemp=bgnTemp-bgn2;
//cout<<"/.."<<bgnTemp<<"\t"<<bgnQuotient.m_Number[bgnQuotient.m_nDigits]<<endl;
}
}

//左移
for(int i=bgnQuotient.m_nDigits;i>=0;i--)
{
bgnQuotient.m_Number[DIGITS_OF_BIG_NUMBER-1-bgnQuotient.m_nDigits+i]=bgnQuotient.m_Number[i];
}
bgnQuotient.m_nDigits=DIGITS_OF_BIG_NUMBER-1-bgnQuotient.m_nDigits;
return bgnQuotient;
}

main.cpp

#include <iostream>
#include "BigNumber.h"
using namespace std;

int main(int argc, char* argv[])
{
CBigNumber bignumber1("123456789123456789");
CBigNumber bignumber2("123456789123456780");

cout<<"条件运算:"<<endl;
cout<<"> "<<(bignumber1>bignumber2)<<endl;
cout<<">="<<(bignumber1>=bignumber2)<<endl;
cout<<"=="<<(bignumber1==bignumber2)<<endl;
cout<<"< "<<(bignumber1<bignumber2)<<endl;
cout<<"<="<<(bignumber1<=bignumber2)<<endl;

cout<<"\n四则运算："<<endl;
cout<<"+"<<bignumber1+bignumber2<<endl;
cout<<"-"<<bignumber1-bignumber2<<endl;
//cout<<"*"<<bignumber1*bignumber2<<endl;
cout<<"*"<<CBigNumber("123456789")*CBigNumber("123456789")<<endl;
cout<<"/"<<CBigNumber("78945613")/CBigNumber("123")<<endl;

CBigNumber bgnI("1"),bgnJ("1");double n=1,m=1;
cout<<1<<'\t'<<bgnI<<"\t\t\t"<<n<<endl;
cout<<2<<'\t'<<bgnI<<"\t\t\t"<<endl;
for(int i=2;i<200;i+=2)
{
bgnI=bgnI+bgnJ; n=m+n;
bgnJ=bgnI+bgnJ; m=m+n;
cout<<i<<'\t'<<bgnI<<"\t\t\t"<<n<<endl;
cout<<i+1<<'\t'<<bgnJ<<"\t\t\t"<<m<<endl;
}

return 0;
}

10-16 378