大数除法:把除法运算转化为减法运算
代码:
#include
#include
#include
using namespace std;
#define N 1000005
char a[N],b[N];
int x[N],y[N],c[N<<1];
//用长度为len1的大整数p1减去长度为len2的大整数p2
// 结果存在p1中,返回值代表结果的长度,不够减返回-1,正好减完返回0
int SubStract( int *k1, int *k2, int len1, int len2 )
{
if( len1 < len2 )
return -1;
if( len1 == len2 )
{
//判断k1 > k2
for(int i=len1-1; i>=0; i-- )
{
if( k1[i] > k2[i] )
break;
else if( k1[i] < k2[i] )
return -1;
}
}
for(int i=0; i<=len1-1; i++ ) //从低位开始做减法
{
k1[i] -= k2[i];
if( k1[i] < 0 ) //若p1<0,则需要借位
{
k1[i] += 10; //借1当10
k1[i+1]--; //高位减1
}
}
for(int i=len1-1; i>=0; i-- ) //查找结果的最高位
if( k1[i] ) //最高位第一个不为0
return (i+1); //得到位数并返回
return 0; //两数相等的时候返回0
}
int main()
{
while(~scanf("%s%s",a,b))
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(c,0,sizeof(c));
int len1=strlen(a),len2=strlen(b),len;
for(int i=len1-1,j=0; i>=0; j++,i--)
x[j]=a[i]-'0';
for(int i=len2-1,j=0; i>=0; j++,i--)
y[j]=b[i]-'0';
if( len1 < len2 ) //如果被除数小于除数,结果为0
{
printf("0\n");
printf("%s\n",a);
continue;
}
len= len1 - len2;
for (int i=len1-1; i>=0; i-- ) //将除数扩大,使得除数和被除数位数相等
{
if ( i>=len )
y[i] = y[i-len];
else //低位置0
y[i] = 0;
}
len2 = len1;
int n;
for(int j=0; j<=len; j++ ) //重复调用,同时记录减成功的次数,即为商
{
while((n= SubStract(x,y + j,len1,len2 - j)) >= 0)
{
len1 =n; //结果长度
c[len-j]++;//每成功减一次,将商的相应位加1
}
}
//输出商
while(1)
{
if(c[len])
break;
len--;
}
for(int i=len; i>=0; i--)
printf("%d",c[i]);
printf("\n");
//输出余数
while(1)
{
if(x[len1]||len1==0)
break;
len1--;
}
for(int i=len1; i>=0; i--)
printf("%d",x[i]);
printf("\n");
}
return 0;
}
大数辗转相除:就是根据上面的除法改一下
代码:
#include
#include
#include
using namespace std;
#define N 1000005
char a[N],b[N];
int x[N],y[N],c[N];
int SubStract( int *k1, int *k2, int len1, int len2 )
{
if( len1 < len2 )
return -1;
if( len1 == len2 )
{
//判断k1 > k2
for(int i=len1-1; i>=0; i-- )
{
if( k1[i] > k2[i] )
break;
else if( k1[i] < k2[i] )
return -1;
}
}
for(int i=0; i<=len1-1; i++ ) //从低位开始做减法
{
k1[i] -= k2[i];
if( k1[i] < 0 ) //若p1<0,则需要借位
{
k1[i] += 10; //借1当10
k1[i+1]--; //高位减1
}
}
for(int i=len1-1; i>=0; i-- ) //查找结果的最高位
if( k1[i] ) //最高位第一个不为0
return (i+1); //得到位数并返回
return 0; //两数相等的时候返回0
}
int main()
{
while(~scanf("%s%s",a,b))
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(c,0,sizeof(c));
int len1=strlen(a),len2=strlen(b),len;
if(len1=0; j++,i--)
x[j]=a[i]-'0';
for(int i=len2-1,j=0; i>=0; j++,i--)
y[j]=b[i]-'0';
int l;
while(1)
{
l=len2;
len= len1 - len2;
for (int i=len1-1; i>=0; i-- ) //将除数扩大,使得除数和被除数位数相等
{
if ( i>=len )
y[i] = y[i-len];
else //低位置0
y[i] = 0;
}
len2 = len1;
int n;
for(int j=0; j<=len; j++ ) //重复调用,同时记录减成功的次数,即为商
{
while((n= SubStract(x,y + j,len1,len2 - j)) >= 0)
len1 =n;
}
while(1)
{
if(x[len1-1]||len1==0)
break;
len1--;
}
if(len1==0) //余数为0时,此时除数就是最大公约数
{
for(int i=len2-1;i>=len2-l;i--)
printf("%d",y[i]);
printf("\n");
break;
}
//把除数变为下一个式子被除数,把余数变为除数
for(int i=0;i=len-l;i--,j--)
x[j]=y[i];
for(int i=0;i