译注:原文链接https://www.di-mgt.com.au/euclidean.html,翻译工具有道翻译http://fanyi.youdao.com/。
在这里我们看看欧几里德算法(辗转相除法-译注)和如何使用它,解答典型的考试题目,并演示如何手工计算。然后,我们看看如何利用它来找到一个数字的模逆和扩展欧几里德算法(推导过程为译者原创:))。
欧几里德算法是计算两个整数最大公约数(gcd)的一种有效方法。大约在公元前300年左右,它首次发表在欧几里德《元素》的第七卷。
我们记gcd(a, b) = d表示d是能同时整除a和b的最大数,如果gcd(a, b) = 1那么我们说a和b是互素的或互质的。gcd有时也写为hcf(highest common factor)。
算法:(欧氏算法)计算两个整数的最大公约数。
输入:两个非负整数a和b, a≥b。
输出:gcd(a,b)。
1. While b > 0, do
a. Set r = a mod b,
b. a = b,
c. b = r
2. Return a.
证明使用了除法算式的基本论断,即对于任意两个整数a、b且b > 0,有唯一的整数q和r,使得a = qb + r,0 <= r < b(a除以b的商为q、余为r,a、b的公约数就是b、r的公约数,反之亦然-译注)。本质上,如果a是一个正整数,那么经过每一步递推a都会变小,最终收敛到一个解(它不能小于1)。
如果a或b的值为负数,只需在上述算法使用绝对值|a|和|b|。按照惯例,如果b = 0那么gcd就是a。
每次数论考试都有欧几里德算法的问题,这简直是个礼物。在考试前的最后一晚练习它就行。下面是我们想要展示的(括号中的注释只是作为指导;在正式答案中不需要它们)。
问题 1(a): 求 gcd(421, 111)。
答案:
使用欧几里德算法:
421 = 111 x 3 + 88 (大数421在左侧)
111 = 88 x 1 + 23 (新的大数111移动到左侧)
88 = 23 x 3 + 19 (注意小数19是怎样移动到"对角"的)
23 = 19 x 1 + 4
19 = 4 x 4 + 3
4 = 3 x 1 + 1 (最后一个非零余数是1)
3 = 1 x 3 + 0
最后的非零余数是1,所以gcd(421, 111) = 1。
在每一步,取较大的数除以另一个,得到整数商,如421 / 111 = 3.793得到3,再求余数,421 - 111 x 3 = 88,我们可以把这个过程写成421 = 111 x 3 + 88。对较小的数(111)重复该操作,直到余数为零。最后一个非零余数就是gcd,在本例中是1。(一旦你有了1作为余数,那最后一行计算就没有必要了,但我们还是保持了完整。)
在我们看来,严格地遵循解题步骤是有帮助的,否则你会在考试中因慌乱而犯错。注意,在每一行等号右边我们总是先写除数(111),然后才是商数(3),如果你这样做了,你总是有正确的数字准备“向左移动”到下一行的另一边。
注意每个数是如何从右上向左下移动的,这让你在写的过程中很容易地进行检查。
下面是另一个例子。问题2(a):求gcd(93, 219)。
219 = 93 x 2 + 33
93 = 33 x 2 + 27
33 = 27 x 1 + 6
27 = 6 x 4 + 3
6 = 3 x 2 + 0
最后的非零余数是3,所以gcd(93, 219) = 3。
给定非零的任意整数a、b,那么存在x、y,使得gcd(a, b) = xa + yb。换句话说,总是能将a、b的最大公约数表示为a、b的整数组合。
大多数试题的(b)部分都包含这个定理,典型的具有以下形式:
“将1 = gcd(421, 111)写成整数组合的表示”
“求解整数x、y,使得gcd(421, 111) = 421x + 111y”
“求线性丢番图方程gcd(421, 111) = 421x + 111y的解”
作为参照,下面将问题1(a)的答案再列出来:
(1) 421 = 111 x 3 + 88
(2) 111 = 88 x 1 + 23
(3) 88 = 23 x 3 + 19
(4) 23 = 19 x 1 + 4
(5) 19 = 4 x 4 + 3
(6) 4 = 3 x 1 + 1
(7) 3 = 1 x 3 + 0
问题1(b):求解整数x、y,使得gcd(421, 111) = 421x + 111y。
答案:
设a = 421,b = 111,将上面的欧几里德算式从倒数第二行往回推。
1 = 4 - 1 x 3 (从第6行开始,将余数1放到左边,小数3放到右边)
1 = 4 - 1 x (19 - 4 x 4) (用第5行替换小数3)(第6行的小数就是第5行的余数-译注)
1 = -1 x 19 + 5 x 4 (重新安排新的小数4)(第6行的大数就是第5行的小数-译注)
1 = -1 x 19 + 5 x (23 - 1 x 19)(用第4行替换小数4)
1 = 5 x 23 - 6 x 19 (将新的大数移到左边)
1 = 5 x 23 - 6 x (88 - 3 x 23)(用第3行扩展小数19)
1 = -6 x 88 + 23 x 23 (重新安排新的小数23,放到右边)
1 = -6 x 88 + 23 x (111 - 1 x 88)
1 = 23 x 111 - 29 x 88 (总是将系数放到因子的左边)
1 = 23 x 111 - 29 x (421 - 3 x 111)
1 = -29 x 421 + 110 x 111 (最后检查总是有一个负数系数)
所以我们得到x = -29,y = 110。
请注意,我们总是在两个不同的行上分两步来做:
最后,我们得到了要找的,形如d = 421x + 111y的解。
要严谨不要走捷径,尤其是在考试的时候。始终将两步计算分别列出,并保持d = 系数 x 大数 + 系数 x 小数,d = 系数 x 大数 + 系数 x (扩展的小数)的有序形式。(注意,我们交换了第(a)部分的顺序以将大小数都保持在右边)。
还要注意的是,不需要将系数 x (扩展的小数)项完全乘出来;只需要简单的加减系数。例如,在上面第4行,19项的系数是-1 + 5 x(-1) = -6。这就是为什么我们把因子放在右边的原因。
当你完成的时候,必然得到x和y一正一负的结果,然后你可以验证结果。
xa + yb = -29 x 421 + 110 x 111
= -12209 + 12210
= 1,完成
如果出错,重新检查每一行,一定有某一行有错误。
问题2(b):求线性丢番图方程gcd(93, 219) = 219x + 93y的解。
答案:
从问题2(a)我们得到gcd(93, 219) = 3,现在从欧几里德算式倒数第二行倒推。
3 = 27 - 4 x 6
= 27 - 4 x (33 - 27 x 1)
= -4 x 33 + 5 x 27
= -4 x 33 + 5 x (93 - 2 x 33)
= 5 x 93 - 14 x 33
= 5 x 93 - 14 x (219 - 2 x 93)
= -14 x 219 + 33 x 93
所以gcd(93, 219) = 219x + 93y的解是x = -14, y = 33。
验证:219x + 93y = 219 x (-14) + 93 x 33 = -3066 + 3069 = 3。
一个整数e模n的逆(也称倒数、乘逆元等-译注)定义为d,使得ed = 1 mod n,记作d = (1/e) mod n或d = e-1 mod n。当且仅当gcd(n,e)=1时,这个逆存在。
为了在计算机上找到大数的模逆,我们通常使用扩展的欧几里德算法,但是对于较小的数有更简单的方法。
对于很小的数,我们可以采用试错法。例如,为了求3模20的倒数,我们有e=3,n=20,需要找到整数d当ed除以20时余数是1。
试 d=1, ed=3x1=3, 3除以20是0余3, 不是
试 d=2, ed=3x2=6, 6除以20是0余6, 不是
...
试 d=6, ed=3x6=18, 18除以20是0余18, 不是
试 d=7, ed=3x7=21, 21除以20是1余1,万岁
7满足关系式,所以模逆d = 3-1 mod 20 = 7。
注意还有其它比较大的结果。
d = 7 + 1 x 20 = 27 因为 27 x 3 = 81 = 3 x 20 + 1
d = 7 + 2 x 20 = 47 因为 47 x 3 = 141 = 7 x 20 + 1
d = 7 + 3 x 20 = 67 因为 67 x 3 = 201 = 10 x 20 + 1
... 等等
也有负的模逆d = -13, -33, -53, …
d = 7 - 1 x 20 = -13 因为 -13 x 3 = -39 = -2 x 20 + 1
d = 7 - 2 x 20 = -33 因为 -33 x 3 = -99 = -5 x 20 + 1
... 等等
在讨论RSA算法时这是一个问题,但模逆通常指0至n-1之间的最小正整数d。
对小整数求e-1 mod n的另一种快速方法是计算e2, e3, e4,…对n取余直到结果为1(这总是在你到达en之前发生,通常很快)。如果k > 0是一个整数,ek≡1,那么e的逆就是ek-1的值。这是因为ek = eek-1≡1,根据定义,ek-1是e的逆(最小正整数模逆是ek-1 mod n-译注)。
例如,n = 20,e = 3,则e1 = 3,e2 = 9,e3 = 27≡7,e4 ≡ 7 x 3 = 21≡1。所以e3≡7是逆,即3-1≡7 mod 20。
另一个例子,找到2-1 mod 17,计算21 = 2,22 = 4,23 = 8,24 = 16,25 = 32≡15, 26 ≡ 30≡13, 27≡ 26≡9,28≡ 18≡1(mod 17)。因此2-1≡9 mod 17。
验证:2 x 9 = 18 = 1 x 17 + 1≡1(mod 17)。
如果我们要求d = e-1 mod n,可以求出x和y这样的整数使得ex + ny = 1,那么e的逆d就是x的值(不能算出来吗?见下文)。
这看起来熟悉吗?这就是我们上面推导出来的表达式。
使用上面的方法求d = 3-1 mod 20,我们首先得到gcd(20,3)并检查它是否为1(否则逆不存在)。
20 = 3 x 6 + 2
3 = 2 x 1 + 1
得到gcd(20,3) = 1。然后我们用这个计算中的数字来求出贝祖等式ex + ny = 1,
1 = 3 - 1 × 2
= 3 - 1 x (20 - 6 x 3)
= -1 x 20 + 7 x 3
x的值(3的系数)是7,所以逆是7。
类似地,为了求111模421的倒数,我们可以使用上面推导出的表达式
110×111 - 29×421 = 1
这就得到x = 110,所以倒数111-1 mod 421 = 110。
验证:111 x 110 =12210 = 29 x 421 + 1 ≡ 1 mod 421。
问题:93-1模219的值是多少?提示:参见上面的问题2(b)。更重要的提示:答案不是33(或-14或205)。
如果算法得出一个负的逆,只需要把模数加到结果中。记住3d≡1 mod 20被所有的7 + 20 k满足,不论k是正数还是负数。所以不仅仅是7、27、47、67…是有效的逆,-13、-33、-53,…也是。如果上面的方法得到-13,与模相加得到-13 + 20 = 7。
对于任何整数y我们有ex + ny ≡ ex mod n,因为ny ≡ 0 mod n,所以ex + ny =1,则ex + ny ≡ ex ≡ 1 mod n,根据定义这意味着x是e的倒数。
扩展欧几里德算法只是上面我们使用的欧几里德算法的一种更奇妙的运用。它涉及到使用额外的变量来计算ax + by = gcd(a, b),而我们是一个过程分成两步。在计算机程序中使用它效率更高,但如果是手工计算,老实说,使用上面的方法更简单。
算法:扩展欧几里德算法。
输入:两个非负整数a和b,且a≥b。
输出:d = gcd(a, b)和满足ax + by = d的整数x和y。
1. If b = 0 then set d = a, x = 1, y = 0, and return(d, x, y).
2. Set x2 = 1, x1 = 0, y2 = 0, y1 = 1
3. While b > 0, do
q = floor(a/b), r = a - qb, x = x2 - qx1, y = y2 - q y1.
a = b, b = r, x2 = x1, x1 = x, y2 = y1, y1 = y.
4. Set d = a, x = x2, y = y2, and return(d, x, y).
在计算机上使用二进制技术可以更有效地实现欧几里德算法和扩展欧几里德算法。
(以下计算机程序略)
原文没有给出扩展欧几里德推导的例子,上述算法看起来也着实迷糊,因此译者在此补上,就以gcd(219,93 )=3为例,推导求解219x + 93y = 3的过程。
将前文欧几里德算式变形为xa + yb = r形式,各式均保持大数在前,即a>=b
(1)1 x 219 - 2 x 93 = 33
(2)1 x 93 - 2 x 33 = 27
(3)1 x 33 - 1 x 27 = 6
(4)1 x 27 - 4 x 6 = 3
(5)1 x 6 - 2 x 3 = 0
每步算式用q表示整数商,x、y表示满足本次xa + yb = r的解,递推:
(1)1 x 219 - 2 x 93 = 33 从原始算式看出每个大数系数均为1,以下省略
得x = 1,y = -2
(2)式将33用(1)式替换
93 - 2 x ( 1 x 219 - 2 x 93 ) = 27
- 2 x 219 + 5 x 93 = 27
得x = -q(前式x),y = 1 - q(前式y)
(3)式将33和27分别用新的(1)、(2)式替换
( 1 x 219 - 2 x 93 ) - 1 x (- 2 x 219 + 5 x 93 ) = 6
3 x 219 -7 x 93 = 6
得x = 大前式x - q(前式x),y = 大前式y - q(前式y)
(4)式将27和6分别用新的(2)、(3)式替换
(- 2 x 219 + 5 x 93 ) - 4 x (3 x 219 - 7 x 93 ) = 3
- 14 x 219 + 33 x 93 = 3
得x = 大前式x - q(前式x),y = 大前式y - q(前式y)
(5)式r等于0,则前式为计算结果
计算结果,d=3,x=-14,y=33。从前面的递推过程可以看出:
弄懂了这个推导过程,前面的算法描述自然就清楚了。