2. 高精度
数据值特别大 , 任何类型都存不了, 用高精度算法加减乘除
-
字符串读入这个数
-
用数组逆序存储该数的每一位
-
利用数组模拟加减乘除运算过程
高精度的本质是模拟算法 , 用代码模拟小学列竖式计算加减乘除的过程
2.1 高精度加法
!洛谷
P1601 高精度加法
题目背景
本题是高精度加法的模板题。
题目描述
给定两个非负整数 a , b a,b a,b,求它们的和。不用考虑负数。
输入格式
输入共两行,每行一个非负整数,分别为 a , b a,b a,b。
输出格式
输出一行一个非负整数,表示 a + b a+b a+b 的值。
输入输出样例 #1
输入 #1
1 1输出 #1
2输入输出样例 #2
输入 #2
1001 9099输出 #2
10100说明/提示
对于 20 % 20\% 20% 的测试数据, a , b ≤ 10 9 a,b \le 10^9 a,b≤109;
对于 40 % 40\% 40% 的测试数据, a , b ≤ 10 18 a,b \le 10^{18} a,b≤1018;
对于 100 % 100\% 100% 的测试数据, 0 ≤ a , b ≤ 10 500 0\le a,b \le 10^{500} 0≤a,b≤10500。
思路:
高精度加法原理:
- 解法: 模拟小学列竖式计算的过程
-
先用字符串读入, 拆分每一位, 逆序放在数组中
eg:
x = " 4 3 9 " n = 3; x[i] - '0' ->数字
int a[] = { 9 3 4 }
n - 1 - i -> 得到数组的下标
-
利用数组, 模拟小学列竖式计算加法的过程
eg:

a = [ 2, 4, 7, 0, 0, 0 ] b = [ 4, 9, 2, 1, 0, 0 ] c = [ 6, 3, 0, 2, 0, 0 ]- 对应位相加, 然后加上进位 -> x
- 处理进位 -> x/10
- 处理余数 -> x%10
代码:
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N] , b[N] , c[N];
int la, lb, lc;
//高精度函数的模板
void add(int c[], int a[], int b[])
{
for(int i = 0; i < lc; i++)
{
c[i] += a[i] + b[i];//对应数相加, 再加上进位
c[i + 1] += c[i] / 10;//处理进位
c[i] %= 10;//处理余数
}
if(c[lc]) lc++; //处理特殊情况:最高位进位, eg:99+1 = 100, 但打印时只打印 00, lc++ 使得1能打印出来
}
int main()
{
string x, y;
cin >> x >> y;
//拆分每一位, 逆序放在数组中
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';
//模拟加法的过程
add(c, a, b);// c = a + b
//输出结果
for(int i = lc - 1; i>= 0; i-- )cout << c[i];
return 0;
}
2.2 高精度减法
!洛谷
P2142 高精度减法
题目描述
给定两个正整数 a , b a,b a,b,求 a − b a-b a−b 的值。
输入格式
输入共两行,每行一个正整数,分别为 a , b a,b a,b。
输出格式
输出一行一个整数,表示 a − b a-b a−b 的值。
如果 a − b < 0 a-b<0 a−b<0,请输出负号。
输入输出样例 #1
输入 #1
2 1输出 #1
1说明/提示
对于 20 % 20\% 20% 的数据, a , b a,b a,b 在
long long类型的存储范围内;对于 100 % 100\% 100% 的数据, 0 < a , b ≤ 10 10086 0<a,b\le 10^{10086} 0<a,b≤1010086。
思路:
高精度减法原理:
- 解法: 模拟小学列竖式计算的过程
-
先用字符串读入, 拆分每一位, 逆序放在数组中
eg:
x = " 4 3 9 " n = 3; x[i] - '0' ->数字
int a[] = { 9 3 4 }
n - 1 - i -> 得到数组的下标
-
利用数组, 模拟小学列竖式计算减法的过程
eg:

