#include
#include
#include
#include
#include
using namespace std;
//大数运算最关键的是用进制理解,就是把一个数组元素表示的最大值作为一个进制;如此,最容易的大数运算也是最耗费空间的就是一个元素表示一位数字,即用十进制表示;还有一种折中的方案,是一个元素最大能表示9999,如此用的是10000进制,则下面的baseNum = 10000;本文的实现的是最省空间的方法,一个元素就是一个unsigned short,这样就表示用2^16进制
const int MaxShort = 100;//最多有MaxShort * 2个字节//如果要表示64位int,MaxShort = 4
const int baseNum = pow(2.0,16.0);
const int Shift = 16;
typedef unsigned short Unshort;
typedef struct BigNum
{
int m_len;//可以通过m_len的正负,判断大数的正负。本程序未实现
Unshort m_data[MaxShort];
}BigNum;
void Reverse(char *src);
void GetAbsDecNum(BigNum &bg,char *tgt);
void PrintData(BigNum &a)
{
for (int i=0;ib,1;a = b,0;ab.m_len)
return 1;
if (a.m_len=0;--i)
{
if(a.m_data[i]>b.m_data[i])
return 1;
if(a.m_data[i] bg2
{
int left = bg1.m_len;
int right = bg2.m_len;
int carry = 0;
BigNum bg;
for (int i=0;i=0 && bg.m_data[bg.m_len -1]==0)
{
--bg.m_len;
}
return bg;
}
int AbsMinus(BigNum &bg1,int n,BigNum &bg2)//必须保证bg1的前n位的数要大于等于bg2//返回减少的位数
{
if(nn) ?n:bg1.m_len;
int beg = bg1.m_len -size;
int len2 = bg2.m_len;
int len1 = bg1.m_len;
int carry = 0;
for (int i=0;i=0 && bg1.m_data[bg1.m_len - 1] ==0)
--bg1.m_len;
return len1 - bg1.m_len;
}
bool AbsComp(BigNum &a,int n,BigNum &b)//大数的前n位数与b比较大小;a>=b返回true
{
int size = (a.m_len>n)? n:a.m_len;
if(size > b.m_len)
return true;
if(size =end;--i)
{
if(a.m_data[i]>b.m_data[i-end])
return true;
if(a.m_data[i] < b.m_data[i-end])
return false;
}
return true;
}
BigNum AbsDiv(BigNum &bg1,BigNum &bg2)//返回商,bg1变为余数;被除数的位数为n,除数的位数为m,则商的位数最多为n-m+1
{//bg1 >=bg2
BigNum c;
memset(c.m_data,0,sizeof(c.m_data));
int len2= bg2.m_len;
int cLen = bg1.m_len -len2 ;
int i=0;
while(AbsComp(bg1,bg2)>=0)
{
//cout<<"first while:"<<++i<=0 && c.m_data[cLen] ==0)
--cLen;
c.m_len = cLen +1;
return c;
}
BigNum AbsAdd(BigNum &bg1,BigNum &bg2)
{
int left = bg1.m_len;
int right = bg2.m_len;
int size = left;
int maxLen = right;
BigNum *bgmax = &bg2;
if(size>right)
{
size = right;
maxLen = left;
bgmax = &bg1;
}
int carry = 0;
BigNum bg;
for (int i=0;i>Shift;
//bg.m_data[i] = tmp &(1<m_data[i] + carry;
carry = tmp>>Shift;
//carry = tmp /baseNum;
//bg.m_data[i] = tmp &(1<0)
{
bg.m_data[i+j] += carry;
}
}
if(bg.m_data[bg1.m_len+bg2.m_len -1] > 0)
bg.m_len = bg1.m_len+bg2.m_len;
else
bg.m_len = bg1.m_len+bg2.m_len -1;
return bg;
}
void GetAbsDecNum(BigNum &bg,char *tgt)
{
int size = bg.m_len;
Unshort *data = bg.m_data;
int b=0;
while (size>0)
{
int i = size - 1;
int reminder = 0;
while (i>=0)
{
int divident = data[i] + reminder * baseNum;
reminder = divident % 10;
data[i] = divident /10;
--i;
}
tgt[b++] = reminder + '0';
while(size>0 && data[size -1]==0)
--size;
}
tgt[b] = '\0';
}
void Reverse(char *src)
{
int size = strlen(src);
int beg = size/2 -1;
for (;beg>=0;--beg)
{
int sym = size -beg -1;
char tmp = src[beg];
src[beg] = src[sym];
src[sym] = tmp;
}
}
int main()
{
char t[100];
memset(t,0,sizeof(t));
char s[] = "6430006453235007";//6430006453235007
BigNum bg = CreateAbsBigNum(s);
//PrintData(bg);
//BigNum bgg = bg;
//Print(bg);
//GetAbsDecNum(bg,t);
//Reverse(t);
//cout<
大数除法应该是最难实现的了,假设数组a除以b,实现它有两种方式:
1:用a-=b,循环,直到a
2:模拟现实,我们手算时是怎么算的,程序就怎么写,
假设a={2 4 2 3 1},b={2 3},结果result={0 0 0 0 0}:
先取a[0]a[1]即24,减去b一次,得a={0 1 2 3 1},result={0 1 0 0 0};
再取a[1]a[2]即12,发现它小于b,则多取一位,取a[1]a[2]a[3]即123,减b五次,得a={0 0 0 8 1},result={0 1 0 5 0};
再取a[3]a[4]即81,减b三次,得a={0 0 0 1 2},result={0 1 0 5 3}。
如果按照方法一计算,效率是无法容忍的。
假如用11111除以1,方法一要计算11111次,而方法二则只要5次。
下面是方法二的代码,经过了简单的测试(没做数据校验,假设数据都是正常的):
bool compare(int a[],int n,int b[],int m)//当a>=b时,返回true
{
int i=0;
int j=0;
int temp_n=n;
int temp_m=m;
while(a[i]==0)
{
i++;
temp_n--;
}
while(b[j]==0)
{
j++;
temp_m--;
}
if(temp_n>temp_m)
return true;
else if(temp_n
else
{
for(i,j;i
if(a[i]>b[j])return true;
if(a[i] }
return true;
}
}
void div(int a[],int n,int b[],int m)
{
int *result;
int *temp;
int start=0;
int end=start+m;
int i;
int flg=0;
int min=0;
result=new int[n];
for(i=0;i
temp=new int[m+1];
for(i=0;i
while(compare(a,n,b,m))
{
while(a[start]==0)
{
start++;
end++;
}
for(i=start;i
temp[i-start+1]=a[i];
}
if(!compare(temp,m+1,b,m))
{
end++;
for(i=start;i
}
while(compare(temp,m+1,b,m))
{
flg=0;
for(i=m;i>=1;i--)
{
min=temp[i]-b[i-1]-flg;
if(min<0)
{
min+=10;
flg=1;
}
else
flg=0;
temp[i]=min;
}
temp[i]-=flg;
result[end-1]++;
}
if(end-start==m)
{
for(i=start;i
a[i]=temp[i+1-start];
temp[i+1-start]=0;
}
}
else
{
for(i=start;i
a[i]=temp[i-start];
temp[i-start]=0;
}
}
start++;
end=start+m;
}
for(i=0;i
delete temp;
}