这道题目把我难住了,用普通的算法通不过。查了资料才知道,这道题目属于大数相乘的问题。
思路和大整数的加法类似,利用乘法的原理解题,用整数数组来解决大数的存储问题。(因为用整型类型来存储大数会发生溢出。)
所谓的乘法原理:是指两个数相乘,其结果等于一个数与另一个数的每一位上的数字相乘后所得到的数字之和。跟我们笔算两个数的乘法是一样的。
例如:125*12 = 5*12+20*12+100*12=1500
网上有很多这道题目的代码,但都是低位存储个位的数(也就是说,数组的存储结果跟实际得到的数字顺序上是恰恰相反的,如a[0]存储的是个位的数。),理解起来很费劲。我终于找到了一个按正常顺序存储的。代码如下,有详细的注释:
#include<iostream> #include<cstdio> #include<memory.h> #define MAX 10000 #define BASE 10000 //这里写10,100,1000,10000,1000000都可以,只是要注意输出格式 int h[MAX]; int main() { int i,j,k,carry; int n; while(scanf("%d", &n)!=EOF) { memset(h,0,MAX*sizeof(int)); //赋值,每一个都置为0 for(i=1,h[MAX-1]=1; i<=n; ++i) //从i=1一直到i=n,将数组的最后一位置为1 for(k=MAX-1,carry=0; k>=0; --k) //从最后一位开始相乘,依次向前与每一位相乘,乘积保存在carry中 { carry+=i*h[k]; h[k]=carry%BASE; carry/=BASE; } for(j=0;j<MAX && h[j]==0; ++j) //从0位开始搜索,找到不为0的第一个数 ; printf("%d", h[j++]); //输出第一个不为0的位,第一位可能不足四位,就地输出! for( ;j<MAX; ++j) printf("%04d", h[j]); //处在中间的值也可能没有四位,这时候要注意了,往左边加0,凑足四位,不然答案会出错! printf("\n"); } return 0; }
根据上面的原理,我写了一个大数(用数组存储)与数(用int存储)的函数:
void Multiply(int bigNum[], int bigLen, int smallNum) { /** **说明:bigNum应该足够长,个位数存储在最后一位,高位没有的置为0 */ int i,j,carry=0; for(i=bigLen-1;i>=0;--i) { carry+=smallNum*bigNum[i]; bigNum[i]=carry%10; carry=carry/10; } }
上面函数中,用的是十进制,便于输出。
完整的例子如下:
#include<iostream> #include<cstdio> #include<memory.h> void Multiply(int bigNum[], int bigLen, int smallNum) { /** **说明:bigNum应该足够长,个位数存储在最后一位,高位没有的置为0 */ int i,j,carry=0; for(i=bigLen-1;i>=0;--i) { carry+=smallNum*bigNum[i]; bigNum[i]=carry%10; carry=carry/10; } } int main() { int i; int a[10]={0,0,0,0,0,0,2,3,4,5}; int b=34; Multiply(a,10,b); for(i=0;i<10 && a[i]==0; ++i) ; for(;i<10;i++) printf("%d", a[i]); return 0; }