A*B Problem
题目描述
给出两个非负整数,求它们的乘积。
输入格式
输入共两行,每行一个非负整数。
输出格式
输出一个非负整数表示乘积。
样例 #1
样例输入 #1
1
2
样例输出 #1
2
提示
每个非负整数不超过 1 0 2000 10^{2000} 102000。
分析
- 与高精度加法一样啦,还是拆开一个一个对应相乘,在相加,类比小学乘法
点击查看其他高精度算法 - 事先说明:定义两个 char 类型的数组 s1 和 s2,分别存放两个乘数,定义两个 int 型的数组 a 和 b 存放转换后的乘数(将 char 型的 ‘1’ 转成 int 型的 ‘1’),int 型数组c 存放相乘的结果,数组c的长度是数组a与数组b长度之和(这是最长的情况),可以写几个数据试一下:
(这个排版可能在手机上可能有问题,可以用电脑看)
1 2 3 4 长度为4 | 1 2 3 4 长度为4
x 1 1 1 长度为3 | x 9 9 长度2
——————————————— | ————————————————
1 3 6 9 7 4 长度为6 | 1 2 2 1 6 6 长度为6
- 与加法一样,乘法也要将两个操作数翻转一下,结果也是逆着输出即可,在这里也要处理前导0,处理前导0的代码我改进了一下,在详细说明一下我这个处理前导0的细节(主要是0 * 0 = 0 的情况)
lenc = lenc - 1;
if (lenc >= 1) {
while (c[lenc] == 0 && lenc >= 1) {
lenc--;
}
}
看一下 0 * 0 = 0 的情况,此时lenc = lena + lenb = 2,数组c的是00
即c[0]=0,c[1]=0,所以有lenc = lenc - 1;因为while循环里的判断是c[lenc] == 0
在while循环往后,lenc可以当成数组下标来看了,抱歉我写的可能有点绕了
- 核心代码是这个
for (int i = 0; i < lenb; i++) {
for (int j = 0; j < lena; j++) {
c[i+j] += b[i] * a[j];
c[i+j+1] += c[i+j] / 10;
c[i+j] = c[i+j] % 10;
}
}
- 图示理解(千言万语唯有图示能表达出我的想法)
完整代码
#include <stdio.h>
#include <string.h>
//翻转函数
void reverse (int d[510], int len) {
int temp, mid = len/2;
for (int i = 0, j = len - 1; i < mid, j >= mid; i++, j--) {
temp = d[i];
d[i] = d[j];
d[j] = temp;
}
}
int main () {
char s1[2005], s2[2005];
int a[2005], b[2005], c[4010] = {0};
scanf("%s", s1);
scanf("%s", s2);
int lena = strlen(s1);
int lenb = strlen(s2);
int lenc = lena + lenb;
//将char的1转为int的1
for (int i = 0; i < lena; i++) {
a[i] = s1[i] - '0';
}
for (int i = 0; i < lenb; i++) {
b[i] = s2[i] - '0';
}
reverse(a, lena);
reverse(b, lenb);
//核心代码
for (int i = 0; i < lenb; i++) {
for (int j = 0; j < lena; j++) {
c[i+j] += b[i] * a[j];
c[i+j+1] += c[i+j] / 10;
c[i+j] = c[i+j] % 10;
}
}
//处理前导0
lenc = lenc - 1;
while (c[lenc] == 0 && lenc >= 1) {
lenc--;
}
//输出
for (int i = lenc; i >= 0; i--) {
printf("%d", c[i]);
}
return 0;
}
如若有错,欢迎大家斧正!<( ̄▽ ̄)/