c++——爆肝7000字的高精度算法大合集&&实战应用

大家好,我是屁孩君,今天跟大家来分享一下高精度!
省流:直接康完整代码


前言

在学习c++的路程中,我们总会遇到有些题的数据范围超出了int,long ,long long…这时我们就需要使用大招:高精度加法!!!


提示:以下是本篇文章正文内容

算法

高精度呢,输入时是使用字符串的,再把它存入输组。
高精度加法:
将两个字符串输入,逆序存入数组,然后使用for循环逐位相加,相加的结果存入c数组,再进位,最后逆序输出。比如说142+256
在这里插入图片描述
用高精度呢,就变成了这样!
在这里插入图片描述
高精度减法:
将两个字符串读入,逆序存入数组,使用for循环逐位相减,将差存入c数组,不够就向后一位借,再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出
比如说456-142。
在这里插入图片描述
我们使用高精度呢,就变成了this
在这里插入图片描述
当然了,还有一种要借位的就有大家去自行模拟了!

高精度乘单精度:单精度不超过10000(题目所示)
将一个字符串读入(因为另一个数是单精度,不用字符串),逆序存入数组,然后把单精度的数当成一个数,用高精度的每一位去乘单精度,把积存入c数组,再进位(注:一个高精度的数乘一个小于等于10000的数,即最多多4位,切记不要忘记去进那四位),再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出
比如说:99910
在这里插入图片描述
使用高精度后,摇身一变
因为这压根就没变所以我就先不列了(趁机偷懒
但是大家发现了吗,其实高精度几乎差不多,只是轻微的改变了一下。
高精度除法:
使用for循环重复输出就ok了细分的简单。
高精乘:
将两个字符串读入,逆序存入数组,a数组的每一位都与b[j]乘,积错位存入c数组,比如说一个乘数的下标是0,另一个乘数的下标是3,那他们的积的下标则为0+3,也就要存入c[3]中,然后进位,再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出
比如说456
789
在这里插入图片描述使用高精度算法后就变成了this
在这里插入图片描述
简单来说就是乘的方向变了一下。


分步完成

高精度加法:
1:输入字符串。

cin>>s1>>s2;

2: 将字符串逆序存储到数组里。

for(int i=0;i<s1.size();i++)
{
	a[s1.size()-(i+1)]=s1[i]-'0';
}
for(int i=0;i<s2.size();i++)
{
	b[s2.size()-(i+1)]=s2[i]-'0';
}

3:把两个数组值相加

for(int i=0;i<len;i++)
{
	c[i]=a[i]+b[i];
}

4:逆序输出

for(int i=len-1;i>=0;i--)cout<<c[i];

高精度减法:
1:判断结果正负

if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2))
{
	q='-';//如果是负数得把符号改成-
	swap(s1,s2);//交换位置
}

2:逆序存入数组

for(int i=0;i<s1.size();i++)
{
	a[i]=s1[s1.size()-i-1]-'0';
}
for(int i=0;i<s2.size();i++)
{
	b[i]=s2[s2.size()-i-1]-'0';
}

3:从左到右逐个减

for(int i=0;i<s1.size();i++)
{
	if(a[i]<b[i])
	{
		a[i+1]-=1;
		a[i]+=10;
	}
	c[i]=a[i]-b[i];
}

4:逆序输出

for(int i=len-1;i>=0;i--)if(c[i]!=0){//重要代码,找出不是0的位置
	p=i;break;
}
for(int i=p;i>=0;i--)cout<<c[i];//逆序输出

高精度乘单精度:
1:将字符串逆序存入数组

	cin>>s1>>b;
	for(int i=0;i<s1.size();i++)
	{
		a[i]=s1[s1.size()-i-1]-'0';
	}

2:逐位乘

	for(int i=0;i<s1.size();i++)
	{
		a[i]*=b;//把b看成一个数,将b与a数组逐位相乘
	}

3:逐位进位

	for(int i=0;i<s1.size()+4;i++)
	{
		if(a[i]>=10)
		{
			a[i+1]+=a[i]/10;//满十进一
			a[i]%=10;
		}
	}

4:判断几位数,从那个位置开始逆序输出

for(int i=s1.size()+3;i>=0;i--)
	{
		if(a[i]!=0)
		{
			p=i;//记录位置
			break;//记得终止循环
		}
	}

5:逆序输出

for(int i=p;i>=0;i--)cout<<a[i];

高精度除法:
1:输出整数部分

cout<<a/b<<'.';

2:反复循环输出小数部分

for(int i=0;i<n;i++)
	 {
	 	t*=10;
	 	cout<<t/b;
	 	t=t%b;
	 }

