高精度算法是一个非常烧脑的问题,那么高精度是什么东西呢?
为什么要用到高精度
在日常生活中,我们经常会做加减乘除的运算。可我们算的数几乎都是万以内的,这个任务对于计算机来说还是小菜一碟。说句实在话,计算机太湖之光每秒能计算万亿以上的数,相当于全球90亿人一起算万亿以上的数,算38年!这如此恐怖的计算量,总是离不开计算机的最强大脑。那么,计算机是怎么计算的呢?
32位CPU中一个整数最大只能取值4,294,967,295(=232-1)。因此在进行更大范围的数值计算中,往往要采取模拟手段。通常通过分离字符的方法通过数字数组进行输入、通过数组倒序输出、通过模拟竖式计算进行计算。
计算机通常在做计算的时候,是把一个非二进制的数转成二进制来进行运算。那么运算总得有空间才能装得下结果,空间有多大呢?
如上图所示,int类型的数通常是由32个比特组成(8个比特为一个字节,一共4个字节,4*8=32(比特))。比如说,一个int类型的a数组,下标为3:int a[3]。那么,每个下标的字节数为4,32个比特,每个下标一共有32个比特,3个下标就是32*3=96(比特)。我们来了解一下各个变量类型所用的位数。
由此可见,long long类型和double类型的位数最多,也意味着它们的数值非常大。可有一个问题,就是如果有道题让你求比double类型还要大的数的运算时,就不能用double或者long long了。怎么办呢?摆烂?这时候,一位叫“高精度”的东西站了出来。
模拟高精度加法
通过上文,我们知道了可以用高精度来解决大整数的运算。就先从高精度加法开始吧。
我们先模拟加法竖式:
962 + 93 = ?
9 6 2
+ 9 3
—————
列出竖式后,我们先把每一位上的数加起来。意思是说,不管有没有进位,先算出结果再说。
9 6 2
+ 9 3
—————
9 15 5
此时,我们发现,15大于了10(有进位),所以要把10往前进一位,变成:
9 6 2
+ 9 3
—————
1 0 5 5
把高精度加法转化成代码就是模拟竖式的过程。当然,在进行运算时,也要把结果倒着存储。具体原因我会在“高精度加法代码及应用”中说。
高精度加法代码及应用
学习了高精度加法的运算过程,下面我们就来打高精度加法的代码。
同样的,先把头文件这些的先打好。
#include <bits/stdc++.h>
using namespace std;
int main(void) //记得要清空main函数里面的内容
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//高精度加法代码
return 0;
}
定义变量。
string s1, s2; //两个高精度字符串,因为输入高精度的数是用字符串输入,否则无法计算机无法接受整数类型的大整数
int a[250], b[250], c[500];
//a数组代表把每一位字符串转成数字后的存储地方,b数组同理,c数组用来存放结果
int len;
//len表示字符串的长度
输入两个字符串。
getline(cin, s1);
getline(cin, s2);
//用getline输入保险
把每一位字符转成数字。
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';
}
接下来比较两个字符串的长度,方便计算。
len = max (s1.size(), s2.size());
把每一位的结果存放进c数组里。
for(int i=0;i<len;i++) c[i]=a[i]+b[i];
接下来遍历字符串,判断结果是否有进位。
for(int i=0;i<len;i++){
if(c[i]>=10){
c[i+1]+=c[i]/10; //下一位进1
c[i]%=10; //保留取模后的结果
}
}
判断如果加法过后结果位数有增加。
if(c[len]!=0) len++;
最后逆序输出结果。
for(int i=len-1;i>=0;i--) cout<<c[i];
把整个过程串起来,合成一段代码(最终代码):
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
int a[250],b[250],c[250];
int main() {
getline(cin,s1);
getline(cin,s2);
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';
}
int len = max(s1.size(), s2.size());
for(int i=0;i<len;i++) c[i]=a[i]+b[i];
for(int i=0;i<len;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;
}
以上就是高精度加法的代码。输入数据的长度由a数组和b数组的下标大小决定。
对了,刚才我说为什么结果要倒着储存,还要倒着进行竖式计算,是因为方便计算,而且计算时不容易出错。
好了,以上就是高精度加法的分析和模拟加代码,记得点个收藏,拜拜!