高精度运算是指在计算机科学和数值计算中,能够处理和运算非常大的数字的技术。在编程中,普通的整数类型(如 int 或 long)有其最大值的限制,超过这个范围的运算就会溢出。为了处理更大的数字,比如在大数加密、科学计算或经济模型分析中,就需要用到高精度(大数)运算。
高精度乘运算模拟的是手算竖式乘法的过程。与加法和减法不同,乘法需要将一个数的每一位分别与另一个数的每一位相乘,再将结果累加到对应的位置上,最后统一处理进位。
高精度乘法的实现步骤如下:
string 类变量来存储整个大数,字符串的每个字符可以直接映射到每一位上的数字。result[i+j] += a1[j] * a2[i],即第一个数的第 j 位与第二个数的第 i 位相乘的结果累加到结果的第 i+j 位上。所有位乘完后再统一处理进位。以下是高精度乘法的完整实现,核心在于双重循环的逐位相乘和统一进位处理:
1#include <iostream>
2using namespace std;
3
4// 将字符串s中的数字倒序转换为整数数组a
5void convert(int a[], string s) {
6 int len = s.length(); // 获取字符串长度
7 for (int i = 0; i < len; i++) {
8 a[i] = s[len - 1 - i] - '0'; // 倒序存储,便于从最低位开始运算
9 }
10}
11
12// 打印整数数组a表示的数字,数组中数字是倒序存储的
13void print(int a[], int len) {
14 for (int i = 0; i < len; i++) {
15 cout << a[len - 1 - i]; // 从后向前打印数组元素,以正确顺序显示数字
16 }
17 cout << endl;
18}
19
20// 使用传统乘法算法进行高精度乘法运算
21void multiplication(int a1[], int len1, int a2[], int len2, int result[], int &len) {
22 for (int i = 0; i < len2; i++) {
23 for (int j = 0; j < len1; j++) {
24 result[i + j] += a1[j] * a2[i]; // 相应位相乘并加到结果数组的相应位置
25 }
26 }
27 for (int i = 0; i < len; i++) {
28 result[i + 1] += result[i] / 10; // 处理进位
29 result[i] %= 10; // 保留个位
30 }
31 while (result[len - 1] == 0 && len > 1) { // 清除结果前导0,但至少保留一位数字
32 len--;
33 }
34}
35
36int main() {
37 string s1, s2;
38 int a1[105] = {0}; // 存储第一个数的数组,初始化为0
39 int a2[105] = {0}; // 存储第二个数的数组,初始化为0
40 cin >> s1 >> s2;
41 int len1 = s1.length(); // 第一个字符串的长度
42 int len2 = s2.length(); // 第二个字符串的长度
43 convert(a1, s1); // 转换第一个字符串为整数数组
44 convert(a2, s2); // 转换第二个字符串为整数数组
45
46 int result[205] = {0}; // 存储结果的数组,初始化为0,长度是两数长度之和
47 int len = len1 + len2; // 设置结果长度初值为两数长度之和
48
49 multiplication(a1, len1, a2, len2, result, len); // 执行乘法运算
50
51 print(result, len); // 打印结果
52 return 0;
53}以计算 123 × 45 为例:
第一步:逆序存入数组
第二步:逐位相乘并累加
核心公式:result[i+j] += a1[j] * a2[i]
遍历 a2 的每一位(i),与 a1 的每一位(j)相乘:
| a2[i] | a1[j] | 乘积 | 累加到 result[i+j] |
|---|---|---|---|
| a2[0]=5 | a1[0]=3 | 15 | result[0] += 15 → 15 |
| a2[0]=5 | a1[1]=2 | 10 | result[1] += 10 → 10 |
| a2[0]=5 | a1[2]=1 | 5 | result[2] += 5 → 5 |
| a2[1]=4 | a1[0]=3 | 12 | result[1] += 12 → 22 |
| a2[1]=4 | a1[1]=2 | 8 | result[2] += 8 → 13 |
| a2[1]=4 | a1[2]=1 | 4 | result[3] += 4 → 4 |
乘完后 result[] = {15, 22, 13, 4, 0}
第三步:统一进位处理
| 位置i | result[i] | 进位到i+1 | result[i]保留 |
|---|---|---|---|
| 0 | 15 | 15/10=1 | 15%10=5 |
| 1 | 22+1=23 | 23/10=2 | 23%10=3 |
| 2 | 13+2=15 | 15/10=1 | 15%10=5 |
| 3 | 4+1=5 | 5/10=0 | 5%10=5 |
进位后 result[] = {5, 3, 5, 5}
第四步:逆序输出
5535验证:123 × 45 = 5535,正确。
当你遇到一道高精度乘法题时,可以按以下步骤思考:
n + m + 1。result[i+j]。此时 result 中的值可能大于 9,这是正常的。%10),高位加上进位值(/10)。a1[j] * a2[i] 的结果应该累加到 result[i+j],而不是 result[i] 或 result[j]。这个公式对应的是竖式乘法中"第 i 位乘第 j 位的结果放在第 i+j 位"。0,但如果前导零清除过度可能导致什么都不输出。len-1(即 n+m-1),否则高位的进位可能丢失。