您的位置:首页 > 其它

求两个不超过100位的非负整数的和,差,乘,除

2013-12-01 19:30 232 查看
思想:

用字符串来控制输入,数组来存储,数组的低位存整数的低位,高位来存储高位,

和:计算的过程基本上和小学生列竖式做加法相同。

差:跟和差不多

乘:计算的过程基本上和列竖式做乘法相同。为编程方便,并不急于处理进位,而将进位问题留待最后统一处理

除:基本的思想是反复做减法,看看从被除数里最多能减去多少个除数,商就是多少。一个一个减显然太慢,如何减得更快一些呢?以7546除以23 为例来看一下:开始商为0。先减去23 的100 倍,就是2300,发现够减3
次,余下646。于是商的值就增加300。然后用646 减去230,发现够减2次,余下186,于是商的值增加20。最后用186 减去23,够减8 次,因此最终商就是328。

n的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。 计算除数的10倍、100 倍的时候,不用做乘法,直接在除数后面补0 即可。

void sum(char *str1,char *str2,int MAX_LEN);
void substract(char *str1,char *str2,int MAX_LEN);
void product(char *str1,char *str2,int MAX_LEN);
void divide(char *str1,char *str2,int MAX_LEN);

int main(int argc, const char * argv[])
{

const int MAX_LEN = 200;

char str1[MAX_LEN],str2[MAX_LEN];

scanf("%s",str1);
scanf("%s",str2);

printf("和:");
sum(str1,str2,MAX_LEN);
printf("差:");
substract(str1,str2,MAX_LEN);
printf("乘:");
product(str1,str2,MAX_LEN);
printf("除:");
divide(str1,str2,MAX_LEN);

return 0;
}

