做文背景:大一学的辗转相除法,可只知其用法(大数不断对小数取余,小数给大数,余数给小数,直到取小数为零后,最后一位被除数(大数)就是最大公约数),并没有真正有哪一次去问问自己为什么得这样做,最后导致想用却忘记怎么用,为此写下个人拙见供自己、大家参考。
设有两数:大数a、小数b以图形示下
它们都有公共的最大约数(Greatest Common Divisor(GCD))r
由于a和b都是r的倍数,所以a还可以写成b+nr即a=b+nr
从上式a=b+nr可以得出a-b还是包含了我们的公约数r(a-b=nr还是r的倍数),换句话求a、b两者的最大公约数可以转化求a-b与b的公约数。
GCD(a, b) =》 GCD(a - b, b)
第二次 GCD(a - b, b) =》 GCD(a - 2b, b) …
第k次 GCD(a - (k-1)b, b) =》 GCD(a - kb, b)
直到最后不能再减b,也就是a%b的余数b1和b来取最大公约数GCD(a%b, b)
以此推出求GCD(a, b)可以已转化求GCD(b,a % b)(换位保证参数一、二永远是大数在前,小数在后)
直到最后GCD(a, b)中b 等于 0 ,最后最大公约数就是我们的a(注意a、b是不断在变的)。
最后写出程序:
int GCD(int n, int m)
{
//大数a 小数b
if(b == 0) //余数为零结束,任何自然数与零取GCD任然是其本身
return a;
else
return GCD(b, a % b); //当a小于b时a、b可换位
// return b == 0 ? a : GCD(b, a % b); //简化
}
运行结果
只有知其然,往后想用也就不会烦于(我好像又忘了)。
重要文献链接: https://blog.csdn.net/weixin_45850035/article/details/114681895