最大公约数的计算____C++

辗转相除法

        在数学中,辗转相除法,又称欧几里得算法(英语:Euclidean algorithm),是求最大公约数的算法。辗转相除法首次出现于欧几里得的《几何原本》(第VII卷,命题i和ii)中,而在中国则可以追溯至东汉出现的《九章算术》。

        辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数。

        算法的计算过程如下:

        设k表示步骤数(从0开始计数)
每一步的输入是都是前两次计算的非负余数rk1和rk2。因为每一步计算出的余数都在不断减小,所以,rk-1小于rk-2。在第k步中,算法计算出满足以下等式的商qk和余数 rk:
        rk2 = qk*rk1 + rk
其中0 ≤ rk < rk-1。也就是rk-2要不断减去rk-1直到比rk-1小。
为求简明,以下只说明如何求两个非负整数a和b的最大公约数(负数的情况是简单的)。在第一步计算时(k = 0),设r2和r1分别等于a和b,第2步(此时k = 1)时计算r−1(即b)和r0(第一步计算产生的余数)相除产生的商和余数,以此类推。
        如果有a < b,算法的第一步实际上会把两个数字交换,因为这时a除以b所得的商q0会等于0,余数r0则等于a。然后,算法的第二步便是把b除以a,再计算所得之商和余数。所以,对于k ≥ 0总有rk         由于每一步的余数都在减小并且不为负数,必然存在第N步时rN等于0,使算法终止,rn−1就是a和b的最大公约数。其中N不可能无穷大,因为在r0和0之间只有有限个自然数。

具体实现代码如下:

//辗转相除法
int C_commondivisor::div_alg(m_num1, m_num2)
{
	int tmp1 = m_num1;
	int tmp2 = m_num2;
	for (; tmp1 % tmp2 != 0; )
	{
	    tmp1 = tmp1 % tmp2;
	    //tmp1整除以tmp2后,tmp1为两数字间的小数字
	    //以下三句均为实现调换数字的数值,使tmp1为最大数字
	    tmp1 = tmp2 - tmp1;
	    tmp2 = tmp2 - tmp1;
	    tmp1 = tmp1 + tmp2;
	}
	return tmp2;
}

辗转相减法

        辗转相减法(求最大公约数),即尼考曼彻斯法,其特色是做一系列减法,从而求得最大公约数。

        不过,对于我来说感觉就是辗转相除法的“减法”版。

        具体实现如下:

//相减法
int C_commondivisor::phase_sub()
{
	int tmp1 = m_num1;
	int tmp2 = m_num2;
	for (; tmp1 - tmp2 != 0; )
	{
		tmp1 = tmp1 - tmp2;
		//判断两个数的大小,让大数始终为tmp1
		if (tmp2 > tmp1)
		{
		    tmp1 = tmp2 - tmp1;
		    tmp2 = tmp2 - tmp1;
		    tmp1 = tmp1 + tmp2;
		}
	}
	return tmp2;
}

穷举法

        穷举法即将所有的可能的结果从两数之中小的那个数开始,依次减1,然后带入进行验证是否满足被两数相除余数为0,若是找到符合的第一个数字,则即为最大公约数,可以说是最没有效率也是最暴力的办法。

具体实现如下:

//穷举法
int C_commondivisor::exhaustion()
{
	//从两个数字中最小的数字开始,依次判断是否能整除以输入的两个数字,若可以,则输出当前的结果,并结束循环
	int i = 0;
	for (i = m_num2; i <= m_num2; i--)
	{
		//若当前整数可以整除输入的两个数字,则这个数即为最大公约数,终止循环
		if ((m_num1 % i) == 0 && (m_num2 % i) == 0)
		{
			break;
		}
	}
	return i;
}


所有具体的代码如下:

编译运行环境为Visual Studio 2017

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//文件名 : commondivisor.cpp
//创建者 : EL.Gou
//创建日期 : 2017.03.21
//开发环境 : Visual Studio 2017
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include 

using namespace std;

class C_commondivisor {
public:
	C_commondivisor();
	int input();    //获得输入的数字
	int output(int i);    //输出结果
	int mainmenu();    //菜单函数
	int div_alg();    //辗转相除法
	int phase_sub();    //相减法
	int exhaustion();    //穷举法
private:
	int m_num1;
	int m_num2;
	int m_result;    //存储算出的最大公约数
};

C_commondivisor::C_commondivisor()
{
	m_num1 = 0;
	m_num2 = 0;
	m_result = 0;
}

