來研究一下最大公約數的性質,我們發現有 g_c_d( k*x,k*y ) = k*g_c_d( x,y ) 這麼一個非常好的性質(證明我就省去了)。說他好是因爲他非常符合我們化小的思想。我們試取 k=2 ,則有 g_c_d( 2x,2y ) = 2 * g_c_d( x,y )。這使我們很快聯想到將兩個偶數化小的方法。那麼一奇一個偶以及兩個奇數的情況我們如何化小呢?
先來看看一奇一偶的情況: 設有2x和y兩個數,其中y爲奇數。因爲y的所有約數都是奇數,所以 a = g_c_d( 2x,y ) 是奇數。根據2x是個偶數不難聯想到,a應該是x的約數。我們來證明一下:(2x)%a=0,設2x=n*a,因爲a是奇數,2x是偶數,則必有n是偶數。又因爲 x=(n/2)*a,所以 x%a=0,即a是x的約數。因爲a也是y的約數,所以a是x和y的公約數,有 g_c_d( 2x,y ) <= g_c_d( x,y )。因爲g_c_d( x,y )明顯是2x和y的公約數,又有g_c_d( x,y ) <= g_c_d( 2x,y ),所以 g_c_d( 2x,y ) = g_c_d( x,y )。至此,我們得出了一奇一偶時化小的方法。
再來看看兩個奇數的情況:設有兩個奇數x和y,似乎x和y直接向小轉化沒有什麼太好的辦法,我們可以繞個道,把x和y向偶數靠攏去化小。不妨設x>y,我們注意到x+y和x-y是兩個偶數,則有 g_c_d( x+y,x-y ) = 2 * g_c_d( (x+y)/2,(x-y)/2 ),那麼 g_c_d( x,y ) 與 g_c_d( x+y,x-y ) 以及 g_c_d( (x+y)/2,(x-y)/2 ) 之間是不是有某種聯繫呢?爲了方便我設 m=(x+y)/2 ,n=(x-y)/2 ,容易發現 m+n=x ,m-n=y 。設 a = g_c_d( m,n ),則 m%a=0,n%a=0 ,所以 (m+n)%a=0,(m-n)%a=0 ,即 x%a=0 ,y%a=0 ,所以a是x和y的公約數,有 g_c_d( m,n )<= g_c_d(x,y)。再設 b = g_c_d( x,y )肯定爲奇數,則 x%b=0,y%b=0 ,所以 (x+y)%b=0 ,(x-y)%b=0 ,又因爲x+y和x-y都是偶數,跟前面一奇一偶時證明a是x的約數的方法相同,有 ((x+y)/2)%b=0,((x-y)/2)%b=0 ,即 m%b=0 ,n%b=0 ,所以b是m和n的公約數,有 g_c_d( x,y ) <= g_c_d( m,n )。所以 g_c_d( x,y ) = g_c_d( m,n ) = g_c_d( (x+y)/2,(x-y)/2 )。
我們來整理一下,對兩個正整數 x>y :
1.均爲偶數 g_c_d( x,y ) =2g_c_d( x/2,y/2 );
2.均爲奇數 g_c_d( x,y ) = g_c_d( (x+y)/2,(x-y)/2 );
2.x奇y偶 g_c_d( x,y ) = g_c_d( x,y/2 );
3.x偶y奇 g_c_d( x,y ) = g_c_d( x/2,y ) 或 g_c_d( x,y )=g_c_d( y,x/2 );
現在我們已經有了遞歸式,還需要再找出一個退化情況。注意到 g_c_d( x,x ) = x ,我們就用這個。
/* return the greatest common divisor of x and y */
{
int factor = 0;
int temp;
if ( x < y )
{
temp = x;
x = y;
y = temp;
}
if ( 0 == y )
{
return 0;
}
while ( x != y )
{
if ( x & 0x1 )
{/* when x is odd */
if ( y & 0x1 )
{/* when x and y are both odd */
y = ( x - y ) >> 1;
x -= y;
}
else
{/* when x is odd and y is even */
y >>= 1;
}
}
else
{/* when x is even */
if ( y & 0x1 )
{/* when x is even and y is odd */
x >>= 1;
if ( x < y )
{
temp = x;
x = y;
y = temp;
}
}
else
{/* when x and y are both even */
x >>= 1;
y >>= 1;
++factor;
}
}
}
return ( x << factor );
}
Stein算法的優勢是不言而喻的,上面的代碼只有位運算和減法,不僅速度加快,而且結局了歐幾里德算法求兩個大數最大公約數的不便。不僅如此,Stein算法還可以很容易的寫成彙編語言實現。