💡 高精度是通过字符串 + 数组逆序存储模拟竖式计算,解决 C++ 内置类型(int/long long)无法存储和运算超大整数的方法,核心包含加减乘除四大基础运算。
1 通用基础
💡 字符串存大数、数组逆序拆分、结果逆序输出
1.1 核心存储逻辑
- 超大数无法用
int/long long存储,先存入string 字符串(x、y) - 字符串不能直接运算,需逐字符转数字并逆序存入数组
- 逆序原因:竖式计算从最低位开始,进位 / 借位时在数组尾部追加元素更方便,避免头部插入的复杂度
- 结果存储在数组
c中,最终逆序输出(从高位到低位)
专业 📚
- C++ 内置整型范围:
int(±2e9)、long long(±9e18),超过该范围的整数称为高精度数 - 逆序存储是高精度算法的行业标准方案,完美适配四则运算的进位 / 借位操作
拆分逆序核心代码 🧑💻
// 计算字符串长度
la = x.size();
lb = y.size();
lc = max(la, lb); // 结果长度初始值(加减除专用),乘法为 la+lb
// 逐字符转数字 + 逆序存入数组(核心代码)
for(int i = 0; i < la; i++) a[la - 1 - i] = x[i] - '0';
for(int i = 0; i < lb; i++) b[lb - 1 - i] = y[i] - '0';
⚠️ 适用场景 & 核心注意
- x[i] - '0' 是字符转数字的唯一标准方法(利用 ASCII 码差值)
- 所有高精度运算必须先执行逆序拆分,无例外
1.2 必备头文件 & 全局变量
-
强制头文件:
<string>:存储高精度数<algorithm>:调用max函数计算长度<iostream>:标准输入输出
-
全局数组:必须开大空间(防止栈溢出),
a/b存运算数,c存结果#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;const int N = 1e6 + 10; // 开大数组,避免越界
int a[N], b[N], c[N]; // a:第一个数 b:第二个数 c:运算结果
int la, lb, lc; // 三个数组的有效长度
string x, y; // 存储输入的超大数
1.3 通用输出逻辑
结果数组逆序存放,输出时从最后一位(最高位)向前遍历输出代码 🧑💻
// 逆序输出最终结果
for(int i = lc - 1; i >= 0; i--) cout << c[i];
2 ➕
💡 模拟小学竖式加法,逐位相加 + 处理进位,结果长度为最大数长度或 + 1。
2.1 核心逻辑
- 遍历每一位,将
a[i]和b[i]相加存入c[i] - 处理进位:
c[i]/10加到下一位,c[i]保留个位(%10) - 最后判断最高位是否进位,有则长度 + 1
专业 📚高精度加法时间复杂度为 O(n)(n 为数字位数),属于线性高效运算。
2.2 加法函数实现 🧑💻
// 高精度加法函数
void add(int a[], int b[], int c[], int length) {
for (int i = 0; i < length; i++) {
c[i] += a[i] + b[i]; // 逐位相加
c[i + 1] += c[i] / 10; // 处理进位
c[i] %= 10; // 保留当前位的个位数字
}
}
✨ 优化建议:原代码进位逻辑简化,直接用 c[i]/10 适配多进位场景,通用性更强
3 ➖
💡 模拟竖式减法,先判断大小保证被减数≥减数,逐位相减 + 处理借位,必须处理前导 0。
3.1 核心逻辑
- 大小判断:若减数 > 被减数,输出负号并交换两数,保证大数减小数
- 逐位相减,若结果 < 0,向前借 1(前一位 - 1,当前位 + 10)
- 处理前导 0 :避免输出
0001这类错误格式,结果为 0 时保留 1 个 0
高精度减法是唯一需要提前比较数大小的运算;前导 0 处理是输出规范的必要步骤。
⚠️ 适用场景 & 核心注意
- 适用场景:两个超大正整数相减
- 避坑 1:交换数字后再计算长度,否则长度错误
- 避坑 2:前导 0 循环条件用 lc>1,保留最后一个 0,避免无输出
3.2 减法函数实现 🧑💻
// 高精度减法函数
void sub(int a[], int b[], int c[]) {
for (int i = 0; i < lc; i++) {
c[i] += a[i] - b[i]; // 逐位相减
if (c[i] < 0) { // 不够减,需要向前借位
c[i + 1]--;
c[i] += 10;
}
}
}
4 ✖️
💡 模拟竖式乘法,双层循环逐位相乘(结果存在第 i+j 位),统一处理进位,结果长度为两数长度之和。
4.1 核心逻辑
- 双层循环:
a的第i位 ×b的第j位,结果存入 c[i+j] - ++所有位相乘完成后,统一处理进位(从低位到高位)++
- 处理前导 0,最后逆序输出
高精度乘法时间复杂度 O(n×m)(n/m 为两个数的位数);
4.2 乘法函数实现 🧑💻
// 高精度乘法函数
void mul(int a[], int b[], int c[]) {
// 双层循环:逐位相乘
for (int i = 0; i < la; i++) {
for (int j = 0; j < lb; j++) {
c[i + j] += a[i] * b[j];
}
}
// 统一处理所有位的进位
for (int i = 0; i < lc; i++) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
// 处理前导0
while (lc > 1 && c[lc - 1] == 0) lc--;
}
5 ➗
💡 仅实现高精度 ÷ 低精度 ,模拟竖式除法从最高位开始计算(和其他三个不同),余数迭代参与运算,处理前导 0。
5.1 核心逻辑
- 仅被除数是高精度数(存 string),除数是低精度数(int)
- 计算顺序:从最高位到最低位(与加减乘完全相反)
- 核心公式:
余数×10 + 当前位 = 新被除数 - 商 = 新被除数 ÷ 除数,余数 = 新的被除数 % 除数
- 处理前导 0,逆序输出
⚠️ 适用场景 & 核心注意
- 高精度 ÷ 高精度实现极复杂,入门 / 竞赛优先掌握高精度 ÷ 低精度;
- 除法是高精度运算中唯一从高位计算的类型。
5.2 除法函数实现 🧑💻
long long t = 0; // 余数(开大类型,防止溢出)
// 高精度 ÷ 低精度 函数
void div(int a[], int b, int c[]) {
for (int i = la - 1; i >= 0; i--) {
t = t * 10 + a[i]; // 迭代计算当前被除数
c[i] = t / b; // 计算当前位的商
t %= b; // 更新余数,用于下一位计算
}
// 处理前导0
while (lc > 1 && c[lc - 1] == 0) lc--;
}
完整可运行代码合集
1. 高精度加法 完整代码
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
string x, y;
const int N = 510;
int a[N], b[N], c[N];
void add(int a[], int b[], int c[],int length)
{
for (int i = 0; i < length; i++)
{
c[i] += (a[i] + b[i]);
if (c[i] >= 10)
{
c[i] %= 10;
c[i + 1] = 1;
}
}
}
int main()
{
cin >> x >> y;
int length = max(x.size(), y.size());//真实的长度,最大下标+1
for (int i = 0; i < x.size(); i++)
a[x.size() - 1 - i] = x[i] - '0';
for (int i = 0; i < y.size(); i++)
b[y.size() - 1 - i] = y[i] - '0';
add(a, b, c,length);
if (c[length] )
length++;
for (int i = length - 1; i >= 0; i--)
{
cout << c[i];
}
return 0;
}
2. 高精度减法 完整代码
cpp
#include<iostream>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
string x, y, sw;
const int N = 1000010;
int a[N], b[N], c[N];
int la, lb, lc;
//
//
//void sub(int a[], int b[], int c[])
//{
// for (int i = 0; i < lc; i++)
// {
// if (a[i] < b[i])
// {
// a[i] += 10;
// a[i + 1]--;
// }
// c[i] = (a[i] - b[i]);
// }
//}
void sub(int a[], int b[], int c[])
{
for (int i = 0; i < lc; i++)
{
c[i] += (a[i] - b[i]);
if (c[i] < 0)
{
c[i + 1]--;
c[i] += 10;
}
}
}
int main()
{
cin >> x >> y;
if (x == y)
{
cout << 0 << endl;//都是0的情况
return 0;
}
//la = x.size();
//lb = y.size();
//lc = max(la, lb);
if (y.size() > x.size() || y > x)
{
cout << "-";
sw = x;
x = y;
y = sw;
}
la = x.size();
lb = y.size();
lc = max(la, lb);
for (int i = 0; i < la; i++)
a[la - 1 - i] = x[i] - '0';
for (int i = 0; i < lb; i++)
b[lb - 1 - i] = y[i] - '0';
sub(a, b, c);
//if (c[lc - 1] == 0)
// lc--;
//int flag = 0;//标记最后一个不是0的下标
//for (int i = lc - 1; i >= 0; i++)
//{
// if (c[i] != 0)
// {
// flag = i;
// break;
// }
//}
while (c[lc - 1]==0&&lc>=1)
lc--;
for (int i = lc - 1; i >= 0; i--)
{
cout << c[i];
}
return 0;
}
3. 高精度乘法 完整代码
cpp
#include<iostream>
#include<string>
using namespace std;
const int N = 4000010;
int la, lb, lc, a[N], b[N], c[N];
string x,y;
void mul(int a[], int b[], int c[])
{
for (int i = 0; i < la; i++)
{
for (int j = 0; j < lb; j++)
{
c[i + j] += a[i] * b[j];
}
}
for (int i = 0; i < lc; i++)
{
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
while (lc > 1 && c[lc - 1] == 0)
lc--;
}
int main()
{
cin >> x >> y;
for (int i = 0; i < x.size(); i++)
a[i] = x[x.size() - 1 - i] -'0';
for (int i = 0; i < y.size(); i++)
b[i] = y[y.size() - 1 - i] - '0';
la = x.size();
lb = y.size();
lc = la + lb;
mul(a, b, c);
for (int i = lc-1; i >=0;i--)
cout << c[i];
return 0;
}
4. 高精度除法 (高精度 ÷ 低精度) 完整代码
cpp
#include<iostream>
#include<string>
using namespace std;
int a[100010], c[100010], b;
int la, lc;
string x ;
long long t = 0;
void div(int a[], int b, int c[])
{
for (int i = la-1 ; i >=0 ; i--)//除法是从被除数最大为到最小位, 数组a 从后往前
{
t = t * 10 + a[i];//上一次的余数乘10再加上 a这一位上的数,就是这次的被除数
c[i] = t / b;//得到这一位上的答案
t %= b;//得到下一次的余数
}
while (lc> 1 && c[lc - 1] == 0)//
lc--;
}
int main()
{
cin >> x >> b;//将 被除数数放到string ,除数就是int
la = x.size();
lc = la;//先将结果的位数取最大的可能值
for (int i = 0; i < la; i++)
a[i] = x[la - i - 1] - '0';//存被除数的每一位
div(a, b, c);
for (int i = lc - 1; i >= 0; i--)
{
cout << c[i];
}
return 0;
}
总结
- 核心口诀:字符串存数 → 逆序转数组 → 模拟竖式计算 → 逆序输出
- 核心区别:加减乘从低位计算,除法从高位计算;减法需判大小,乘法长度为两数长度和
- 通用避坑:必须处理进位 / 借位、前导 0,数组开足够大
