高精度算法
登录以参加训练计划
📚 高精度算法——让计算机学会“列竖式”
适用场景:当数字大到连 long long
都存不下时(比如1000位的数字),我们就需要像小学生一样逐位计算。下面用糖果店进货的例子来讲解~
🍭 第一部分:高精度加法(糖果进货)
问题:老板进了 123456789
颗糖和 987654321
颗巧克力,总数是多少?
C++代码实现
#include <iostream>
#include <cstring> // 使用字符串处理大数
using namespace std;
const int MAXN = 1000; // 最大支持1000位数字
int main() {
char s1[MAXN], s2[MAXN]; // 用字符串读入大数
int a[MAXN] = {0}, b[MAXN] = {0}, c[MAXN] = {0}; // 数字逆序存到数组
// 输入示例(可以修改这两个数字玩)
cout << "请输入第一个大数:";
cin >> s1; // 例如输入 "123456789"
cout << "请输入第二个大数:";
cin >> s2; // 例如输入 "987654321"
// Step1. 将字符串逆序存入数组(个位在前)
int len1 = strlen(s1);
for (int i = 0; i < len1; i++) {
a[i] = s1[len1-1 - i] - '0'; // 逆序存储,比如 "123" 存成 [3,2,1]
}
int len2 = strlen(s2);
for (int i = 0; i < len2; i++) {
b[i] = s2[len2-1 - i] - '0';
}
// Step2. 逐位相加(像列竖式)
int len_max = max(len1, len2);
int carry = 0; // 进位
for (int i = 0; i < len_max; i++) {
c[i] = a[i] + b[i] + carry;
carry = c[i] / 10; // 计算进位
c[i] %= 10; // 当前位保留个位
}
// Step3. 处理最高位进位(比如9+9=18需要多一位)
if (carry > 0) {
c[len_max] = carry;
len_max++;
}
// Step4. 逆序输出结果
cout << "相加结果:";
for (int i = len_max-1; i >= 0; i--) {
cout << c[i];
}
return 0;
}
运行示例:
请输入第一个大数:123456789
请输入第二个大数:987654321
相加结果:1111111110
🍬 第二部分:高精度减法(糖果销售)
问题:原有 987654321
颗糖,卖出 123456789
颗,还剩多少?
代码核心逻辑(接加法代码之后)
// 高精度减法函数(确保a >= b)
void big_sub(int a[], int b[], int len_a, int len_b) {
int c[MAXN] = {0};
for (int i = 0; i < len_a; i++) {
if (a[i] < b[i]) { // 需要借位
a[i+1]--; // 向前借1
a[i] += 10; // 当前位加10
}
c[i] = a[i] - b[i];
}
// 去掉前导零(比如 100-99=001 → 显示1)
int pos = len_a-1;
while (c[pos] == 0 && pos > 0) pos--;
cout << "相减结果:";
for (int i = pos; i >= 0; i--) {
cout << c[i];
}
}
// 主函数中调用示例:
// 比较两个数谁大(略,实际需要先判断大小)
// big_sub(a, b, len1, len2);
运行示例:
请输入第一个大数(大数):987654321
请输入第二个大数(小数):123456789
相减结果:864197532
🍫 第三部分:高精度乘法(糖果批发)
问题:每箱有 123456789
颗糖,采购 987
箱,总共有多少?
代码核心逻辑
void big_mul(int a[], int b[], int len_a, int len_b) {
int c[MAXN] = {0};
for (int i = 0; i < len_a; i++) {
for (int j = 0; j < len_b; j++) {
c[i+j] += a[i] * b[j]; // 关键步骤:乘积累加
c[i+j+1] += c[i+j] / 10; // 处理进位
c[i+j] %= 10;
}
}
// 处理总进位
int len_c = len_a + len_b;
while (len_c > 0 && c[len_c-1] == 0) len_c--;
cout << "相乘结果:";
for (int i = len_c-1; i >= 0; i--) {
cout << c[i];
}
}
运行示例:
请输入第一个大数:123456789
请输入第二个大数:987
相乘结果:121851851643
📝 高精度算法总结表
操作 | 核心步骤 | 注意事项 |
---|---|---|
加法 | 逐位相加,处理进位 | 最高位可能有进位 |
减法 | 逐位相减,处理借位 | 确保大数减小数,去掉前导零 |
乘法 | 双重循环累加,处理多级进位 | 结果位数=两数位数之和 |
除法 | 试商法(较复杂,暂不展开) | 通常只做高精度÷低精度 |
🌟 学习建议
- 动手实践:修改代码中的数字,观察不同计算结果
- 扩展挑战:尝试实现高精度除法(比如123456789 ÷ 45)
- 应用场景:CSP-J竞赛中处理大数运算、密码学等领域
现在试着用这些代码计算你家电话号码连加十次的结果吧!(๑>ڡ<)✿
- 参加人数
- 0
- 创建人