/*
功能Function Description: 大数除法
开发环境Environment: DEV C++ 4.9.9.1
技术特点Technique:
版本Version:
作者Author: 可笑痴狂
日期Date: 20120731
备注Notes:
解题方法:
基本的思想是反复做减法,看看从被除数里最多能减去多少个除数,商就是多少。一个一个减显然太慢,如何减得更快一些呢?
以7546 除以23 为例来看一下:开始商为0。先减去23 的100 倍,就是2300,发现够减3 次,余下646。于是商的值就增加300。
然后用646 减去230,发现够减2 次,余下186,于是商的值增加20。最后用186 减去23,够减8 次,因此最终商就是328。
所以本题的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。 计算除数的10 倍、100 倍的时候,
不用做乘法,直接在除数后面补0 即可。
*/
#include<stdio.h>
#include<string.h>
#define MAX 1000
int a1[MAX+10],a2[MAX+10],ans[MAX+10]; //a1被除数,a2除数,ans存放商。逆序存放
char s1[MAX+10],s2[MAX+10];
//长度为 nLen1 的大整数p1 减去长度为nLen2 的大整数p2
//结果放在p1 里,返回值代表结果的长度
//如不够减返回-1,正好减完返回 0
int Substract(int *p1,int *p2,int len1,int len2)
{
int i;
if(len1<len2)
return -1;
if(len1==len2)
{
for(i=len1-1; i>=0;--i)
{
if(p1[i]<p2[i]) //p1<p2
return -1;
else if(p1[i]>p2[i]) //p1>p2
break;
}
}
for(i=0;i<len1;++i)//要求调用本函数确保当i>=len2时,p2[i]=0
{
p1[i]-=p2[i];
if(p1[i]<0)
{
p1[i]+=10;
--p1[i+1];
}
}
for(i=len1-1;i>=0;--i)
if(p1[i]) //找到最高位第一个不为0
return i+1;
return 0; //全部为0,说明两者相等
}
int main()
{
int n,i,j,len1,len2,temp,nTimes;
scanf("%d",&n);
while(n--)
{
scanf("%s%s",s1,s2);
memset(a1,0,sizeof(a1));
memset(a2,0,sizeof(a2));
memset(ans,0,sizeof(ans));
len1=strlen(s1);
len2=strlen(s2);
if(len1<len2)
{
printf("0\n"); //不够除
continue;
}
for(i=len1-1,j=0;i>=0;--i)
a1[j++]=s1[i]-'0';
for(i=len2-1,j=0;i>=0;--i)
a2[j++]=s2[i]-'0';
nTimes=len1-len2;
if(nTimes>0)
{
for(i=len1-1;i>=nTimes;--i)
a2[i]=a2[i-nTimes];//朝高位移动
for(;i>=0;--i)
a2[i]=0; //低位补零
len2=len1;
}
for(i=0;i<=nTimes;++i)
{
//一直减到不够减为止
//先减去若干个 a2×(10 的nTimes次方),
//不够减了,再减去若干个 a2×(10 的nTimes-1 次方),......
while((temp=Substract(a1,a2+i,len1,len2-i))>=0) //注意while循环中的括号不能少
{
len1=temp;
++ans[nTimes-i];//每成功减一次,则将商的相应位加1
}
}
for(i=MAX;i>=0&&ans[i]==0;--i);//下面输出结果,先跳过高位0
if(i>=0)
for(;i>=0;--i)
printf("%d",ans[i]);
else
printf("0");
printf("\n");
}
return 0;
}