辗转相除的原理是: if 0 == A % x && 0 == B % x ; then 0 == (A - B) % x ; 因此, 算法通过求这个数的余数, 用小者再和余数求余, 不断迭代, 因而缩小 gcd 的范围, 直到有一次能够找到 gcd 为止, 此时 0 == 任何余数 % gcd 成立.
// tmp.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int gcd(int num1, int num2)
{
// Any of each is 0, the result must be zero.
if (0 == num1 || 0 == num2)
{
return 0;
}//if
// This is based on a fact that
// if
// A % x = 0 and B % x = 0
// then
// ( A - B ) % x = 0
// so, we just reduce the scope to get the result
// step by step.
int remainder = num2;
int remainder1 = 0; // num1 % remainder: reduce once redundant evaluated
int temp = 0; // Reduce once redundant evaluated
int cnt = 0; // Counter how many times
// arithmetics have been execute.
while (temp = 0 == (remainder1 = num1 % remainder) ?
num2 % remainder : remainder1)
{
remainder = temp;
cnt++;
}//while
cout <<cnt <<" times' arithmetics executed" <<endl;
return remainder;
}
int gcd_classic(int a, int b)
{
int c = a < b ? a : b; // The greatest common divisor.
int tmp = 0; // Reduce reduplicated evaluation of 'a % b'.
int cnt = 0; // Counter how many times
// arithmetics have been execute.
while (0 != (tmp = a % b))
{
c = tmp;
a = b;
b = c;
cnt++;
}
cout <<cnt <<" times' arithmetics executed" <<endl;
return c;
}
int gcd_error(int num1, int num2);
int main()
{
// 经典的'辗转相除法'语法简洁, 效率很高.
// 我尝试了一个自己的算法, 暂且称为'缩减算法', 是
// 看了'辗转相除法'后想尝试一种更好记忆的算法而产生的.
// 在尝试的过程中还因为一些错误误以为自己发现了更好的算法.
// 想来这一下午没白费, 至少对'辗转'有了更深刻的印象和理解.
// 之前错误的算法我列在最后了. 以供参考.
cout <<"Result: " <<gcd(1448442, 10024) <<endl;
cout <<"Result: " <<gcd_classic(1448442, 10024) <<endl;
cout <<"Error Result: " <<gcd_error(1448442, 10024) <<endl;
return 0;
}
int gcd_error(int num1, int num2)
{
// Any of each is 0, the result must be zero.
if (0 == num1 || 0 == num2)
{
return 0;
}//if
int remainder = num2;
int cnt = 0; // Counter how many times
// arithmetics have been execute
while (0 != num1 % remainder) // Error occur here!
{
remainder = num1 % remainder;
cnt++;
}//while
cout <<cnt <<" times' arithmetics executed" <<endl;
return remainder;
}