- 算法学习
高精度乘法
- @ 2025-10-1 10:41:42
1. 概念引入:乘法原理的模拟
高精度乘法用于计算两个超过内置数据类型(如 long long)存储范围的超大整数 和 的乘积 。
其核心原理是模拟我们日常进行竖式乘法的过程:
- 逐位相乘: 将乘数 的每一位,依次乘以被乘数 的每一位。
- 错位相加: 将所有这些乘积(即中间结果)根据其位数位置错位对齐后,进行累加。
- 统一进位: 最后,对累加得到的结果进行统一的进位处理。
2. 实现步骤与代码解析
我们将以您提供的代码为例,分步解析高精度乘法的实现。
步骤 A:输入与逆序存储
与高精度加法和减法相同,为了方便计算和处理位数,我们采用逆序存储的方式,将大整数的个位存入数组下标 1 的位置。
代码解析:
char a[200],b[200];
cin >> a >> b;
int lena = strlen(a); // A的长度
int lenb = strlen(b); // B的长度
// 将 A 逆序存入 a1,个位在 a1[1]
for(int i = 1; i <= lena; i++)
{
a1[i] = a[lena-i]-'0';
}
// 将 B 逆序存入 b1,个位在 b1[1]
for(int i = 1; i <= lenb; i++)
{
b1[i] = b[lenb-i]-'0';
}
步骤 B:核心运算——逐位相乘与累加
这一步是乘法的核心。我们使用双重循环来模拟 的每一位乘以 的每一位,并将乘积累加到结果数组 中对应位置。
关键原理:位数对应关系
如果 的第 位(,代表 )乘以 的第 位(,代表 ),那么它们的乘积应该累加到结果的第 位上(代表 )。
| 运算 | 的位次 | 的位次 | 结果 的位次 | 结果 的数组下标 |
|---|---|---|---|---|
| 示例:个位 个位 | (个位) | |||
| 示例:十位 个位 | (十位) | |||
代码解析:
for(int i=1;i<=lena;i++) // 遍历 A 的每一位
{
for(int j=1;j<=lenb;j++) // 遍历 B 的每一位
{
// 累加:将 a1[i] * b1[j] 的乘积累加到结果 c[i+j-1] 上
// 此时 c[i+j-1] 存储的是可能大于 10 的中间和
c[i+j-1] += a1[i] * b1[j];
}
}
步骤 C:统一进位处理
经过步骤 B 后,结果数组 中的每一位可能都大于 9(例如 可能会被累加多次)。我们需要从低位向高位统一进行进位处理。
结果的最大长度: 两个 位数的乘积最多是 位。在这里,最大长度是 。
代码解析:
int len = lena + lenb; // 结果的最大可能长度
for(int i = 1; i <= len; i++) // 遍历结果 c 的每一位
{
// 将当前位 c[i] 产生的进位加到下一位 c[i+1] 上
c[i+1] += c[i] / 10;
// 当前位只保留个位数
c[i] = c[i] % 10;
}
步骤 D:处理前导零与输出结果
代码解析:
lenc = len; // 从结果的最大长度开始判断
// 跳过最高位可能的无效 0 (例如 10 * 10 = 100, 结果数组长度是 4,但 c[4] = 0)
while(c[lenc] == 0 && lenc > 1)
{
lenc--; // 缩短实际长度
}
// 逆序输出数组 c,得到最终结果
for(int i = lenc; i >= 1; i--)
{
cout << c[i];
}
3. 完整代码(高精度乘法)
#include <bits/stdc++.h>
using namespace std;
int a1[200],b1[200],c[200]; // 用数组存储大整数
int main()
{
char a[200],b[200];
cin >> a >> b;
int lena = strlen(a);
int lenb = strlen(b);
// --- 步骤 A: 逆序存储 ---
for(int i=1;i<=lena;i++)
{
a1[i]=a[lena-i]-'0';
}
for(int i=1;i<=lenb;i++)
{
b1[i]=b[lenb-i]-'0';
}
// --- 步骤 B: 逐位相乘与累加 ---
for(int i=1;i<=lena;i++)
{
for(int j=1;j<=lenb;j++)
{
// 乘积累加到对应的 c[i+j-1] 位置
c[i+j-1] += a1[i] * b1[j];
}
}
// --- 步骤 C: 统一进位处理 ---
int len = lena + lenb; // 结果最大长度
for(int i = 1; i <= len; i++)
{
// 进位加给下一位 c[i+1]
c[i+1] += c[i] / 10;
// 当前位只保留个位
c[i] = c[i] % 10;
}
// --- 步骤 D: 处理前导零与输出 ---
int lenc = len;
// 找到实际的最高位
while(c[lenc] == 0 && lenc > 1)
{
lenc--;
}
// 逆序输出结果
for(int i=lenc;i>=1;i--)
{
cout << c[i];
}
cout << endl;
return 0;
}
0 条评论
目前还没有评论...