高精度模拟

     又是不知道多少天地学习,真是忙忙碌碌,忙忙碌碌!最近很多人问到我一个求阶乘之和的题,本来俩个for循环搞定的事,确实不难,然而阶乘的范围有点大,大到什么程度呢?大到了一个long long 都装不下!这里就要引入我们的算法高精度了。

        要解决这道题我们首先需要学会高精乘法,和高精加法。

        直接上代码:

        A+B问题:

        第一步:将俩个long long存不下的数用俩个字符串a,b吸入,接着我们还需要俩个数组,用l,和r,来表示。

string a, b;//俩个数
int l[505],r[505],s[505];

        第二步:将a和b中的数用逆序(方便后面做处理,从个位开始加),转化到数组l和r中去

for (int i = 0; i < la; i++) {
		l[i] = a[la - i-1] - '0';
		//转化
	}
	for (int i = 0; i < lb; i++) {
		r[i] = b[lb - i - 1] - '0';
	}

第三步:进行加法运算,(细节都在带码中了)

ma = max(la, lb) ;//确定上线,选取最大的那个
	for (int i = 0; i < ma; i++) {
		s[i] += (l[i] + r[i]);//注意是加等于
		s[i + 1] = s[i] / 10;//关键:如果大于9就说明需要进位了,这也是上一部需要+=的原因
		s[i] = s[i] % 10;//将个位保留
	}

最后:输出,注意因为输出是从末尾输出的,所以输出的边界很重要,一定要除去前导0

while (s[ma] == 0&&ma>0)ma--;//去除前导0;
	for (int i = ma; i > -1; i--) {
		cout << s[i];
	}

A*B问题

前面的处理方法和加法都差不多,我就不做过多的叙说,这里主要讲一下计算的步骤和输出需要注意的地方

for (int i = 1; i <=la; i++) {//双重循环,每一位都要相乘
		for (int j = 1; j <= lb; j++) {//每一位乘完再加
			c[i + j - 1] += m[i] * n[j];//注意+=,理解一下他的意思
			c[i + j] += c[i + j - 1] / 10;//注意+=
			c[i + j - 1] %= 10;
		}
	}

主体都能理解,但这里最需要理解的是一个数的第i位乘第j位就会变成i+j-1位,

        

        最后就是输出了

//去除前导0
	int q = la + lb;
	while (c[q] == 0 && q > 1)q--;
	//输出
	for (int i = q; q > 0; q--) {
		cout << c[q];
	}

阶乘的和

终于来到了大boss

#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1e4;
int a[N], b[N];
int main() {
	int n;
	cin >> n;
	a[1] = 1; b[1] = 1;
	for (int i = 2; i <= n; i++) {
		for (int j = 1; j<=100; j++) {
			a[j] *= i;//a[j]相当于i的阶乘
		}
		//转化
		for (int j = 1; j <=100; j++) {
			if (a[j] > 9) {
				int p = a[j] / 10;
				a[j + 1] += p;
				a[j] %= 10;
			}
		}//相加
		for (int j = 1; j <= 100; j++) {
			b[j] += a[j];
			if (b[j] > 9) {
				int p = b[j] / 10;
				b[j + 1] += p;
				b[j] %= 10;
			}
		}
	}
	//输出
	int m= 2 * n;
	while (b[m] == 0 && m > 1)m--;//去除前导0
	for (int i = m; i > 0; i--) {
		printf("%d", b[i]);
	}

	return 0;

}

这里再附加一道高精度减法,大家可以去思考一下再来看看我的代码:

答案代码奉上:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string a, b;
int r[20000], l[20000],c[20000];
int main() {
	cin >> a >> b;
	int m;
	int mark;
	int la = a.length(); int lb = b.length();
	if (la >lb||(la==lb&&a>b)||a==b) {//string类型可以直接比大小,但只有等长的时候。才会准确
		mark=0;
		m = la;
	}
	else {
		mark = 1;
		m = lb;
	}//比较俩个数的大小
	for (int i = 0; i < la; i++) {//判断是否需要加-号,重点
		l[i] = a[la - i - 1] - '0';
	}
	for (int i = 0; i < lb; i++) {
		r[i] = b[lb - i - 1]-'0';
		}
	if (!mark) {
		for (int i = 0; i < m; i++) {
			if (l[i] >= r[i]) {
				c[i] = l[i] - r[i];
			}
			else {
				c[i] = l[i] + 10 - r[i];//借位
				l[i + 1] -= 1;
			}
		}
	}
	else {
		for (int i = 0; i < m; i++) {
			if (r[i] >= l[i]) {
				c[i] = r[i] - l[i];
			}
			else {
				c[i] = r[i] + 10 - l[i];
				r[i + 1] -= 1;
			}
		}
	}
	m = m - 1;
	while (c[m] == 0&&m>0)m--;//处理前导0;
	if(!mark){
		for (int i = m; i > -1; i--) {
			cout << c[i];
		}
	}
	else {
		putchar('-');
		for (int i = m; i > -1; i--) {
			cout << c[i];
		}
	}
	return 0;

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值