void sum(char *str1,char *str2,int MAX_LEN)//加
{
//    求两个不超过100位的非负整数的和

int arr1[MAX_LEN];
int arr2[MAX_LEN];

memset(arr1,0,sizeof(arr1));//对数组进行清零
memset(arr2,0,sizeof(arr2));

int strlen1 =(int)strlen(str1);
int strlen2 =(int)strlen(str2);

int i,j;
for(i=0,j=strlen1-1;j>=0;i++,j--)//把字符串的字符转换为数字后
arr1[i]=str1[j]-'0';            //从后往前传递给数组
for(i=0,j=strlen2-1;j>=0;i++,j--)
arr2[i]=str2[j]-'0';

for(i=0;i<MAX_LEN;i++)//按位相加
{
arr1[i]+=arr2[i];//数组arr1保存运算后的结果
if(arr1[i]>=10) //按10进位
{
arr1[i]-=10;
arr1[i+1]++;//进位
}
}

for(i=MAX_LEN-1;(i>=0)&&(arr1[i]==0);i--);//从数组后面往前输出,即为结果
if(i>=0)
for(;i>=0;i--)
printf("%d",arr1[i]);
else
printf("0");
printf("\n");
}
void substract(char *str1,char *str2,int MAX_LEN)//减
{
//    求两个不超过100位的非负整数的差

int arr1[MAX_LEN];
int arr2[MAX_LEN];

memset(arr1,0,sizeof(arr1));//对数组进行清零
memset(arr2,0,sizeof(arr2));

int strlen1 =(int)strlen(str1);
int strlen2 =(int)strlen(str2);

int i,j;
for(i=0,j=strlen1-1;j>=0;i++,j--)//把字符串的字符转换为数字后
arr1[i]=str1[j]-'0';            //从后往前传递给数组
for(i=0,j=strlen2-1;j>=0;i++,j--)
arr2[i]=str2[j]-'0';

int nStartPos=0;
for(i=0;i<MAX_LEN;i++)//按位相减
{
arr1[i]-=arr2[i];//数组arr1保存运算后的结果
if(arr1[i]<0) //借位
{
arr1[i]+=10;
arr1[i+1]--;//借位
}
if(arr1[i])
nStartPos=i;//记录最高位的位置
}

//    for(i=MAX_LEN-1;(i>=0)&&(arr1[i]==0);i--);//从数组后面往前输出,即为结果
i=nStartPos;
if(i>=0)
for(;i>=0;i--)
printf("%d",arr1[i]);
else
printf("0");
printf("\n");
}
void product(char *str1,char *str2,int MAX_LEN)//乘
{
//    求两个不超过100位的非负整数的积

int arr1[MAX_LEN],arr2[MAX_LEN],arr3[2*MAX_LEN];

for(int k=0;k<MAX_LEN;k++)arr1[k]=0;
for(int k=0;k<MAX_LEN;k++)arr2[k]=0;
for(int k=0;k<2*MAX_LEN;k++)arr3[k]=0;

int i,j;
int strlen1=(int)strlen(str1);
int strlen2=(int)strlen(str2);

for(i=0,j=strlen1-1;j>=0;i++,j--)//把字符串的字符转换为数字后
arr1[i]=str1[j]-'0';            //从后往前传递给数组
for(i=0,j=strlen2-1;j>=0;i++,j--)
arr2[i]=str2[j]-'0';

for(i=0;i<strlen2;i++)//用第二个数乘以第一个数
{
for(j=0;j<strlen1;j++)
arr3[i+j]+=arr2[i]*arr1[j];//乘
}
for(i=0;i<MAX_LEN*2;i++)//进位
{
if(arr3[i]>=10)
{
arr3[i+1]+=arr3[i]/10;
arr3[i]%=10;
}
}
for(i=2*MAX_LEN-1;(arr3[i]==0)&&(i>=0);i--);
if(i>=0)
for(;i>=0;i--)
printf("%d",arr3[i]);
else
printf("0");
printf("\n");
}
void divide(char *str1,char *str2,int MAX_LEN)//除
{
int divide_sub( int * p1, int * p2, int strlen1, int strlen2);
int arr1[MAX_LEN]; //被除数, arr1[0]对应于个位
int arr2[MAX_LEN]; //除数, arr2[0]对应于个位
int aResult[MAX_LEN]; //存放商,aResult[0]对应于个位
//长度为 strlen1 的大整数p1 减去长度为strlen2 的大整数p2
//结果放在p1 里,返回值代表结果的长度
//如不够减返回-1,正好减完返回 0

int i, j;
int strlen1 = (int)strlen( str1);
memset( arr1, 0, sizeof(arr1));
memset( arr2, 0, sizeof(arr2));
memset( aResult, 0, sizeof(aResult));

for( j = 0, i = strlen1 - 1;i >= 0 ; i --)
arr1[j++] = str1[i] - '0';
int strlen2 = (int)strlen(str2);
for( j = 0, i = strlen2 - 1;i >= 0 ; i --)
arr2[j++] = str2[i] - '0';
if( strlen1 < strlen2 )
{
printf("0\n");
}
int nTimes = strlen1 - strlen2;
if(nTimes > 0)
{
for( i = strlen1 -1; i >= nTimes; i -- )
arr2[i] = arr2[i-nTimes];//朝高位移动
for( ; i >= 0; i--)//低位补0
arr2[i] = 0;
strlen2 = strlen1;
}
for( j = 0 ; j <= nTimes; j ++ )
{
int nTmp;
//一直减到不够减为止
//先减去若干个 arr2×(10 的 nTimes 次方),
//不够减了,再减去若干个 arr2×(10 的 nTimes-1 次方),......
while( (nTmp = divide_sub(arr1, arr2+j, strlen1, strlen2-j)) >= 0)
{
strlen1 = nTmp;
aResult[nTimes-j]++; //每成功减一次,则将商的相应位加1
}
}
//下面输出结果,先跳过高位0
for( i = MAX_LEN-1; (i >= 0) && (aResult[i] == 0); i -- );
if( i >= 0)
for( ; i>=0; i--)
printf("%d", aResult[i]);
else
printf("0");
printf("\n");
}
int divide_sub( int * p1, int * p2, int strlen1, int strlen2)
{
int i;
if( strlen1 < strlen2 )
return -1;
//下面判断p1 是否比p2 大,如果不是,返回-1
if( strlen1 == strlen2 )
{
for( i = strlen1-1; i >= 0; i -- )
{
if( p1[i] > p2[i] )           break; //p1>p2
else if( p1[i] < p2[i] )   return -1; //p1<p2
}
}
for( i = 0; i < strlen1; i ++ )
{ //要求调用本函数确保当i>=strlen2 时,p2[i] = 0
p1[i] -= p2[i];
if( p1[i] < 0 )
{
p1[i]+=10;
p1[i+1] --;
}
}
for( i = strlen1 -1 ; i >= 0 ; i-- )
if( p1[i] )//找到最高位第一个不为0
return i + 1;
return 0;//全部为0,说明两者相等
}


测试:

666666666666666666666666666666666666666666666666666666666666666666
22222222222222222222222222222222222222222222222222222222222222222
和:688888888888888888888888888888888888888888888888888888888888888888
差:644444444444444444444444444444444444444444444444444444444444444444
乘:14814814814814814814814814814814814814814814814814814814814814814651851851851851851851851851851851851851851851851851851851851851852
除:30
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