• 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;
    
    • 1

    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';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3:把两个数组值相加

    for(int i=0;i<len;i++)
    {
    	c[i]=a[i]+b[i];
    }
    
    • 1
    • 2
    • 3
    • 4

    4:逆序输出

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

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

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

    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';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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
    • 2
    • 3
    • 4

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

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

    2:逐位乘

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

    3:逐位进位

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

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

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

    5:逆序输出

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

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

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

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

    for(int i=0;i<n;i++)
    	 {
    	 	t*=10;
    	 	cout<<t/b;
    	 	t=t%b;
    	 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    高精度乘:
    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';
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    这个大家都会吧!
    
    • 1

    3:错位加到c数组里

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

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

    for(i=s1.size()+s2.size()-1;i>=0;i--)
    	{
    		if(c[i]!=0){
    			p=i;
    			break;
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5:逆序输出

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

    完整代码

    高精度加法:

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    高精度减法:

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    高精度乘单精度:

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    高精度除法:

    #include
    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;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    高精度乘:

    #include
    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;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    实战应用

    题目描述
    求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;
    
    • 1

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

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

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

    for(int j=0;j<k;j++)
    {
    	if(a[j]>=10){
    	a[j+1]+=a[j]/10;
    	a[j]%=10;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

    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;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.逆序输出

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

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

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    题目描述
    请计算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;
    
    • 1

    2.将另一个乘数慢慢减

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

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

    for (int j = 0; j < k; j++)
    {
    	a[j] *= i;
    }
    
    • 1
    • 2
    • 3
    • 4

    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++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.逆序输出

    for (int i = k - 1; i >= 0; i--)
    {
    	cout << a[i];
    }
    
    • 1
    • 2
    • 3
    • 4
    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    总结(注意事项)

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


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

  • 相关阅读:
    算法通关村第十六关:黄金挑战:滑动窗口与堆结合
    Java列表查询Long(id)到前端转换出错
    负载均衡器 OpenELB ARP 欺骗技术解析
    前端笔记:React的form表单全部置空或者某个操作框置空的做法
    阿里P8MySQL,基础/索引/锁/日志/调优都不误,一锅深扒端给你
    SpringBoot系列教程之定义接口返回类型的几种方式
    js面试题==和===
    华为OD机考:0023-磁盘容量排序
    MySQL底层原理
    使用Fiddler进行手机抓包
  • 原文地址:https://blog.csdn.net/weixin_60626543/article/details/126545880