大数的乘法
1 ;敲完了大数加法减法之后,自然而然的就开始敲大数成法了,其实大数乘法是算法与前面我们敲的大数加减法类似,只是代码长一点点罢了,废话不多说。直接分析了。
2;第一步,我们先模拟大数乘法的运算吧(相当于小学学的乘法列式),先说说两位比较小的数的乘积是怎么算的呢。例如999*91;第一步是1*999=999,然后9*999=8991;最后就是999+89910=90909;则999*91的结果就是90909,这一运算就相当于模拟我们小学学的乘法列式一样的原则。大数也是一样的,总体来说分两大部分。这两大部分里面又包含几个小的部分考虑完了之后,那么代码也就出啦了
第一部分就是将一个比较短的数中的每个数都去乘以那个比较长的数,并且将每位数字与其那个大数的乘积(注意这也是大数)都要用一个数组(并且要是二维数组)记录下来,
第二部分就是将记录下来的大数相加,也就是把大数的乘法变成大数的加法了,这里面还也要注意的是记得加0,正如上面那个事列中9*999=8991但是加上的确实89910;这一点要注意,(这里我们为了后面的大数相加的方便,所以就用了字符串来存储了)
1,比较长度并赋值,这个在大数的加减法中经常做到,所以代码就只需粘贴复制即可了。
2,同样的我们的思维然而是从后面开始运算,因此那个循环也是与前面大数加减一样的,
3,这里我们需要的是加0的步骤怎么完成,这其实有规律的,短的那个数最低位是不加0的,前一位就加一个0,前几位就是加几个0,因此我们只需要在前面加个循环,特意来完成在存储和的数组里加0了。至于变量,循环的控制就需要自己去琢磨了。记得补上’0’因为我们是用字符串存储乘积的。
K在循环外初始化值为-1;
k++;
for(q = k; q != 0; q--){//乘法后面补0;
dwcjh[w][l] = 0+'0';//注意这里要加上'0',当时我调试了好久才发现这个bug;
// printf("%d\n",dwcjh[w][l]);
l++;
}
4;怎么像加减法那样实现乘积呢,一样的我们仍然采取进位的方法,唯一的区别就是这里的进位可能不是1;要变成jwcj = wcj/10;
if(wcj > 9){
jwcj = wcj/10;//进位数
wcj = wcj%10;
}
else jwcj = 0;
dwcjh[w][l] = wcj+'0';
l++;
至于乘法就是类似的了 wcj = (a[i]-'0')*(b[j]-'0')+jwcj;//位乘积
5,同样我们这里也要注意最高位前面是否还有进位。
现在我们已经完成一半了,可在这里测试一下输出乘积的字符串,在你打对的情况下,是不是发现我们%s输出时他们都是反的,正如上面的89910我们的输出是01998,没错我们的代码要的就是这样的输出。如果你已经打出来了,那么就可以继续进行多组大数的加法了。
其实很简单就是大数加法多出了循环和strcpy赋值、还有就是strrev颠倒;
哈哈,就在刚才突然发现bug,初始化,初始化,因为我打的是多组输入因此在使用之前都用memset初始化为0;一下子改了好多bug了,之前的大数加减似乎也没有初始化的,(然而那里不用)、下次一定要记住多组输入字符串要记得每次都要memset初始化0;哈哈,突然发现只需将存储乘积的字符串初始化0即可,至于原因是,存储乘积的是二维数组,因为后面的是整体应用如果不初始化的话,那么前面的结果可能会影响后面的结果,为什么说的是如果,这就要自己去想了;嘻嘻。
1;因为要用到循环来两两计算,因此要在外面就要进行一次颠倒赋值;里面还会进行strrev关于颠倒的问题这个模拟一下就出来了的。这个模拟就是用小学的乘法式子与代码来一一模拟对应就OK了。
我们的代码是将字符串颠倒后仍然是从最后面往前面计算,并且将结果又颠倒,这时也可是输出答案。
2还有就是初始化问题,在最后面要初始化0一下。
#include<stdio.h>
#include<string.h>
int main()
{
int n, lena, lenb, m, mm, jwcj, wcj, l, q,flag, k, w, kk, i, j;
char a[100], b[100], t[100], dwcjh[100][150];
int jzs, c, wsh;
char ss[1000]={0},a1[1000],tt[1000];
scanf("%d",&n);
getchar();
while(n--){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(dwcjh,0,sizeof(dwcjh));//二维数组初始化化也是这样的;
scanf("%s",&a);
scanf("%s",&b);
lena = strlen(a);
lenb = strlen(b);
if(lena < lenb){//换边。将长的放在前面;
strcpy(t, b);
strcpy(b, a);
strcpy(a,t);
m = lenb;
lenb = lena;
lena = m;
}
k = -1;
w = 0;
for(j = lenb-1; j != -1; j--){
jwcj = 0;
l = 0;
k++;
for(q = k; q != 0; q--){//乘法后面补0;
dwcjh[w][l] = 0+'0';//注意这里要加上'0',当时我调试了好久才发现这个bug;
// printf("%d\n",dwcjh[w][l]);
l++;
}
for(i = lena-1; i != -1; i--){
wcj = (a[i]-'0')*(b[j]-'0')+jwcj;//位乘积
// printf("%d\n",wcj);
if(wcj > 9){
jwcj = wcj/10;//进位数
wcj = wcj%10;
}
else jwcj = 0;
dwcjh[w][l] = wcj+'0';//把这些乘积的数存起来等下再相加;
// printf("%d\n",wcj);
l++;
}
if(jwcj != 0){
dwcjh[w][l] = jwcj+'0';
l++;
}
// dwcjh[w][l] = '\0';
// printf("%s\n",dwcjh[w]);
w++;
// printf("%d\n",w);
}
//
以上完成了大数之间的乘法。剩下的就是将每个单位乘出来的数相加就是答案了。、
//
strrev(dwcjh[0]);
strcpy(a1,dwcjh[0]);
for(kk = 1; kk < w; kk++){
strrev(dwcjh[kk]);
lena = strlen(a1);
lenb = strlen(dwcjh[kk]);
if(lena < lenb){//换边。将长的放在前面;
strcpy(tt, dwcjh[kk]);
strcpy(dwcjh[kk], a1);
strcpy(a1,tt);
mm = lenb;
lenb = lena;
lena = mm;
}
// printf("%s\n",a1);
// printf("%s\n",dwcjh[kk]);
jzs = 0;
l = 0;
for(i = lena-1, j = lenb-1; j != -1; i--, j--){//计算公共部分。也就是数组短的那部分
wsh = (a1[i]-'0')+(dwcjh[kk][j]-'0')+jzs;
//printf("%d\n",wsh);
if(wsh > 9){
jzs = 1;
wsh = wsh%10;
}
else jzs = 0;
ss[l] = wsh+'0';//返回值要为字符串则里面的元素要是字符;
l++;
}
for(; i != -1; i--){//数组长的剩余的部分
wsh = (a1[i] - '0')+jzs;
if(wsh > 9){
jzs = 1;
wsh = wsh%10;
}
else jzs = 0;
ss[l] = wsh+'0';
l++;
}
if(jzs == 1){//考虑最后一位是否进位了
ss[l] = 1+'0';
l++;
}
//printf("%s\n",ss);
memset(a1, 0, sizeof(a1));//记得初始化;
strrev(ss);
strcpy(a1,ss);
memset(ss, 0, sizeof(ss));
}
printf("%s\n",a1);
}
return 0 ;
}