高精度算法 小白

南昌理工学院ACM集训队

1 什么是高精度

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,我们可以将这个数字拆开,拆成一位一位的,或者是几位几位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。
由于数字过于庞大,用long long 和double 也存不下的数字,只能用高精度算法解决,也就是把数字当成字符串数组输入,然后进行一位一位的运算得出结果

2 高精度的输入和输出

当一个数过于庞大时,我们用整形类型是存不下的,所以我们可以用字符串数组来存储这个数字,
例如 a=987654321,存入字符串数组中应该是这样的 h={1,2,3,4,5,6,7,8,9}. 这里是用倒序来存储这个数字的,因为我们计算都是从低位开始计算,因为有进位,所以到时候可以最直接加上去,会方便一些。

数字的输入

string a;
 int b[10000];
 cin>>a;
 int len=a.length();
 for(int i=0;i <len;i ++){
 	b[i] =a[len-i-1]-'0';
 }

数字的输出

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

3 开始实战

例题一 洛谷 P1601 A+B Problem(高精)
原汁原味的高精度加法例题 先上代码

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
string a,b;
string add(string str1,string str2)
{
	string str;
	int len1=str1.length();//字符串的长度 
	int len2=str2.length();
	//因为是加法所以不用比较大小,只要满足两个数的长度一样长就可以了,所以就在短的那个数前补0
	if(len2>len1){//短的补0 
		for(int i=1;i <=len2-len1;i ++)
			str1 ="0"+str1 ;//直接在数组前面补0,并且长度会加一 
	}
	else {
		for(int i=1;i <=len1-len2;i ++)
		   str2 ="0"+str2;
	}
	//string 类型的操作,不太清楚的可以去查一查
	len1=str1.length();//此时两个数的的长度一致了,随便取哪一个,都是数字的长度
	int x=0;//记录进位 
	int temp;//记录当前值
	for(int i=len1-1;i >=0;i --)
	{
		temp =str1[i]-'0'+str2[i]-'0'+x;
		x =temp/10;
		temp %=10;
		str=char(temp+'0')+str; //构造当前值 
	}
	if(x!=0) str=char(x+'0')+str;//再判定一下 
	
	return str; 
}
//因为这里返回的也是字符串数组,所以要加char;

int main()
{
cin>>a>>b;	
cout<<add(a,b);	
	
return 0;	
 } 

可以直接套模板的,理解起来也不是特别难

例题二 洛谷 P1303 A*B Problem

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
string a,b;
string add(string str1,string str2)
{
	string str;
	int len1=str1.length();//字符串的长度 
	int len2=str2.length();
	
	if(len2>len1){//短的补0 
		for(int i=1;i <=len2-len1;i ++)
			str1 ="0"+str1 ;//直接在数组前面补0,并且长度会加一 
	}
	else {
		for(int i=1;i <=len1-len2;i ++)
		   str2 ="0"+str2;
	}
	len1=str1.length();
	int x=0;//记录进位 
	int temp;//记录当前值
	for(int i=len1-1;i >=0;i --)
	{
		temp =str1[i]-'0'+str2[i]-'0'+x;
		x =temp/10;
		temp %=10;
		str=char(temp+'0')+str; //构造当前值 
	}
	if(x!=0) str=char(x+'0')+str;//再判定一下 
	
	return str; 
}

string mul(string str1,string str2)
{
    string str;
    int len1=str1.length();
    int len2=str2.length();
    string tempstr;//让一个数字的每一位,从最低位开始去乘另一个数,然后把他们都加起来,注意数字的位置
    for(int i=len2-1;i>=0;i--)
    {
        tempstr="";//对这个字符串数组进行清0操作
        int temp=str2[i]-'0';
        int t=0;//记录当前位数的值
        int cf=0;//记录进位
        if(temp!=0)
        {
            for(int j=1;j<=len2-1-i;j++)
              tempstr+="0"; 
//从tempstr数组的0位置开始补0
            for(int j=len1-1;j>=0;j--)
            {
                t=(temp*(str1[j]-'0')+cf)%10;
                cf=(temp*(str1[j]-'0')+cf)/10;
                tempstr=char(t+'0')+tempstr;//将当前位数的值补到tempstr中去,构造值,补在0前面
            }
            if(cf!=0) tempstr=char(cf+'0')+tempstr;
        }
        str=add(str,tempstr);
    }
    str.erase(0,str.find_first_not_of('0'));
    return str;
}