a = [ 4, 9, 2, 1, 0, 0 ] b = [ 2, 4, 7, 0, 0, 0 ] c = [ 2, 5, 5, 0, 0, 0 ]- 先比较大小, 然后用较大的数减去较小的数
- 直接用字符串比大小会出错
- 先比较长度
- 再用字典序比较大小
- 对应位相减 , 然后处理借位
- 如果减的结果 < 0
- 往前借一位, 然后这一位加上10
- 处理前导0
- 先比较大小, 然后用较大的数减去较小的数
代码:
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 +10;
int a[N], b[N], c[N];
int la, lb, lc;
//比大小
bool cmp(string& x, string& y){
//先比较长度
if(x.size() != y.size()) return x.size() < y.size();
//再按照字典序的方式比较
return x < y;
}
//高精度减法的模板
void sub(int c[], int a[], int b[]){
for(int i = 0; i < lc; i++){
c[i] += a[i] - b[i]; // 对应位相减, 然后处理借位
if(c[i] < 0){
c[i] += 10;
c[i+1] -= 1; //借位
}
}
//处理前导0
while(lc > 1 && c[lc-1] == 0) lc--;
}
int main(){
//读入字符串
string x, y;
cin >> x >> y;
//比大小
if(cmp(x,y)){
swap(x, y);
cout << '-';
}
//1. 拆分每一位, 然后逆序放在数组
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(c, a, b);
//输出结果
for(int i = lc - 1; i >= 0; i--) cout << c[i];
return 0;
}
2.3 高精度乘法
!洛谷
P1303 A*B Problem
题目背景
高精度乘法模板题。
题目描述
给出两个非负整数,求它们的乘积。
输入格式
输入共两行,每行一个非负整数。
输出格式
输出一个非负整数表示乘积。
输入输出样例 #1
输入 #1
1 2输出 #1
2说明/提示
每个非负整数不超过 10 2000 10^{2000} 102000。
方法:
高精度乘法原理:
- 解法: 模拟小学列竖式计算的过程
-
先用字符串读入, 拆分每一位, 逆序放在数组中
eg:
x = " 4 3 9 " n = 3; x[i] - '0' ->数字
int a[] = { 9 3 4 }
n - 1 - i -> 得到数组的下标
-
利用数组, 模拟小学列竖式计算乘法的过程
无进位相乘, 然后相加, 最后处理进位

代码:
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
int a[N], b[N], c[N];
int la, lb, lc;
//高精度乘法模板
void mul(int c[], int a[], int b[])
{
//无进位相乘然后相加
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()
{
//输入
string x, y;
cin >> x >> y;
//逆序输入数组
la = x.size(); lb = y.size(); lc = la + lb;//注意乘法lc最大长度为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';
mul(c, a, b);//c=a*b;
//输出
for(int i = lc - 1; i >= 0; i--) cout << c[i];
return 0;
}
2.4 高精度除法(高精度/低精度)
!洛谷
P1480 A/B Problem(高精度除法Ⅰ)
P1480 A/B Problem(高精度除法Ⅰ) - 洛谷
题目描述
输入两个整数 a , b a,b a,b,输出它们的商。
输入格式
两行,第一行是被除数,第二行是除数。
输出格式
一行,商的整数部分。
输入输出样例 #1
输入 #1
10 2输出 #1
5说明/提示
0 ≤ a ≤ 10 5000 0\le a\le 10^{5000} 0≤a≤105000, 1 ≤ b ≤ 10 9 1\le b\le 10^9 1≤b≤109。
思路:
解法: 模拟列竖式计算过程
-
字符串读入第一个数 , 拆分每一位 , 逆序放在数组中
-
利用数组, 模拟列竖式除法的过程
- t = t * 10 + a[i]
- t / b = 商
- t % b = 余数
代码:
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
typedef long long LL;
int a[N] , c[N];
int la, lc;
//高精度除以低精度的模板
void sub(int c[], int a[], int b)
{
LL t = 0;// 标记每次除完之后的余数
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--;
}
int main()
{
//读数
string x;
int b;
cin >> x >> b;
//逆序输入第一个数
la = x.size();
for(int i = 0 ; i < la ; i++) a[la - i - 1] = x[i] - '0';
//模拟除法
lc = la;
sub(c, a, b); // c = a / b
for(int i = lc - 1; i >= 0; i--) cout << c[i];
return 0;
}