综述
最近闲来无事写了一个比较简单的高精度模板……想来之前没有总结过这一块的知识,就写一篇博客来简单记录一下吧。关于高精度模板的资料其实挺多的,有某个方法不是很理解的话可以再搜搜资料或者自己手动模拟一下。这个模板的效率肯定不是最好的,可能还会有隐藏的bug,仅给大家提供一种实现高精度的思路。
朴素想法
我们先从最简单的开始,如果让你实现一个正数的高精度加法,你会怎么做?大部分人的做法肯定是用数组或者链表来模拟这个过程,以数组为例,从低位到高位依次存储数字的每一位,那么加法无非就是从最低位开始逐位进行加法计算,进行进位。没错,这就是高精度算法的实现思路。不过为了简化算法,我们还需要使用一些技巧。比如,针对加法,我们仅计算同符号的大数相加,若不同符号则视为减法。针对减法,我们仅计算较大的数减去较小的数,然后通过取反运算将其扩展到全部情况。
那么乘法怎么计算呢?类似于竖式乘法,可以把乘数逐位拆分,然后再进行计算。很显然这样做的复杂度是比较高的,也有更加优秀的做法,不过这里就不讨论了~
比较复杂的是除法,这里提供一种思路吧,感觉复杂度还是比较高的。有点逆推的意思,不妨设 a / b = c a/b=c a/b=c,也即 a = b ∗ c a=b*c a=b∗c,此时把 c c c逐位拆分可得: a = b ∗ c n + b ∗ c n − 1 + … + b ∗ c 0 a=b*c_n+b*c_{n-1}+…+b*c_0 a=b∗cn+b∗cn−1+…+b∗c0。那么只要我们依次(从高位到低位)计算出 c n 、 c n − 1 、 … c_n、c_{n-1}、… cn、cn−1、…,再把它们拼起来就可以得到 c c c了。显然只要确定了 c i c_i ci的位数,就可以通过减法来模拟出 c i c_i ci的值。这个位数其实是比较容易确定的,如果 a a a有 x x x位, b b b有 y y y位,那么 c c c最多有 x − y + 1 x-y+1 x−y+1位,逐位模拟即可。
压位
如果每次只存储数字的一位的话,是不是有点浪费?考虑到 l o n g l o n g long\ long long lon