faqts : Computers : Programming : Languages : Python : Snippets

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

9 of 18 people (50%) answered Yes
Recently 4 of 10 people (40%) answered Yes

Entry

Euclid's algoritm for greatest common denominator

Jul 5th, 2000 10:01
Nathan Wallace, Hans Nowak, Snippet 208, Tim Peters


"""
Packages: maths
"""
#!/usr/local/bin/python
#!c:\python\python.exe
import sys
import os
import string
import math
def exgcd ( u, v, pr = 0 ) : 
    """An implementation of the Extended Euclidean algorithm for finding 
    greatest common denominator, called `The Pulverizer', or 'kuttaka'.  
    (See Knuth, V2 (3d Ed.), 4.5.2.  Here is Knuth's description of the 
    Pulverizer:
    This extension of Euclid's algorithm can be described conveniently in 
    vector notation:
    Algorithm X (Extended Euclid's algorithm). Given nonnegative integers u
    and v, this algorithm determines a vector (u1, u2, u3) such that uu1 +
    uu2 = u3 = gcd(u, v). The computation makes use of auxiliary vectors
    (v1, v2, v3), (t1, t2, t3); all vectors are manipulated in such a way
    that the relations 
    ut1 + vt2 = t3; uu1 + vu2 = u3; uv1 + vv2 = v3; 
    hold throughout the calculation. 
    X1. [Initialize.]
    Set (u1, u2, u3)  (1, 0, u), (v1, v2, v3)  (0, 1, v). 
    X2. [Is v3 = 0?] If v3 = 0, the algorithm terminates. 
    X3. [Divide, subtract.] Set q  u3/v3, and then set 
    (t1, t2, t3)  (u1, u2, u3) - (v1, v2, v3)q, 
    (u1, u2, u3)  (v1, v2, v3), (v1, v2, v3)  (t1, t2, t3). 
    Return to step X2. 
    For example, let u = 40902, v = 24140. At step X2 we have 
    q    u1    u2    u3      v1   v2     v3
    0     1    0  40902      0    1  24140
    1     0    1  24140      1   -1  16762
    1     1   -1  16762     -1    2   7378
    2    -1    2   7378      3   -5   2006
    3     3   -5   2006    -10   17   1360
    1   -10   17   1360     13  -22    646
    2    13  -22    646    -36   61     68
    9   -36   61     68    337 -571     34
    2   337 -571     34   -710 1203      0
    The solution is therefore
    337 · 40902 -571 · 24140 = 34 = gcd(40902, 24140). 
    If the pr argument is non-zero, then exgcd() will print the intermediate 
    values for each step."""
    u1, u2, u3 = 1, 0, u
    v1, v2, v3 = 0, 1, v
    q = 0
    if pr != 0 :
        print "q %2d   u1 %4d u2 %4d u3 %6d   v1 %4d v2 %4d v3 %6d" % \
	    ( q, u1, u2, u3, v1, v2, v3 )
    while v3 > 0 :
        q = u3 / v3
        t1, t2, t3 = ( u1 - ( v1 * q ) ), ( u2 - ( v2 * q ) ), ( u3 - ( v3 * q ) )
        u1, u2, u3 = v1, v2, v3
        v1, v2, v3 = t1, t2, t3
	if pr != 0 :
            print "q %2d   u1 %4d u2 %4d u3 %6d   v1 %4d v2 %4d v3 %6d" % \
	        ( q, u1, u2, u3, v1, v2, v3 )
    return u3, u1, u2
if __name__ == "__main__" :
    u = 40902
    v = 24140
    if len ( sys.argv ) > 1 :
	if len ( sys.argv ) > 2 :
	    u = string.atoi ( sys.argv[ 1 ] )
	    v = string.atoi ( sys.argv[ 2 ] )
	else :
	    print "Two integer arguments required."
	    sys.exit ( -1 )
    u3, u1, u2 = exgcd ( u, v, 1 )
    print "The answer is %d" % ( u3 )
    print "u1 %d * u %d        u2 %d * v %d" % ( u1, u, u2, v )
    print " = %d                = %d" % ( u1 * u, u2 * v )
    print "         a = %d" % ( ( u1 * u ) + ( u2 * v ) )
    print "u3 %d u1 %d u2 %d" % ( u3, u1, u2 )