高精度乘:
1:将两个字符串逆序存入数组a与数组b

	for(i=0;i<s1.size();i++)
	{
		a[i]=s1[s1.size()-i-1]-'0';
	}
	for(i=0;i<s2.size();i++)
	{
		b[i]=s2[s2.size()-i-1]-'0';
	}

2:用a[i]去乘以b[j]

这个大家都会吧!

3:错位加到c数组里

	c[i+j]=c[i+j]+a[i]*b[j];

4:从数组的最后面往前面遍历,找到第一个非零元素,简单的来讲就是第一个有数的位置

for(i=s1.size()+s2.size()-1;i>=0;i--)
	{
		if(c[i]!=0){
			p=i;
			break;
		}
	}

5:逆序输出

for(int i=len-1;i>=0;i--)cout<<c[i];

完整代码

高精度加法:

#include<bits/stdc++.h>
using namespace std;
string a1,b1;
int a[250],b[250],c[500];
int main()
{
	cin>>a1>>b1;
	for(int i=0;i<a1.size();i++)
	{
		a[i]=a1[a1.size()-i-1]-'0';
	}
	for(int i=0;i<b1.size();i++)
	{
		b[i]=b1[b1.size()-i-1]-'0';
	}
	int len=max(a1.size(),b1.size());
	for(int i=0;i<len;i++)
	{
		c[i]+=a[i]+b[i];
		if(c[i]>=10)
		{
			c[i+1]+=c[i]/10;
			c[i]%=10;
		}
	}
	if(c[len]!=0)len++;
	for(int i=len-1;i>=0;i--)cout<<c[i];
	return 0;
}

高精度减法:

#include<bits/stdc++.h>
using namespace std;
string a1,b1;
int a[250],b[250],c[250];
char q='+';
int main()
{
	int p=0;
	cin>>a1>>b1;
	if(a1.size()<b1.size()||(a1.size()==b1.size()&&a1<b1))
	{
		q='-';
		swap(a1,b1);
	}
	for(int i=0;i<a1.size();i++)
	{
		a[i]=a1[a1.size()-i-1]-'0';
	}
	for(int i=0;i<b1.size();i++)
	{
		b[i]=b1[b1.size()-i-1]-'0';
	}
	for(int i=0;i<a1.size();i++)
	{
		if(a[i]<b[i])
		{
			a[i+1]-=1;
			a[i]+=10;
		}
		c[i]=a[i]-b[i];
	}
	if(q=='-')cout<<'-';
	for(int i=a1.size();i>=0;i--)
	{
		if(c[i]!=0)
		{
			p=i;
			break;
		}
	}
	for(int i=p;i>=0;i--)cout<<c[i];
	return 0;
}

高精度乘单精度:

#include<bits/stdc++.h>
using namespace std;
string s1;
int a[250],b;
int main()
{
	int p;
	cin>>s1>>b;
	for(int i=0;i<s1.size();i++)
	{
		a[i]=s1[s1.size()-i-1]-'0';
	}
	for(int i=0;i<s1.size();i++)
	{
		a[i]*=b;
	}
	for(int i=0;i<s1.size()+4;i++)
	{
		if(a[i]>=10)
		{
			a[i+1]+=a[i]/10;
			a[i]%=10;
		}
	}
	for(int i=s1.size()+3;i>=0;i--)
	{
		if(a[i]!=0)
		{
			p=i;
			break;
		}
	}
	for(int i=p;i>=0;i--)cout<<a[i];
	return 0;
}

高精度除法:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int a,b,n,t;
	cin>>a>>b>>n;
	t=a%b;
	cout<<a/b<<'.';
	 for(int i=0;i<n;i++)
	 {
	 	t*=10;
	 	cout<<t/b;
	 	t=t%b;
	 }
	 return 0;
 } 

高精度乘:

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[250],b[250],c[500],i,j;
int main()
{ 
	int p;
	cin>>s1>>s2;
	for(i=0;i<s1.size();i++)
	{
		a[i]=s1[s1.size()-i-1]-'0';
	}
	for(i=0;i<s2.size();i++)
	{
		b[i]=s2[s2.size()-i-1]-'0';
	}
	for(i=0;i<s1.size();i++)
	{
		for(j=0;j<s2.size();j++)
		{
			c[i+j]=c[i+j]+a[i]*b[j];
			if(c[i+j]>=10)
			{
				c[i+j+1]+=c[i+j]/10;
				c[i+j]%=10;
			}
		}
		
	}
	for(i=s1.size()+s2.size()-1;i>=0;i--)
	{
		if(c[i]!=0){
			p=i;
			break;
		}
	}
	for(i=p;i>=0;i--)
	{
		cout<<c[i];
	}
	return 0;
} 

