欧几里得算法(Euclidean Algorithm)

预备知识(不严谨定义)

整除:简单来说, \(a = nb\), 则有\(b|a\),读作b整除a

约数(divisor):上面整除的例子里,b就是a的约数,公约数就是多个数的共有约数,如2就是4、6、8的公约数

最大公约数(greast common divisor, 简称gcd):顾名思义,公约数里最大的一个,设\(gcd(a,b)=m\),则任取a、b的公约数c,有\(c <= m\),需要注意的是,最大公约数往往是整数,特殊的:

  • \(b|a\), 则\(gcd(a, b)=b\)
  • 任取整数\(n\),有\(gcd(0, n)=n\)

互素(relatively prime):两个数的最大公约数是1,那么我们就称这两个数的互素的

如果我们要求最大公约数,我们先来想一下最简单的思路。

假设\(a>b\),我们使用暴力求解的方式,从1开始,设置一个变量存储最大公约数值,每发现一个既能整除a又能整除b的数,将其置为最大公约数,直到遍历到b为止。粗一看,时间复杂度也并不很高,似乎也是可行的方法。但实际上,在实际的密码学程序中,需要大量的这类操作,并且操作的数往往是非常大的数,这时,这种方法就显得十分低效,而欧几里德方法就是为了能够高效的求取最大公约数。

欧几里德算法

首先我们来看,设

\[a = q*b+r \\d = gcd(a, b) \]

那么\(r = a-q*b\),由于\(d|a、d|b\),则有\(d|(a-q*b)=r\),即d也是b和r的最大公约数,此外,又有\(b>r => b=q_1*r+r_1\)以此类推,就得到了我们的欧几里德算法。

算法描述为:

  1. 将输入置为\(a>b\)
  2. \(a=q*b+r\)
  3. \(r=0\),则\(gcd(a,b)=b\)
  4. 否则,令\(a := b, b := r\), 注意这里的:=是赋值操作,重复2

建议自己模拟一下,易于理解!

欧几里德算法的实现

# 加减法的实现对计算机的计算方式更友善
def gcd1(a, b):
    a, b = max(a, b), min(a, b)
    while a != b:
        a, b = max(b, a-b), min(b, a-b)
    return a

def gcd2(a, b):
    a, b = max(a, b), min(a, b)
    while a % b != 0:
        a, b = b, a%b
    return b

实用的欧几里德算法

上面只是欧几里德算法的直接实现,效率较低,不能满足实际环境的需要。

通常的生产代码中使用的最大公约数算法是一种称作binary GCD的算法,其算法描述如下,

openssl中使用的BN_gcd便使用了该算法

posted @ 2019-09-17 19:41  火腿烧豆腐  阅读(4583)  评论(0编辑  收藏  举报