算法竞赛基础算法以及模板 算法基础2 高精度


1. 高精度加法

主要思想是将数字存储在一个数组中,再模拟人工加法,其原理可以参考博主之前写过的文章
P1601 A+B Problem(高精)(洛谷题解) 高精度加法

注意点

  • i遍历变量记得要从X.size()-1开始遍历,否则会发生下标越界
  • 记得在最后一次相加的时候判断有没有剩余的进位

判断剩余进位

	// 最后如果 t 还有的话
	if (t)C.push_back(1);

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int N = 10e6 + 10;

vector<int> add(vector<int>& A, vector<int>& B) {
	// 这里传引用会使得运算加快
	int t = 0;

	// 创建结果
	vector<int> C;

	for (int i = 0; i < A.size() || i < B.size(); i++) {
		if (i < A.size())t += A[i];
		if (i < B.size())t += B[i];
		C.push_back(t % 10);

		t /= 10;
	}

	// 最后如果 t 还有的话
	if (t)C.push_back(1);

	return C;
}

int main()
{
	// 初始化
	string a, b;
	vector<int> A, B;

	cin >> a >> b;	// a = "12345"

	// 逆序存进向量
	// 记得i从大小 -1 开始
	for (int i = a.size()-1; i >= 0; i--)A.push_back(a[i] - '0'); // A = [54321],减去字符存进整数
	for (int i = b.size()-1; i >= 0; i--)B.push_back(b[i] - '0');

	// 创建结果
	auto C = add(A, B);

	// 输出
	for (int i = C.size()-1; i >=0; i--)printf("%d", C[i]);
}

2. 高精度减法

注意,我们这里只考虑了A、B都大于0的情况,对于减去一个负数的情况均可以通过加一个判断条件分支转换为题目中的特定类型

注意点

  • 通过直接return A.size()>B.size()的方法来减少判断条件分支
  • 注意在返回最终结果钱需要对前面有0 的结果进行处理,避免出现003这样的状况
  • 如果A - B,B>A,则可以转换为 - ( B - A ),我们在输出的结果钱用printf加上一个负号即可

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

// 判断
bool cmp(vector<int>A, vector<int>B) {
	// 先判断A、B两个数值的大小
	if (A.size() != B.size())return A.size() > B.size();

	// 如果位数相等,从最高位,也就是数字的末尾开始比较
	for (int i = A.size() - 1; i >= 0; i--) 
		// 返回的数大就大,小就小
		if (A[i] != B[i])return A[i] > B[i];

	// 如果最后都没返回,证明两数相等,也返回ture
	return true;
}

// 相减
vector<int>sub(vector<int>A, vector<int>B) {

	vector<int>C;

	// 经过前面的比较, 这里已经默认A比B大了
	for (int i = 0, t = 0; i < A.size(); i++)
	{
		// 如果有借位,t都是正数1
		t = A[i] - t;
		
		if (i < B.size())t -= B[i];

		// 将借位后的数放进C中
		C.push_back((t + 10) % 10);
		
		// 观察t是否借位
		if (t < 0)t = 1;
		else t = 0;
	}

	// 为避免输出 003 这样的计算结果
	// 同时避免没有运算结果,必须保证里面的位数比0大
	while (C.size() > 1 && C.back() == 0)C.pop_back();

	return C;
}

int main()
{
	string a,b;
	cin >> a >> b;

	vector<int> A, B;

	for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0');
	for (int i = b.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');

	// 先判断大小,如果A大于B就直接相减,否则直接输出符号,再输出B - A
	if (cmp(A, B)) 
	{
		auto C = sub(A, B);

		for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]);
	}
	else
	{
		auto C = sub(B, A);

		// 先输出负号,再相减
		printf("-");
		for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]);
	}
	

	return 0;
}

3. 高精度乘法

这里主要考虑一个很大的a(位数在60以上),与一个在int可存储之内的b(位数小于6)进行乘法计算,并将结果输出(并不考虑使用大数乘法的方式)

注意

  • 记得除去前导0
  • 避免123456*0=00000的情况
  • 只要t不是0就一直循环

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;


// 相乘,传入引用加快计算
vector<int>mul(vector<int>&A, int b) {
	vector<int>C;

	for (int i = 0, t = 0; i < A.size() || t ; i++)
	{
		if (i < A.size())t += A[i] * b;
		C.push_back(t % 10);
		t /= 10;
	}

	// 除去前导0
	while (C.back() == 0 && C.size() > 1)C.pop_back();

	return C;
}

int main()
{
	string a;
	int b;

	cin >> a >> b;

	vector<int>A;

	// 记得减去字符0
	for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i]-'0');

	auto C = mul(A, b);

	for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]);

	return 0;
}

4. 高精度除法

注意,这里考虑的情况和前面的高精度乘法类似,都是一个高精度的整数除以一个低精度的整数

注意点

  • 我们这里要算除法后的余数
  • 余数的计算我们用r,使用传引用的方式
  • 注意为了和前面的模板保持一致,我们还是使用原来的方法计算,再在最后把结果倒转
  • 注意reverse()函数在algorithm包里面
  • 注意reverse的函数原型reverse(开始坐标,结束坐标)


写在最后

各位看官,都看到这里了,麻烦动动手指头给博主来个点赞8,您的支持作者最大的创作动力哟! <(^-^)>
才疏学浅,若有纰漏,恳请斧正
本文章仅用于各位同志作为学习交流之用,不作任何商业用途,若涉及版权问题请速与作者联系,望悉知

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值