实战应用

题目描述
求2+22+222+…+222…*2的和是多少?最后一项有多少2相乘由键盘读入的n决定(1<=n<=100)!

比如:n=3,那么s=2+22+22*2=14!

输入
从键盘读入一个整数n(1<=n<=100)

输出
输出求出的和

样例
输入
3
输出
14
这题呢其实就是把高精度加法和乘法融合在了一起,我们呢就开两个数组,一个是哪来存储每次加的值的,一个是用来存和的,每次把存加的值的数组的每个元素都成2。
1.将a数组的a[0]元素设为1,不然怎么乘都是0。

a[0]=1;

2.将储存每次加的值的数组每位上都乘二

for(int j=0;j<k;j++)
{
	a[j]*=2;
}

3.将储存每次加的值的数组进位

for(int j=0;j<k;j++)
{
	if(a[j]>=10){
	a[j+1]+=a[j]/10;
	a[j]%=10;
	}
}

4.判断位数,如果第k位不为零,就将数组位数加一。

if(a[k]!=0)k++;

5.将存和的数组加上存储每次加的值的数组的值

for(int j=0;j<len;j++)
{
	b[j]+=a[j];
	if(b[j]>=10)
	{
		b[j+1]+=b[j]/10;
		b[j]%=10;
	}
}

6.逆序输出

for(int i=len-1;i>=0;i--)
{
	cout<<b[i];
}

话不多说,直接上完整代码

#include<bits/stdc++.h>
using namespace std;
int a[5000];
int b[5000];
int main()
{
	int n,k=1,k2=1,len;
	cin>>n;
	a[0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<k;j++)
		{
			a[j]*=2;
		}
		for(int j=0;j<k;j++)
		{
			if(a[j]>=10){
				a[j+1]+=a[j]/10;
				a[j]%=10;
			}
		}
		if(a[k]!=0)k++;
		len=k;
		if(len<k2)len=k2;
		for(int j=0;j<len;j++)
		{
			b[j]+=a[j];
			if(b[j]>=10)
			{
				b[j+1]+=b[j]/10;
				b[j]%=10;
			}
		}
		if(b[len]!=0)len++;
	}
	for(int i=len-1;i>=0;i--)
	{
		cout<<b[i];
	}
	return 0;
}

题目描述
请计算n的阶乘(1<=n<=100)
n的阶乘计算公式为:n!=n*(n-1)(n-2)1,如:5!=5432*1=120

输入
一个整数n(1<=n<=100)

输出
n的

样例
输入
20
输出
2432902008176640000
直接上完整代码
这题其实就是高精度乘法的plus版,只不过另一个乘数一直在变而已了。
1.将a数组的a[0]元素设为1,不然怎么乘都是0。

a[0] = 1;

2.将另一个乘数慢慢减

for (int i = n; i >= 1; i--)

3.将a数组的每一位都乘另一个乘数

for (int j = 0; j < k; j++)
{
	a[j] *= i;
}

4.进位

for (int j = 0; j < k; j++)
{
	if (a[j] >= 10) {
	a[j + 1] += a[j] / 10;
	a[j] %= 10;	
	}
	if (a[k] != 0)k++;
}

5.逆序输出

for (int i = k - 1; i >= 0; i--)
{
	cout << a[i];
}
#include<iostream>
using namespace std;
int a[5000];
int main()
{
	int n,k=1;
	cin >> n;
	a[0] = 1;
	for (int i = n; i >= 1; i--)
	{
		for (int j = 0; j < k; j++)
		{
			a[j] *= i;
		}
		for (int j = 0; j < k; j++)
		{
			if (a[j] >= 10) {
				a[j + 1] += a[j] / 10;
				a[j] %= 10;
			
			}
		if (a[k] != 0)k++;
		}
	}
	for (int i = k - 1; i >= 0; i--)
	{
		cout << a[i];
	}
	return 0;
}

总结(注意事项)

总而言之,高精度的过程最好的理解办法就是画图,列竖式。
高精度的各种算法大体是相同的,比如说逆序存入数组,进位,逆序输出,判断第一个非零元素…
高精度的细节还是很多的,一步错,步步错。高精度的题目呢一般都是高精度基本的plus版,有些题呢需要几种高精度算法组合起来使用。
高精度大家一定要好好的理解,不要走马观花!!!


今天就给大家分享到这里了!!!
古德拜!!!
记得三连哦!!!

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 41
    评论
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值