从这篇博客开始,我就要和大家分享我在学习C++过程中的一些干货,帮助大家更好的学习C++。
今天我要讲高精度算法的加减运算。在开始之前,我们先来复习一下各个数据类型的数据范围:
其中我们最常用的因该是int和long long,数据范围为-2^31~2^31-1和-2^63~2^63-1,最大的unsigned long long是0~2^64-1。
但这是就有个问题了,有时候我们要计算两个整数之间的运算,那万一都是11位以上的“庞然大物”呢?unsigned long long 都装不下,何况是其他的呢?
这时我们就要运用一个新的算法——高精度算法。
先看一个问题:
这是典型的递推,公式是f[i]=f[i-1]+f[i-2];
那么第一百项就等于135301852344706746049+21892299583455169026。
可以看到两个数都是21位,这unsigned long long 也装不下啊!(unsigned long long:我撑死了)
那么这时就要用高精度的加法算法啦!
其实高精度算法的核心就是模拟小学加法竖式。
我们来看一个竖式:
这肯定都会吧?
我们来过一下:首先8+5=13,写3,进1。再4+3+1=8,写8。再9+2=11,写1,进1。最后写0,进1,答案就是:10183。
那C++该咋模拟呢?
比如我们可以定3个int数组:a,b,c。a,b来存储加数,c存结果,那 么c[1]=a[1]+b[1],c[2]=a[2]+b[2],……
我们就可以得到第一个式子:
c[i]=a[i]+b[i];
哎,不对。
因为加法还有进位,你不可能用=号,因该用+=。
既然说到进位,我们就来看看该怎么实现。
逢十进一,我们可以用从c[i]/10来表示进位,那么因为是c[i+1]加上进位,所以代码就是:
c[i+1]=c[i]/10;
进位之后还得留位,留位其实就是c[i]/10的余数,就是c[i]%10,总代码就是:
但是,没完。
现在有个问题就是,该怎么输入两个超大数。
string:你忘了我吗?
对,string就能做到这一点。
但你做加法不还要转成int吗?
'0':你是忘了我吗?
'0'完全能做到这一点。
我们先来看一下高精度加法的总代码:
这个while是啥用呢?
当我们计算时,难免会有前导零,我们可以用这行代码来消除。
最后免费附上完整子程序:
string Add(string as,string bs){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
string cs="";
int al=as.size(),bl=bs.size();
int cl=max(al,bl)+1;
for(int i=1;i<=al;i++)a[i]=as[al-i]-'0';
for(int i=1;i<=bl;i++)b[i]=bs[bl-i]-'0';
for(int i=1;i<=cl;i++){
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;
c[i]%=10;
}
while(c[cl]==0&&cl>1)cl--;
for(int i=cl;i>=1;i--)cs+=c[i]+'0';
return cs;
}
好,点赞加速日更!