文章目录
02_高精度算法
1.高精度加法
1.概念讲解
- 本质:模拟算法
- 当数据类型特别大,各种数据类型都无法存放时,此时就需要高精度算法的加减乘除:
- 什么意思?我们通常所接触到的数据范围一般为109 (int存放) ~ 1018 (long long存放) 级别,当数据的范围达到10100000 (甚至百万次方时),我们所学到的任何数据类型都是无法存放它们的,此时我们就需要用到高精度算法。
- 使用步骤:
- 先用字符串读入这个数,再用数组逆序存储该数的每一位。
- 为什么使用字符串存储数字呢?因为在计算机视角看待一串数字(如 123 ),计算机会将其视作:‘1’(字符1), ‘2’, ‘3’。
- 又为什么使用数组逆序存储?数字在数组中的存储方式其实是逆序的(int arr[ ] = {个位, 十位, 百位, 千位……}) - 从最低位至高位;因此如:123,其每一位在数组中的对应位置,int arr[ ] = {3, 2, 1};),以此方便加法计算的进位处理。
- 利用数组模拟加减乘除的过程
2.P1601 A+B Problem(高精)
题目来源:洛谷
题目链接:P1601 A+B Problem(高精))(如果无法打开可浏览器搜索洛谷,题库输入:P5731)
题目难度:*
题目描述
高精度加法,相当于 a+b problem,不用考虑负数。
输入格式
分两行输入。 a , b ≤ 1 0 500 a,b \leq 10^{500} a,b≤10500。
输出格式
输出只有一行,代表 a + b a+b a+b 的值。
输入输出样例 #1
输入 #1
1 1
输出 #1
2
输入输出样例 #2
输入 #2
1001 9099
输出 #2
10100
说明/提示
20 % 20\% 20% 的测试数据, 0 ≤ a , b ≤ 1 0 9 0\le a,b \le10^9 0≤a,b≤109;
40 % 40\% 40% 的测试数据, 0 ≤ a , b ≤ 1 0 18 0\le a,b \le10^{18} 0≤a,b≤1018。
3.代码思路
**a.**拆分每一位,将其逆序放入数组中
//我们定义一个字符串439,并将其存放在数组中 string s = "4 3 9"; idex 0 1 2 ^ i(假设指针 i 从前向后遍历时指向1) //显而易见,数字字符串在数组中是以逆序的形式存储的 int a[] = { '9', '3', '4'}; idex 0 1 2 //两下标和 2 2 2 ^ j //可得出下标对应关系:j = s.size() - 1 - i //即可得出结论:元素s[i] 对应存放 在数组 a 中的位置为 j,因此 a[j] == s[i];
**b.**模拟计算加法过程,并考虑进位情况
- 对应位相加,再加上进位
- 处理进位:x / 10
- 处理余数:x % 10
//模拟 数组 c 存储 a + b 后的结果 1. int a[] = { 2, 4, 7, 0, 0, 0}; int b[] = { 4, 9, 2, 1, 0, 0}; ^ int c[] = { 6, (6 / 10) == 0,因此进位为0} 2. int a[] = { 2, 4, 7, 0, 0, 0}; int b[] = { 4, 9, 2, 1, 0, 0}; ^ int c[] = { 6, 0(进位) + 13(对应位相加), (13 / 10) == 1,因此进位1}; 3. int a[] = { 2, 4, 7, 0, 0, 0}; int b[] = { 4, 9, 2, 1, 0, 0}; ^ int c[] = { 6, 3, 1 + 9,(10 / 10 == 1,因此进位1)}; 4. int a[] = { 2, 4, 7, 0, 0, 0}; int b[] = { 4, 9, 2, 1, 0, 0}; ^ int c[] = { 6, 3, 0,1 + 0 + 1}; //最终 int c[] = { 6, 3, 0, 2};//2036
4.代码实现
#include<iostream>
using namespace std;
#include <algorithm>
const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;//标记对应数组中的长度
//高精度加法的模板 - c = a + b;
void add(int c[], int a[], int b[])
{
//将最终的计算结果放入 c 中
for(int i = 0; i < lc; i++)
{
c[i] += a[i] + b[i];//注意事项:"+=",因为 c[i] 这个位置可能存在进位,
//所以在进行对位相加时需要把进位加入 c[i] 中 (对位相加,再加上进位)
c[i + 1] += c[i] / 10;//处理进位
c[i] %= 10;//处理余数
}
//处理边界问题,如果 lc 指向位置存在值(说明上步计算结果出现了进位),因此需要实际长度(lc) + 1
if(c[lc]) lc++;
}
int main()
{
//每个数使用字符串的方式读入
string x, y;cin >> x >> y;
//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';//因为 x[i] 中存放的其实是字符,需要 - '0' 变为 int
for(int i = 0; i < lb; i++) b[lb - 1 - i] = y[i] - '0';// i 位置的字符(元素),在数组中所对应的位置:长度 - 1 - i
//2.模拟加法的过程
add(c, a, b);// c = a + b;
//输出结果
for(int i = lc - 1; i >= 0; i--)//因为数字存放在数组的方式是逆序的,因此需要逆向输出
//eg: 123
//数组存储方式:int arr[] = {'3', '2', '1'}; - 以字符类型且 逆序 的方式来存储 字符串123
{
cout << c[i];
}
return 0;
}