![关于str.erase的解释](https://img-blog.csdnimg.cn/20200808110048528.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0dKTTU2Nw==,size_16,color_FFFFFF,t_70)
//比如这个字符串为000124  返回这个字符串为124
int main()
{
cin>>a;
cin>>b;	
if(a[0]=='0'||b[0]=='0')
cout<<"0";
else
cout<<mul(a,b);	
	
return 0;	
 } 

这样写的好处是 不用考虑你数组有时开的不够大的情况,一般都说都能满足

例题3 洛谷 P2142 高精度减法

#include<bits/stdc++.h>
using namespace std;

string s1,s2;
int a[500000],b[500000],l1,l2,c[5000000],g=0;
int main()
{
cin>>s1>>s2;
l1=s1.size();
l2=s2.size();
if(s1.size()<s2.size()||(l1==l2&&s2>s1)){
g=1;
swap(s1,s2);//交换字符串
swap(l1,l2);//记得要交换长度
}
for(int i=l1;i >0;i --) a[i] =s1[l1-i]-'0';
for(int i=l2;i >0;i --) b[i] =s2[l2-i]-'0';
int len=max(l1,l2);


for(int i=1;i <=len;i ++){
	if(a[i]<b[i]){
		a[i+1]--;
		a[i]+=10;
	}
	c[i]=a[i]-b[i];
} 
while(c[len]==0) len --; //可能会出现数字前面有0的情况,所以长度需要缩小

if(g==1) cout<<"-";

for(int i=len;i >0;i --) cout<<c[i];
if(len<1) cout<<"0";//但也有值为0的情况,这种情况直接输出0;

return 0;	
 } 

这是直接在main函数里写,比较简单直观,但是如果遇见有题目需要进行连减的时候,再这样写可能就比较麻烦了。最好是用函数来写,到时候要用可以直接调用。
下面是代码

#include<bits/stdc++.h>
#define mian main
#define MAXN 10500 
using namespace std;
string a, b;

string sub(string a, string b)
{
    int na[MAXN] = {0},nb[MAXN] = {0},c[MAXN] = {0};
    string f;
    int l1=a.size(),l2=b.size();
    if((a < b && l1 <= l2) || l2 > l1)
     return "-" + sub(b, a);
    for(int i = l1; i > 0; i --)na[i] = a[l1 - i] - '0';
    for(int i = l2; i > 0; i --)nb[i] = b[l2 - i] - '0';

    int maxl = max(l1, l2);

    for(int i = 1; i <= maxl; i ++)
    {
        if(na[i] < nb[i])
        {
            na[i + 1] --;
            na[i] += 10;
        }
        cs[i] = na[i] - nb[i];
    }
    while(c[maxl] == 0)maxl --;//防止减后降位,多输出若干0
    if(maxl < 1)return "0";
    for(int i = maxl; i > 0; i --)
    f += c[i] + '0';//数组转化为字符串。 
    return f;
}

int main()
{
    cin >> a >> b;
    cout << sub(a, b);
    return 0;
}

其实除了这些还有许多关于高精度的知识点像是 高精度除法 高精度开方 高精度平方之类的 这里就不写这么多了感兴趣的小伙伴可以再去了解一下 (因为我也不是很懂 笑哭)

最后其实高精度还有一种贼简单的方法 用Python写

#Python3
a=input();
b=input();
print(int(a)-int(b))
# python2
a=input()
b=input()
print int(a)-int(b)

就3行代码 简直不能太简单(如果我会python的话)

那就这样吧,以后再多接触关于高精度的知识的话,会补充的!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值