高精度算法 cpp


2. 高精度

数据值特别大 , 任何类型都存不了, 用高精度算法加减乘除

  1. 字符串读入这个数

  2. 用数组逆序存储该数的每一位

  3. 利用数组模拟加减乘除运算过程

高精度的本质是模拟算法 , 用代码模拟小学列竖式计算加减乘除的过程


2.1 高精度加法

!洛谷

P1601 高精度加法

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。

思路:

高精度加法原理:

  • 解法: 模拟小学列竖式计算的过程
  1. 先用字符串读入, 拆分每一位, 逆序放在数组中

    eg:

    x = " 4 3 9 " n = 3; x[i] - '0' ->数字

    int a[] = { 9 3 4 }

    n - 1 - i -> 得到数组的下标

  2. 利用数组, 模拟小学列竖式计算加法的过程

    eg:

    复制代码
     a = [ 2, 4, 7, 0, 0, 0 ]
     b = [ 4, 9, 2, 1, 0, 0 ]
     c = [ 6, 3, 0, 2, 0, 0 ]
    1. 对应位相加, 然后加上进位 -> x
    2. 处理进位 -> x/10
    3. 处理余数 -> 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 高精度减法

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。

思路:

高精度减法原理:

  • 解法: 模拟小学列竖式计算的过程
  1. 先用字符串读入, 拆分每一位, 逆序放在数组中

    eg:

    x = " 4 3 9 " n = 3; x[i] - '0' ->数字

    int a[] = { 9 3 4 }

    n - 1 - i -> 得到数组的下标

  2. 利用数组, 模拟小学列竖式计算减法的过程

    eg:

    复制代码
     a = [ 4, 9, 2, 1, 0, 0 ]
     b = [ 2, 4, 7, 0, 0, 0 ]
     c = [ 2, 5, 5, 0, 0, 0 ]
    1. 先比较大小, 然后用较大的数减去较小的数
      1. 直接用字符串比大小会出错
      2. 先比较长度
      3. 再用字典序比较大小
    2. 对应位相减 , 然后处理借位
    3. 如果减的结果 < 0
    4. 往前借一位, 然后这一位加上10
    5. 处理前导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

P1303 A*B Problem - 洛谷

题目背景

高精度乘法模板题。

题目描述

给出两个非负整数,求它们的乘积。

输入格式

输入共两行,每行一个非负整数。

输出格式

输出一个非负整数表示乘积。

输入输出样例 #1

输入 #1

复制代码
1 
2

输出 #1

复制代码
2

说明/提示

每个非负整数不超过 10 2000 10^{2000} 102000。

方法:

高精度乘法原理:

  • 解法: 模拟小学列竖式计算的过程
  1. 先用字符串读入, 拆分每一位, 逆序放在数组中

    eg:

    x = " 4 3 9 " n = 3; x[i] - '0' ->数字

    int a[] = { 9 3 4 }

    n - 1 - i -> 得到数组的下标

  2. 利用数组, 模拟小学列竖式计算乘法的过程

    无进位相乘, 然后相加, 最后处理进位

代码:
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。

思路:

解法: 模拟列竖式计算过程

  1. 字符串读入第一个数 , 拆分每一位 , 逆序放在数组中

  2. 利用数组, 模拟列竖式除法的过程

    1. t = t * 10 + a[i]
    2. t / b = 商
    3. 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;
}

相关推荐
Tisfy2 小时前
LeetCode 1622.奇妙序列:懒更新
数学·算法·leetcode·题解·设计
古一木2 小时前
ai学习笔记
笔记
qyzm2 小时前
AtCoder Beginner Contest 449
数据结构·python·算法·贪心算法
liuyao_xianhui2 小时前
优选算法_判断字符是否唯一_C++
java·开发语言·数据结构·c++·算法·链表
Barkamin2 小时前
希尔排序的简单实现
数据结构·算法·排序算法
Eward-an2 小时前
CKA/CKS认证通关复盘:实验环境搭建避坑指南,版本雷区+高效练习全解析
算法
Flying pigs~~2 小时前
自然语言处理(NLP)开胃小菜
人工智能·算法·自然语言处理·大模型·文本分析处理
Yupureki2 小时前
《C++实战项目-高并发内存池》7.大块内存的申请与释放
服务器·c语言·开发语言·c++·算法·哈希算法
2301_803554522 小时前
c++中的CAS是什么
java·开发语言·c++