欧几里得算法(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便使用了该算法

原文地址:https://www.cnblogs.com/chuaner/p/11536491.html