高精度算法及运用其解决阶乘之和

C++高精度算法

本人刚开始学习c++,在洛谷网站刷题时遇到用高精度算法计算阶乘之和P1009时遇到了困惑,于是学习了这种算法,以此记录自己的学习过程。

高精度算法存在的必要性

我们有时在用c++做运算时,例如50!,数据的运算结果超出了int、double、long long、undesigned long long的范围,使数据溢出,这时便需要高精度算法来解决。

高精度算法

基本原理

此处为我的个人理解,勿喷。

基本原理就是将一个大数的个位、十位、百位等有序地存储在一个整型数组中,然后通过操作整型数组来进行按位运算

高精度加法

大体思路

参考小学学习的竖式运算的法则,个位与个位相加,超过10进1,十位与十位相加,超过10进1,此时不要忘记个位时的进位,以此类推。

正常情况下,例如123,百位数字1对应a[0],数字的最高位对应数组的最小下标,由于考虑到进位的影响,这样就会导致在运算时很不方便,因此就可以用倒序存储的方式使数字的最低位对应数组的最小下标,即个位数字3对应a[0]。

代码

倒叙的代码

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int a[1000] = {}, b[1000] = {}, c[2000] = {};//a[1000],b[1000]分别用来存储倒序后的数字
	string a1, b1;
	cin >> a1 >> b1;//将两个数字以字符串的形式输入
	int m = max(a1.length(), b1.length());//用来接收相加后的长度,如果最高位有进位,m还需+1
	for (int i = 0; i < a1.length(); i++)//倒叙的代码
	{
		a[a1.length() - 1 - i] = a1[i]-'0';
	}
	for (int i = 0; i < b1.length(); i++)
	{
		b[b1.length() - 1 - i] = b1[i]-'0';
	}

高精度加法代码,接上。

for (int i = 0; i < max(a1.length(), b1.length()); i++)//高精度加法的核心代码
	{
		c[i] += a[i] + b[i];//按位相加
		c[i + 1] = c[i] / 10;//判断有无进位,有进位的话,c[i+1]+=1;
		c[i] %= 10;//判断取余后c[i]的最终结果
	}
	if (c[max(a1.length(), b1.length())] != 0)//用来判断相加后的总长度是否增加
		m++;
	for (int i=m - 1; i >= 0; i--)//完成后再倒序输出,即为最终结果
	{
		cout<<c[i];
	}
	return 0;
}

高精度乘法

大体思路

与加法有相似之处,按位相乘,但是需要注意的是不同位相乘对结果的作用不一样,需要通过举例子找下下标的规律。另外还有一点不同就是加法的进位最多就是1,而乘法则不一定。

代码

倒序代码

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int a[1000] = {}, b[1000] = {}, c[2000] = {};//a[1000],b[1000]分别用来存储倒序后的数字
	string a1, b1;
	cin >> a1 >> b1;//将两个数字以字符串的形式输入
	int n = a1.length()+ b1.length();//两个数相乘最终的位数不会超过两数的位数之和
	for (int i = 0; i < a1.length(); i++)//倒序的主要代码
	{
		a[a1.length() - 1 - i] = a1[i]-'0';
	}
	for (int i = 0; i < b1.length(); i++)
	{
		b[b1.length() - 1 - i] = b1[i]-'0';
	}

高精度乘法代码,接上。

for (int i = 0; i < a1.length(); i++)//核心部分:首先按位相乘,暂时不进位,与加法有所差别
	{
		for (int j = 0; j < b1.length(); j++)
		{
			c[i + j] += a[i] * b[j];//找下标之间的关系十分重要
		}
	}
	for (int i = 0; i < n; i++)//按位相乘后对进位进行处理,本位若大于等于10将商加到下一位,余数则作为新的本位
	{
		if (c[i] >= 10)
		{
			c[i + 1] += c[i] / 10;
			c[i] %= 10;
		}
	}
	while (c[n] == 0)//除去多余的前导
	{
		n--;
	}
	for (int i = n; i >= 0; i--)//倒序输出即为所得
	{
		cout << c[i];
	}
	return 0;
}

阶乘之和的代码

题目的链接在文章的开头处,代码如下。

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	int n;
	int a[100], b[100];
	memset(a, 0, sizeof(a));//对数组赋初值
	memset(b, 0, sizeof(b));
	a[0] = 1;
	b[0] = 1;
	int i, j;
	cin >> n;
	for ( i = 2; i<=n ; i++)
	{
		for ( j = 0; j < 100; j++)//高精度乘法
			a[j] *= i;
		for ( j = 0; j < 100; j++)
		{
			if (a[j] >= 10)
			{
				a[j + 1]+= a[j] / 10;
				a[j] %= 10;
			}
			b[j] += a[j];//高精度加法
			if (b[j] >= 10)
			{
				b[j + 1]+=1;
				b[j] -= 10;
			}
		}
	}
	for (j = 99; j >= 0; j--)
	{
		if (b[j])
		{
			break;
		}
	}
	for (i = j; i >= 0; i--)
	{
		cout << b[i];
	}
	system("pause");
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值