Section 4.高精度

一、高精度加法(正数+正数)

  1. 大整数的存储:将个位存在a[0],十位存在a[1],百位存在a[2]......,方便进位,因为如果按照正序存储的话,最高位需要进位时,所有数字都需要向右移一位
  2. 模拟竖式加法

vector::size()函数的用法:假设有vector<>a,则a.size()返回数组a的长度

vector::push_back()函数的用法:函数将一个新的元素加到vector<>的最后面,位置为当前最后一个元素的下一个元素,参数为要插入的值

#include <iostream>
#include <vector>
using namespace std;
vector<int> add(vector<int>A, vector<int>B)
{
	vector<int>C;
	int t = 0;  //进位标记
	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;  //计算进位
	}
	if (t)
		C.push_back(1);  //如果加完后仍有进位,则加一位最高位1
	return C;
}
int main()
{
	string a, b;
	vector<int>A, B;
	cin >> 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');  //把数字逆序存放
	auto C = add(A, B);
	for (int i = C.size() - 1; i >= 0; i--)
		printf("%d", C[i]);  //再逆序输出
	return 0;
}

二、 高精度减法(正数-正数)

  1. 大整数的存储:同上
  2. 模拟竖式减法:同位相减如果小于0,则再加上10,后一位减去1
  3. 注意考虑结果可能为负数:如果a-b>0,直接计算就行;如果a-b<0,则先计算b-a,再加负号

vector::back()函数的用法:访问vector<>中的最后一个元素

vector::pop_back()函数的用法:取消vector<>中最后一个元素的地址映射。效果:使用.size()时会忽略该元素,但是如果使用指针,会发现该元素仍然存在,说明该函数没有真正把内存里面的数值删掉

#include <iostream>
#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()); 
	else  //位数相同时
	{
		for (int i = A.size() - 1; i >= 0; i--)
		{
			if (A[i] != B[i])
				return (A[i] > B[i]);
		}
		return true;
	}
}
vector<int> sub(vector<int>A, vector<int>B)
{
	vector<int>C;
	int t = 0;  //借位标记
	for (int i = 0; i < A.size(); i++)
	{
		t = A[i] - t;
		if (i < B.size())
			t -= B[i];  //因为B的位数一定小于等于A,所以要考虑i超过了B的最高位时的情况
		C.push_back((t + 10) % 10);  //同时考虑了需要借位与不需要借位时的情况
		if (t < 0)
			t = 1;  //向前借位
		else
			t = 0;
	}
	while (C.size() > 1 && C.back() == 0)  //去除前导0,但是结果为0的时候不能把最后一个0也去掉,所以以位数来判断是否结果为0
		C.pop_back();
	return C;
}
int main()
{
	string a, b;
	vector<int>A, B;
	cin >> 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');  //把数字逆序存放
	if (cmp(A, B))  //A>B
	{
		auto C = sub(A, B);
		for (int i = C.size() - 1; i >= 0; i--)
			printf("%d", C[i]);  //再逆序输出
	}
	else  //A<B
	{
		auto C = sub(B, A);
		cout << "-";  //先输出负号
		for (int i = C.size() - 1; i >= 0; i--)
			printf("%d", C[i]);  //再逆序输出
	}
	return 0;
}

 三、高精度乘法(高精度*低精度)

  1. 大整数的存储:同上
  2. 模拟竖式乘法:将高精度上的每一位数乘以整个低精度数(和小学竖式乘法略有不同),该位就为结果模10,进位就为结果除10
#include <iostream>
#include <vector>
using namespace std;
vector<int>mul(vector<int>A, int b)
{
	vector<int>C;
	int t = 0;  //进位标记
	for (int i = 0; i < A.size() || t; i++)  //“或t”是考虑到最后一位也可能有进位
	{
		if (i < A.size())  //最后一位进位时直接跳过此步
			t += A[i] * b;
		C.push_back(t % 10);  //当前位
		t /= 10;  //进位
	}
	while (C.size() > 1 && C.back() == 0)  //去除前导0,但是结果为0的时候不能把最后一个0也去掉,所以以位数来判断是否结果为0
		C.pop_back();
	return C;
}
int main()
{
	string a;
	int b;
	cin >> a >> b;
	vector<int>A;
	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;
}

 四、高精度除法(高精度除低精度)

  1. 大整数的存储:同上
  2. 模拟竖式除法:递归

reverse(first,last)函数的用法:该函数在头文件<algorithm>中,作用是反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),该函数没有返回值。

vector::begin()函数的用法:该函数返回一个指向vector的第一个元素的迭代器

vector::end()函数的用法:该函数返回一个指向vector的past-the-end元素的迭代器,它不指向最后一个元素,因此要获取我们可以使用的最后一个元素,应该用vector::end()-1

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>div(vector<int>A, int b, int& r)  //通过引用传回r
{
	vector<int>C;
	r = 0;
	for (int i = A.size() - 1; i >= 0; i--)
	{
		r = r * 10 + A[i];  //这一位的最终被除数等于上一位的余数乘10加上这一位的被除数
		C.push_back(r / b);
		r %= b;
	}
	reverse(C.begin(), C.end());
	while (C.size() > 1 && C.back() == 0)  //去前导0
		C.pop_back();
	return C;
}
int main()
{
	string a;
	int b;
	cin >> a >> b;
	vector<int>A;
	for (int i = a.size() - 1; i >= 0; i--)
		A.push_back(a[i] - '0');  //逆序存储
	int r;  //余数
	auto C = div(A, b, r);
	for (int i = C.size() - 1; i >= 0; i--)
		printf("%d", C[i]);  //逆序输出
	cout << endl << r << endl;  //输出余数
	return 0;
}

五、配套练习

Acwing791icon-default.png?t=LBL2https://www.acwing.com/problem/content/793/Acwing792icon-default.png?t=LBL2https://www.acwing.com/problem/content/794/Acwing793icon-default.png?t=LBL2https://www.acwing.com/problem/content/795/Acwing794icon-default.png?t=LBL2https://www.acwing.com/problem/content/796/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值