//获得输入函数
int C_commondivisor::input()
{
	cout << "                请输入要计算的一个数字:";
	cin >> m_num1;
	cout << "                请输入要计算的另一个数字:";
	cin >> m_num2;
	cout << "\n\n" << endl;
	//判断两个数字的大小,大的数字赋值给m_num1
	if (m_num2 > m_num1)
	{
		//交换两数的数值
		m_num1 = m_num2 - m_num1;
		m_num2 = m_num2 - m_num1;
		m_num1 = m_num1 + m_num2;
	}
	return 0;
}

//输出结果函数
int C_commondivisor::output(int i)
{
	cout << "\n\n                数字" << m_num1 << "和数字" << m_num2;
	if (i == 2)
	{
		cout << "用相减法计算得到";
	}
	else if (i == 3)
	{
		cout << "用穷举法计算得到";
	}
	else
	{
		cout << "用辗转相除法得到";
	}
	cout << "的最大公约数为:" << m_result << "\n\n\n\n\n\n" << endl;
	return 0;
}

//菜单函数
int C_commondivisor::mainmenu()
{
	cout << "                本程序为计算两个数的最大公约数的程序    " << endl;
	while (true)
	{
		cout << "                辗转相除法请输入”1“" << endl;
		cout << "                相    减   法请输入”2“" << endl;
		cout << "                穷    举   法请输入”3“" << endl;
		cout << "                退           出请输入”0“" << endl;
		cout << "                若输入其他数字,则选择辗转相除法计算" << endl;
	    cout << "\n\n                请 选 择 计 算 方 式 :";
	    int tmp = 0;
		cin >> tmp;
		if (tmp == 1)
		{
			input();
			m_result = div_alg();    //辗转相除法计算
		}
		else if (tmp == 2)
		{
			input();
			m_result = phase_sub();    //相减法计算
		}
		else if (tmp == 3)
		{
			input();
			m_result = exhaustion();    //穷举法计算
		}
		else if (tmp == 0)
		{
			break;    //退出循环,结束程序执行
		}
		else
		{
			input();
			m_result = div_alg();    //若输入不在范围内,则使用辗转相除法计算
		}
		//依据计算输出相应的计算方式及结果
		output(tmp);
	}
	return 0;
}

//辗转相除法
int C_commondivisor::div_alg()
{
	int tmp1 = m_num1;
	int tmp2 = m_num2;
	for (; tmp1 % tmp2 != 0; )
	{
		tmp1 = tmp1 % tmp2;
		//tmp1整除以tmp2后,tmp1为两数字间的小数字
		//以下三句均为实现调换数字的数值,使tmp1为最大数字
		tmp1 = tmp2 - tmp1;
		tmp2 = tmp2 - tmp1;
	    tmp1 = tmp1 + tmp2;
	}
	return tmp2;
}

//相减法
int C_commondivisor::phase_sub()
{
	int tmp1 = m_num1;
	int tmp2 = m_num2;
	for (; tmp1 - tmp2 != 0; )
	{
		tmp1 = tmp1 - tmp2;
		//判断两个数的大小,让大数始终为tmp1
		if (tmp2 > tmp1)
		{
		    tmp1 = tmp2 - tmp1;
		    tmp2 = tmp2 - tmp1;
		    tmp1 = tmp1 + tmp2;
		}
	}
	return tmp2;
}

//穷举法
int C_commondivisor::exhaustion()
{
	//从两个数字中最小的数字开始,依次判断是否能整除以输入的两个数字,若可以,则输出当前的结果,并结束循环
	int i = 0;
	for (i = m_num2; i <= m_num2; i--)
	{
		//若当前整数可以整除输入的两个数字,则这个数即为最大公约数,终止循环
		if ((m_num1 % i) == 0 && (m_num2 % i) == 0)
		{
			break;
		}
	}
	return i;
}

int main(int argc,char** argv[])
{
	C_commondivisor CCD;
	CCD.mainmenu();
	return 0;
}

与以上算法相比,在进行非常大的数字的最大公约数计算时,stein算法是更有效率的算法,具体算法概念及流程可以参考:http://blog.csdn.net/kemlkyo/article/details/22698597

参考资料:wikipedia https://zh.wikipedia.org/wiki/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95#.E6.9C.80.E5.A4.A7.E5.85.AC.E7.BA.A6.E6.95.B0

你可能感兴趣的:(C/C++小程序)