大整数乘法

问题描述

求两个不超过 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;

 }

实现技巧不一定一出现进位就马上处理,而是等全部结果算完后再统一处理进位,有时会方便些。

posted on 2010-04-16 14:17  蓝牙  阅读(287)  评论(0编辑  收藏  举报