【高精度】加减乘除
本文最后更新于 34 天前,其中的信息可能已经有所发展或是发生改变。

高精度计算定义

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。

加法

#include<iostream>
#include<vector>

using namespace std;
//C=A+B
vector<int> add(vector<int> &A,vector<int> &B)
{
	vector<int> C;
	int t=0; //t是进位
	for(int i=0;i<A.size() || i<B.size();i++)
	{
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;   //t若>=10,t/=10,t变为1,表明要进位,t若<10,表明不需进位,t变为0
	} 
	if(t) C.push_back(1);  //如果最高位还有进位,在数组最后补1即可
	return C;
}

int main()
{
	string a,b;
	vector<int> A,B;
	
	cin>>a>>b;//a="123456"
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');//A=[6,5,4,3,2,1]
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	
	vector<int> C=add(A,B);
	
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
	return 0; 
}
 

第一步将两个超大数以字符串的形式输入,倒叙输入在各自数组中。第二步定义进位数,然后各自位数相加,只保留个位数,剩下的还给进位,以此类推第三步检测t是否还有数,有的话push一个1(加法直接push 1 即可)第四步倒序输出。

减法

#include<iostream>
#include<vector>

using namespace std;

vector<int> sub(vector<int> &A,vector<int> &B)
{
	vector<int> C;
	for(int i=0,t=0;i<A.size();i++)
	{
		t=A[i]-t;
		if(i<B.size()) t-=B[i];
		C.push_back((t+10)%10);//若t<0,借位加10,若>=0,加10再余10还是t
		if(t<0) t=1; //借位 
		else t=0; 		
	}
	while(C.size()>1 && C.back()==0) C.pop_back();
	return C;
}

int main()
{
	string a,b;
	vector<int> A,B;
	cin>>a>>b;
    char flag;
    if(a.size()<b.size()) swap(a,b),flag='-';
    else if(a.size() == b.size() && a<b)swap(a,b),flag='-';
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
    cout<<flag;
    vector<int> C=sub(A,B);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
	return 0;
}
 

前几个步骤其实差不太多,主要讲讲借位部分,C.push_back((t+10)%)的巧妙构思,不论t>0或者t<0都是可以保留小数位且负数情况还能借位。下一步if-else则是巧妙运用了t前者t=A[i]-t的设置。

乘法(高精度*低精度)

#include<iostream>
#include<vector>
using namespace std;

vector<int> mul(vector<int> &A,int b)
{
	vector<int> C;
	int t=0;
	for(int i=0;i<A.size() || t;i++)
	{
		if(i<A.size()) t+=A[i]*b;
		C.push_back(t%10);
		t/=10;    
	} 
	return C;
}

int main()
{
	string a;
	int b;
	cin>>a>>b;
	vector<int> A;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	vector<int> C=mul(A,b);
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
	return 0;
}

 

废话不多说,关键在于

for(int i=0;i<A.size() || t;i++)
    {
        if(i<A.size()) t+=A[i]*b;
        C.push_back(t%10);
        t/=10;    
    }
    return C;
中i<A.size()||t ,这里作用是哪怕i不在数组处理的位置时候,只要t不为非零就一直进行下去。“||”二者满足一个即可,当t为0则为非。

乘法(高精度*高精度)

#include <iostream>
#include <vector>
using namespace std;

vector<int> add(vector<int> &A,vector<int> &B)
{	
	vector<int> C;
	int t=0;
	for(int i=0;i<A.size() || i<B.size();i++)
	{
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	} 
	if(t) C.push_back(t);
	return C;
}

vector<int> mul(vector<int>& numA, vector<int>& numB)
{	
	vector<int> result;
	for(int i=0; i<numA.size(); i++)
	{	
		vector<int> temp;
		int carry = 0;
		for(int j=0; j<numB.size(); j++)
		{
			carry += numA[i]*numB[j];
			temp.push_back(carry%10);
			carry /= 10;
		}
		if(carry) temp.push_back(carry);
		temp.insert(temp.begin(),i,0);
		result = add(result,temp);
	}
	return result;
}

int main() 
{
	string A,B;
	vector<int> numA,numB;
	cin >> A >> B;
	for(int i=A.length()-1; i>=0; i--) 
	{
		numA.push_back(A[i]-'0');
	}
	for(int i=B.length()-1; i>=0; i--) 
	{
		numB.push_back(B[i]-'0');
	}
	vector<int> result = mul(numA,numB);
	for(int i=result.size()-1; i>=0; i--)
	{
		cout << result[i];
	}
	if(result.empty()) cout << "0";
	return 0;
} 

高精度*高精度,就是将加法和乘法结合起来(多了个x.insert(x.begin,i,0)进行位数迭代)

除法(高精度/低精度)

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
vector<int> div(vector<int> &A,int b,int &r) 
{
	vector<int> C;
	r=0;
	for(int i=A.size()-1;i>=0;i--)
	{
		r=r*10+A[i];
		C.push_back(r/b);
		r%=b;
	}
	reverse(C.begin(),C.end());
	while(C.size()>1 && C.back()==0) C.pop_back();
	return C;
}

int main()
{
	string a;
	int b;
	cin>>a>>b;
	vector<int> A;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	int r;
    vector<int> C=div(A,b,r);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    cout<<endl<<r<<endl;
    return 0;  
}   
 
 

关键也在于对除法的处理上,引进一个余数的概念,根据竖式除法输入倒叙输入便于在div函数中进行分开处理。

for(int i=A.size()-1;i>=0;i–)
    {
        r=r*10+A[i];
        C.push_back(r/b);
        r%=b;
    }
    reverse(C.begin(),C.end());
    while(C.size()>1 && C.back()==0) C.pop_back();
    return C;
 
此处颠倒是为了下面做pop0处理。r的进位继承非常巧妙
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