【常用算法总结——C++高精度运算】
众所周知,数与数进行运算时,当两个数位数过大,我们的电脑就会烤鱼。所以我们就出现了高精度运算,他的思想主要就是用字符串来存储数据,再一位一位地分别计算(因为是字符,所以要记得-‘0’或-48),达到最后的结果。所以,这篇文章将会告诉大家如何进行C++中的一些高精度运算。
如果有没写的,说明博客主智商阅历不够,以后就会有了(等着吧)
高精度加法
一位一位的对着加,注意存储进位,小的数加完后把大数剩下的加进来,注意前导零和相加等于0
1 #include<bits/stdc++.h> 2 using namespace std; 3 int c[10000001];//记录结果的数组 4 string a,b; 5 long long k=0,r=0,i,j; 6 bool flag; 7 int main() 8 { 9 cin>>a>>b;//输入需要做操作的字符串 10 if(a.size()<b.size()||a.size()==b.size()&&a<b)//把大的字符串放前面,方便操作 11 { 12 swap(a,b); 13 } 14 for(i=a.size()-1,j=b.size()-1;j>=0;i--,j--)//从最低位相加,相加他们的公共部分,所以j>=0 15 { 16 c[k++]=(r+a[i]-'0'+b[j]-'0')%10;//两个位数和进位的相加后取个位 17 r=(r+a[i]-'0'+b[j]-'0')/10;//记录进位 18 } 19 while(i>=0)//再把剩下的继续加 20 { 21 c[k++]=(r+a[i]-'0')%10;//位数和进位的相加后取个位 22 r=(r+a[i]-'0')/10;//记录进位 23 i--; 24 } 25 if(r)c[k++]=r;//如果还有进位,进到最高位 26 for(i=k-1;i>=0;i--)//输出 27 { 28 if(c[i]!=0||flag)//防止前导0输出的操作 29 { 30 cout<<c[i]; 31 flag=true; 32 } 33 } 34 if(flag==false)cout<<0;//如果都没有输出,说明相加结果为0,应当输出0 35 return 0; 36 }
以上代码是两个正数相加,若有负数,则需要另行判断:
如果两个数都是负数,那么去掉负号,输出结果前加上负号即可。
如果两个数有一个数是负数,先去掉负号,比较大小
如果去掉负号的数大于另一个数,则需要用去掉负号的数减去另一个数,再输出负号(此时用高精度减法)
如果去掉负号的数小于另一个数,则需要用另一个数减去去掉负号的数,(此时用高精度减法)
高精度减法
一位一位的对着减,注意存储借位,小的数减完后把大数剩下的借位减进来,注意前导零和相减等于0
1 #include<bits/stdc++.h> 2 using namespace std; 3 int c[10000001];//记录结果的数组 4 string a,b; 5 long long k=0,r=0,i,j; 6 bool flag; 7 int main() 8 { 9 cin>>a>>b;//输入需要做操作的字符串 10 if(a.size()<b.size()||a.size()==b.size()&&a<b)//把大的字符串放前面,方便操作 ,还要判断相减是否为负数 11 { 12 cout<<"-"; 13 swap(a,b); 14 } 15 for(i=a.size()-1,j=b.size()-1;j>=0;i--,j--) 16 { 17 c[k++]=(a[i]-b[j]-r);//两个位数相减再减去接的位数 18 r=0;//清零标记 19 if(c[k-1]<0){c[k-1]+=10;r=1;}//如果是负数就借十,并标记 20 } 21 while(i>=0)剩下的继续减 22 { 23 c[k++]=(a[i]-'0'-r);//减去借的 24 r=0;//清零标记 25 if(c[k-1]<0){c[k-1]+=10;r=1;}//如果是负数就借十,并标记 26 i--; 27 } 28 for(i=k-1;i>=0;i--)//输出 29 { 30 if(c[i]!=0||flag)//防止前导0输出的操作 31 { 32 cout<<c[i]; 33 flag=true; 34 } 35 } 36 if(flag==false)cout<<0;//如果都没有输出,说明相减结果为0,应当输出0 37 return 0; 38 }
以上代码是两个正数相减,若有负数,则需要另行判断:
如果两个数都是负数,去掉负号,用后一个数减前一个数。
如果两个数有一个数是负数,先去掉负号,比较大小
如果第一个数是负数,相加,输出负号(此时用高精度加法)
如果第二个数是负数,相加(此时用高精度加法)
高精度乘法
相信大家都手动计算过乘法,就是一个数的每一位乘另一个数的每一位最后相加即可,当然,我们程序也是这样模拟
这里有一个基本的知识点,相信大家在手写竖式的时候知道,就是c[i+j]+=a[i]+b[j](因为a和b都是从0下标开始的,如果从下标1开始,就c[i+j-1]+=a[i]+b[j])
1 #include<bits/stdc++.h> 2 using namespace std; 3 string a,b; 4 int k; 5 int c[1000001]; 6 int main() 7 { 8 cin>>a>>b; 9 reverse(a.begin(),a.end()); 10 reverse(b.begin(),b.end()); 11 for(int i=0;i<a.size();i++) 12 { 13 for(int j=0;j<b.size();j++) 14 { 15 c[i+j]+=(a[i]-48)*(b[j]-48); 16 } 17 } 18 for(k=0;k<=a.size()+b.size();k++) 19 c[k]+=c[k-1]/10,c[k-1]%=10; 20 while(!c[k]&&k>=1)k--; 21 for(;k>=0;k--) 22 cout<<c[k]; 23 return 0; 24 }
高精度除法(高精除以高精)
高精度除法(高精除以低精)
手动模拟除法过程,每次读到新位计算出被除数,然后计算。大体就是一位一位的做减法操作。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int c[10000001];//记录结果的数组 4 string s; 5 long long k=0,a,b,i; 6 bool flag; 7 int main() 8 { 9 cin>>s>>b;//输入被除数和除数 10 for(int i=0;i<s.size();i++)//从高位开始,一位一位向低位 11 { 12 a=a*10+s[i]-'0';//加上被除数的这一位 13 c[k++]=a/b; 14 a%=b;//除完了 15 } 16 for(i=0;i<k;i++)//因为是从高位到低位,所以要反着输出 17 { 18 if(c[i]!=0||flag)//防止前导0输出的操作 19 { 20 cout<<c[i]; 21 flag=true; 22 } 23 } 24 if(flag==false)cout<<1;//如果都没有输出,说明相减结果为1,应当输出1 25 return 0; 26 }
以上代码是两个正数相除,若有负数,则需要另行判断:
如果两个数都是负数,去掉负号,不管他。
如果两个数有一个数是负数,去掉负号,输出时加上。
高精度模运算(高精模低精)
这个和高精度除法差不多,不需要记录和输出商就差不多
1 #include<bits/stdc++.h> 2 using namespace std; 3 string s; 4 long long k=0,a,b,i; 5 bool flag; 6 int main() 7 { 8 cin>>s>>b;//输入被除数和除数 9 for(int i=0;i<s.size();i++)//从高位开始,一位一位向低位 10 { 11 a=a*10+s[i]-'0';//加上被除数的这一位 12 a%=b;//一直取余 13 } 14 cout<<a; 15 return 0; 16 }