高精度算法 学习笔记

高精度算法

高进度算法一共分为 6 6 6个主题,分别是高精度加法、高精度减法、高精度乘法、高精度除法、高精度开根和压位。

一、高精度加法

现在有一道题目,如下

给你两个整数a和b,请你算出它们的和。
数据范围:1<=a,b<=10^1000

一看这道题,就感觉是基础的 a + b a+b a+b问题,其实不然——数据范围肯定会爆。
那么我们怎么做呢?
我们回顾一下小学时候学的竖式加法。
假设 a = 145 , b = 44 a=145,b=44 a=145,b=44,竖式如下图
在这里插入图片描述
其实我们只用从最低位开始加,然后加到最高位就行了。
假设两个加数分别存入 a a a b b b数组,答案存入 c c c数组, y y y表示进位,则
c i = ( a i + b i + y )   m o d   10 c_i=(a_i+b_i+y)\:mod\:10 ci=(ai+bi+y)mod10
y = ⌊ a i + b i + y 10 ⌋ y=\lfloor \frac{a_i+b_i+y}{10}\rfloor y=10ai+bi+y
那么就可以直接用一个循环做了。
时间复杂度为 O ( m a x ( n , m ) ) O(max(n,m)) O(max(n,m))
n n n m m m分别表示两个数的位数。

二、高精度减法

那么高精度减法是不是也可以用竖式的办法解决呢,答案是对。
假设被减数 a = 100 a=100 a=100,减数 b = 78 b=78 b=78,竖式如下图
在这里插入图片描述
计算过程见右边。
其实我们只要判断一下当前这个位置是否够减,如果够,就减;否则,就加上 10 10 10再减,并把前一位减去 1 1 1
程序如下:

for(int i=1;i<=n;i++)
{
	if(a[i]<b[i])
	{
		a[i]+=10;
		a[i+1]--;
	}
	c[i]=a[i]-b[i];
}

注意:最后要删除前导 0 0 0
那如果 a < b a<b a<b,怎么办?
因为 a − b = − ( b − a ) a-b=-(b-a) ab=(ba),而 b > a b>a b>a,所以我们只用计算 b − a b-a ba就行了,输出时在前面加个负号。
时间复杂度为 O ( m a x ( n , m ) ) O(max(n,m)) O(max(n,m))
n n n m m m分别表示两个数的位数。

三、高精度乘法

上面我们解决了加法和减法,那么乘法是怎么样的呢?
乘法需要细心找规律才能找到。
假设乘数分别是 12 12 12 13 13 13,竖式如下图
在这里插入图片描述
我们看一下上图,可以发现一个规律:第 i i i位和第 j j j位相乘的结果应该存在第 i + j − 1 i+j-1 i+j1位上。
举例一下:
1 1 1 2 2 2乘以第 2 2 2 1 1 1,结果应该放在第 2 2 2位,因为 1 + 2 − 1 = 2 1+2-1=2 1+21=2
如果不明白可以看下图:
在这里插入图片描述
根据这个规律,我们就可以直接计算出答案,这里就不多说了。
注意:答案要累加进一个数组,因为可能会有 i + j − 1 i+j-1 i+j1重复的情况。
时间复杂度为 O ( n m ) O(nm) O(nm)
n n n m m m分别表示两个乘数的位数。

四、高精度除法

高精度除法有两种方法,第一种是二分答案,第二种是利用减法来求。

第一种方法

由于乘法是除法的逆运算,所以我们直接寻找一个数看这个数是否满足乘法运算就行了。
找数的方法很简单,就是二分答案。
如果没学过二分答案,可以自己去网上学一学,以后我会出关于二分答案的内容。
二分答案时,我们只要做乘法就行了。
时间复杂度大概为 O ( n m log ⁡ a 2 ) O(nm\log_a^2) O(nmloga2)
n n n表示被除数的位数, m m m表示除数的位数, a a a表示被除数。
其实复杂度远没有这么多。

第二种方法

我们只用一次一次的用被除数减去除数,直到被减数等于 0 0 0为止,答案就是次数。
这种时间复杂度很高,应该是 O ( a b ) O(\frac{a}{b}) O(ba)
a a a表示被除数, b b b表示除数。

五、高精度开根

高精度怎么开根呢,方法和高精度除法一样,都可以用二分答案来解决。
我们二分答案时,就只用算一下乘法,然后调整位置。
时间复杂度为 O ( n m log ⁡ a 2 ) O(n^m\log_a^2) O(nmloga2)
n n n表示被开方数的位数, m m m表示根指数, a a a表示被开方数。

六、压位

那么有什么方法可以使高精度算法的速度更快呢?
答案是,压位。
假如我们现在要算两个数的加法。
我们可以一次就算 5 5 5位,这样只用开 i n t int int
我们可以一次就算 12 12 12位,这样只用开 l o n g l o n g long long longlong
那么时间复杂度就变成了 O ( a b ) O(\frac{a}{b}) O(ba)
a a a表示原来的时间复杂度, b b b表示压位的位数。
这样就可以大大的缩短时间了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值