题目描述
算法分析与设计
其实这题对我来说比较具有挑战性,可能我的思维有时候不是很活跃,就是不太聪明,所以即使知道这题的解法就是模拟小学时候的竖式计算的过程,但是我依旧很弄不明白中间的一些代码是怎么写出来的,花费了很长时间把它弄懂了,我想尽可能详细的把解题的完整思路写出来,给有同样困惑的读者看,但是我始终觉得要把一个算法题目实现思路的细节描述清楚是一件很困难的事情,因为有时候实现细节真的就是应了那一句话只可意会不可言传,我的算法功底不是很好,所以无法用简单的语言把一个题目描述清楚,所以我只能尽量多写点,以求把题目讲解清楚。
思路分析:回想我们小学的时候做乘法是怎么做的,我们首先进行列竖式,列竖式时需要进行对齐操作,所谓对齐就是两个进行相乘的数的个位对个位,十位对十位,百位对百位,然后用一个数的每一位去乘以另一个数的每一位然后进行错位相加,如图是一个利用竖式来进行乘法运算的模拟过程,用2931 x 1937:
这题要求实现的是大数乘法,两个乘数的长度达到了100位,已经远远超过了计算机可以存储的最大整数,所以我们没有办法用整型的变量去存储这两个乘数更不用说用整型去存储他们的乘数了,所以我们需要借助两个字符数组来存放两个乘数,分别定义为num1,num2,还需要一个整数数组来存放结果,但是为了实现我们在进行“列竖式求两数乘法”时候的对齐操作,我们需要将两个乘数逆序存放在字符数组中,所以用数组来模拟列竖式求两数乘法的过程如图:
代码实现此过程:
for (int i = 0; i < cnum1; i++)
{
pin = 0;
for (int j = 0; j < cnum2; j++)
{
int temp = result[i + j] + (int)(num1[i] - '0') * (int)(num2[j] - '0') + pin; //这里注意要将字符数组中的字符型的数字转换成相对应的整数
result[i + j] = temp % 10;
pin = temp / 10;
len = i + j; //这里操作的目的是记录更新结果数组中的数字的个数,便于最后的逆序操作
}
if (pin)
{
result[cnum2 + i] = pin;
len = cnum2 + i;
}
}
读者可以仔细看看我上面用字符数组来模拟竖式计算的过程,停下来仔细想一下如下公式是怎么得到的,只要想清楚这一点这一题就可以解出来了
int temp = result[i + j] + (int)(num1[i] - '0') * (int)(num2[j] - '0') + pin; //这里注意要将字符数组中的字符型的数字转换成相对应的整数
result[i + j] = temp % 10;
这里如果还没有看明白的话可以去看看这个视频,然后再回来看我的代码就会明白这题是怎么做的了,视频链接:高精度算法-乘法_哔哩哔哩_bilibili
题目源代码以及运行结果截图
题目源代码
//高精度乘法:给出两个长度小于 100 位的正整数,求其乘积。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define N 201
int result[N] = { 0 };
//以下函数用于将一个字符数组进行逆序
void reverse(char* s, int n);
//以下函数用于记录一个字符串中的字符个数,不包括结束字符
int count_str(char* s);
int main()
{
char num1[100], num2[100];
int pin;
while (scanf("%s", num1) != EOF)
{
getchar();
scanf("%s", num2);
getchar();
int cnum1 = count_str(num1);
int cnum2 = count_str(num2);
reverse(num1, cnum1);
reverse(num2, cnum2);
int len;
for (int i = 0; i < cnum1; i++)
{
pin = 0;
for (int j = 0; j < cnum2; j++)
{
int temp = result[i + j] + (int)(num1[i] - '0') * (int)(num2[j] - '0') + pin; //这里注意要将字符数组中的字符型的数字转换成相对应的整数
result[i + j] = temp % 10;
pin = temp / 10;
len = i + j; //这里操作的目的是记录更新结果数组中的数字的个数,便于最后的逆序操作
}
if (pin)
{
result[cnum2 + i] = pin;
len = cnum2 + i;
}
}
for (int k = len; k >= 0; k--)
{
printf("%d", result[k]);
}
printf("\n");
}
}
void reverse(char* s, int n)
{
int i, j;
char temp;
for (i = 0, j = n - 1; i < j; i++, j--)
{
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
return;
}
int count_str(char* s)
{
int count = 0;
for (int i = 0; s[i] != '\0'; i++)
{
count++;
}
return count;
}
运行结果截图
祝学习进步,生活愉快!