高精度计算(加减乘运算)

目录

高精度加法

【题目传送门】

【算法】

【代码】

 高精度减法

【题目传送门】

【算法】

【代码】

高精度乘法

【题目传送门】

【算法】

【代码】

尾声


高精度加法

【题目传送门】

信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1168A+B Problem(高精) - 洛谷https://www.luogu.com.cn/problem/P1601

【算法】

先说最简单的高精度加法,很简单,模拟竖式就行了

例如:123 + 968:

     1 2 3
+   9 6 8
--------1----
  1 0 9 1

现将两个数每一位都相加,最后处理进位(高位加上本位除以 10,本位模 10)

注意,需要从低位到高位相加,因此需要将两个数倒过来,然后从 1 遍历到更大的长度(可以开全局数组,这样初值就都是零,位数小的数高位就都是 0,和位数大的数的高位加起来不变),这样输出就需要倒序输出

可以用一个变量 x 表示上一位的进位,每次 x 变成本次的数除以 10,然后每次答案加上 x,再模 10

最后需要处理一下最高位的进位,也就是判断最终 x 有没有值,如果有,就输出 x

具体请看下方代码

【代码】

(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后为 a 数组和 b 数组,答案存放在 c 数组中)

#include <iostream>
#include <algorithm>
#include <string>
#define N 205
using namespace std;

string s, s1;
int a[N], b[N], c[N], x;

int main() {
	cin >> s >> s1;
	for(int i = 0; i < s.size(); ++i)
		a[s.size() - i] = s[i] - 48;
	for(int i = 0; i < s1.size(); ++i)
		b[s1.size() - i] = s1[i] - 48;
	int l = max(s.size(), s1.size());
	for(int i = 1; i <= l; ++i) {
		c[i] = (a[i] + b[i] + x) % 10;
		x = (a[i] + b[i] + x) / 10;
	}
	if(x)
		cout << x;
	for(int i = l; i > 0; --i)
		cout << c[i];
	cout << endl; 
	
	return 0;
}

 高精度减法

【题目传送门】

信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1169高精度减法 - 洛谷https://www.luogu.com.cn/problem/P2142

【算法】

也很简单,模拟竖式

例如:81 - 79:

     、

     8 1
 -   7 9
----------
        2

注意,这次要判断负数了,就看如果第二个大,就输出一个 '-' ,然后调换两数

也是逆序存储,然后从前往后遍历,遍历到大数的长度,大数减小数

如果发现不够减,则大数的上一位减一,本位减后加 10(借位)

注意,最后要去掉前导 0

具体请看下方代码

【代码】

(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后 a 数组存储大数, b 数组存储小数,答案存放在 a 数组中,f 表示是否答案会是负数)

#include <iostream>
#include <string>
#define N 205
using namespace std;

string s, s1;
int a[N], b[N];
bool f;

int main() {
	cin >> s >> s1;
	if(s.size() < s1.size())
		f = 1;
	else if(s.size() == s1.size())
		for(int i = 0; i < s.size(); ++i)
			if(s[i] < s1[i]) {
				f = 1;
				break;
			}
	if(f) {
		cout << "-";
		swap(s, s1);
	}
	for(int i = 0; i < s.size(); ++i)
		a[s.size() - i] = s[i] - 48;
	for(int i = 0; i < s1.size(); ++i)
		b[s1.size() - i] = s1[i] - 48;
	int l = max(s.size(), s1.size());
	for(int i = 1; i <= l; ++i) {
		a[i] -= b[i];
		if(a[i] < 0) {
			--a[i + 1];
			a[i] += 10;
		}
	}
	while(!a[l] && l > 1)
		--l;
	for(int i = l; i > 0; --i)
		cout << a[i];
	cout << endl; 
	
	return 0;
}

高精度乘法

【题目传送门】

信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1307A*B Problem - 洛谷https://www.luogu.com.cn/problem/P1303

【算法】

模拟竖式

例如:13 * 72:

     1 3

 ×  7 2

-----------

     2 6

  9 1

----------

  9 3 6

首先,也一定是逆序存储

观察后发现第 i 为和第 j 位相乘后被加到了第 (i + j - 1) 位(逆序存储后)

有了这个规律,我们就可以将每种位数的两两组合枚举出来,然后第 (i + j - 1) 位存储 i 和 j 位相乘的结果

注意要处理进位,而进到最高位的时候还需要向更高位 (i + j) 位进位(i + j - 1 + 1 等于 i + j),所以第二层循环结束后要再处理一下最高位的进位

最后还需要去前导 0

具体请看下方代码

【代码】

(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后为 n 数组和 m 数组存储,答案存放在 a 数组中,x 表示进位,len 表示最终答案长度)

#include <iostream>
#include  <algorithm>
#include <string>
#define N 10005
using namespace std;

string s, s1;
int n[N], m[N], a[N], len, x;

int main() {
	cin >> s >> s1;
	for(int i = s.size() - 1; i >= 0; --i)
		n[s.size() - i] = s[i] - 48;
	for(int i = s1.size() - 1; i >= 0; --i)
		m[s1.size() - i] = s1[i] - 48;
	for(int i = 1; i <= s.size(); ++i) {
		x = 0;
		for(int j = 1; j <= s1.size(); ++j) {
			a[i + j - 1] += x + n[i] * m[j];
			x = a[i + j - 1] / 10;
			a[i + j - 1] %= 10;
		}
		a[i + s1.size()] = x;
	}
	len = s.size() + s1.size();
	while(!a[len] && len > 1)
		--len;
	for(int i = len; i >= 1; --i)
		cout << a[i];
	cout << endl;
	
	return 0;
}

尾声

如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!

最后,祝您(您的团队)在 OI 的路上一路顺风!!!

┬┴┬┴┤・ω・)ノ Bye~Bye~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值