大整数乘法 |
问题描述 |
求两个不超过 200位的非负整数的积。 |
输入数据 |
有两行,每行是一个不超过 200位的非负整数,没有多余的前导 0。 |
输出要求 |
一行,即相乘后的结果。结果里不能有多余的前导 0,即如果结果是 342,那么就不能输出为 0342。 |
输入样例 |
12345678900 |
98765432100 |
输出样例 |
1219326311126352690000 |
解题思路 |
在下面的例子程序中,用 unsigned an1[200]和 unsigned an2[200]分别存放两个乘数,用 aResult[400]来存放积。计算的中间结果也都存在 aResult中。aResult长度取 400是因为两个 200位的数相乘,积昀多会有 400位。an1[0], an2[0], aResult[0]都表示个位。 |
计算的过程基本上和小学生列竖式做乘法相同。为编程方便,并不急于处理进位,而将进位问题留待昀后统一处理。 |
现以 835×49为例来说明程序的计算过程。 |
先算 835×9。5×9得到 45个 1,3×9得到 27个 10,8×9得到 72个 100。由于不急于处理进位,所以 835×9算完后,aResult如下: |
|
图 7-2-1 接下来算 4×5。此处 4×5的结果代表 20个 10,因此要 aResult[1]+=20,变为: |
|
图 7-2-2 再下来算 4×3。此处 4×3的结果代表 12个 100,因此要 aResult[2]+= 12,变为: |
|
图 7-2-3 昀后算 4×8。此处 4×8的结果代表 32个 1000,因此要 aResult[3]+= 32,变为: |
|
图 7-2-4 |
乘法过程完毕。接下来从 aResult[0]开始向高位逐位处理进位问题。aResult[0]留下 5,把 4加到 aResult[1]上,aResult[1]变为 51后,应留下 1,把 5加到 aResult[2]上……昀终使得 aResult里的每个元素都是 1位数,结果就算出来了: |
|
图 7-2-5 总结一个规律,即一个数的第 i位和另一个数的第 j位相乘所得的数,一定是要累加到结果的第 i+j位上。这里 i, j都是从右往左,从 0开始数。
参考程序: |
|
#include <stdio.h> |
#include <string.h> |
#define MAX_LEN 200 |
unsigned an1[MAX_LEN+10]; |
unsigned an2[MAX_LEN+10]; |
unsigned aResult[MAX_LEN * 2 + 10]; |
char szLine1[MAX_LEN+10]; |
char szLine2[MAX_LEN+10]; |
int main() |
{ |
gets( szLine1); //gets函数读取一行 |
gets( szLine2); |
int i, j; |
int nLen1 = strlen( szLine1); |
memset( an1, 0, sizeof(an1)); |
memset( an2, 0, sizeof(an2)); |
memset( aResult, 0, sizeof(aResult)); |
j = 0; |
for( i = nLen1 - 1;i >= 0 ; i --) |
an1[j++] = szLine1[i] - '0'; |
int nLen2 = strlen(szLine2); |
j = 0; |
for( i = nLen2 - 1;i >= 0 ; i --) |
an2[j++] = szLine2[i] - '0'; |
|
for( i = 0;i < nLen2; i ++ ) { //每一轮都用 an1的一位,去和 an2各位相乘 |
//从 an1的个位开始 |
for( j = 0; j < nLen1; j ++ ) //用选定的 an1的那一位,去乘 an2的各位 |
aResult[i+j] += an2[i]*an1[j]; //两数第 i, j位相乘,累加到结果的第 i+j位 |
} |
//下面的循环统一处理进位问题 |
for( i = 0; i < MAX_LEN * 2; i ++ ) { |
if( aResult[i] >= 10 ) { |
aResult[i+1] += aResult[i] / 10; |
aResult[i] %= 10; |
} |
} |
//下面输出结果 |
bool bStartOutput = false; |
for( i = MAX_LEN * 2; i >= 0; i -- ) |
if( bStartOutput) |
printf("%d", aResult[i]); |
else if( aResult[i] ) { |
printf("%d", aResult[i]); |
bStartOutput = true; |
} |
if(! bStartOutput ) |
printf("0"); |
return 0; |
} |
实现技巧不一定一出现进位就马上处理,而是等全部结果算完后再统一处理进位,有时会方便些。 |