欧几里得辗转相除java_2019-02-27 辗转相除(数学证明及算法)

1.概述

辗转相除,又称欧几里得算法,用于求最大公约数

Java实现如下:

//循环实现

private static int gcd(int a, int b) {

int temp = 0;

while(b != 0){

// 换位

temp = a % b;

a = b;

b = temp;

}

return a;

}

//递归实现

int gcd(int a, int b) {

return b == 0 ? a : gcd(b, a % b);

}

这个算法实现很简单,但是这么难理解可是让人“辗转”呀

那到底是什么样子呢?我们以递归的代码来分析。

首先我们证明一个东西

求证:gcd(m,n)=gcd(n,b)

其中

m和n是两个数,gcd(m,n)表示m和n的最大公约数

设a , b分别是m除以n的商和余数,即m=n * a+b。

证明:

设c=gcd(m,n), d=gcd(n,b)

∵ c为m和n的公约数,

∴ m能被c整除,n也能被c整除

∴ n * a可以被c 整除 【注1】

∴ m - n * a 也能被c整除 【注2】

∵ 题目条件m=n * a+b

∴ m - n * a = b

∴ c为n和b的公约数

∵d为n和b的最大公约数

∴ c <= d 【注3】

∵ d为n和b的公约数

∴ n能被d整除,b也能被d整除

∴ n * a 能被d整除 【注1】

∴ n * a + b 能被d整除,根据题目条件,也即m能被d整除

∴ d为m和n的公约数

∵ c为m和n的最大公约数

∴ d <= c

∴ 综上,d = c

即gcd(m,n)=gcd(n,b) 证毕

【注1】:

n / c = x (其中x为整数)

n * a / c = x * a (a也为整数)

即n能被c整除,n*a也能

【注2】

m ÷ c = x1 (x1为整数)

n * a ÷ c = x * a(x,a为整数)

m ÷ c - n * a ÷ c = x1 - x * a (结果也为整数)

【注3】

注意公约数与最大公约数之间的区别。

如第一段证明,我们所求只能的c是n和b的公约数,但不能下定论说c是最大公约数。

2.求解算法

有了上面的证明过程,我相信你已经明白了算法的内含。

//递归实现

int gcd(int m, int n) {

return b == 0 ? m : gcd(n, m % n);

}

因为gcd(m,n)=gcd(n,b)啊,

所以我们求m和n的公约数,只需要求n和b(即m % n)的即可

那什么时候是个头呢? 应该是 b = 0的时候,b是个余数,余数都等于0了就是最简状态了,而且下一步0不能被当作分母来运算,这就标志着算法的结束。

而此时最简状态的 m(形参) 即是最大公约数。

更深入的理解 当 m % n = 0,(这里的m,n指的是形参)即 m 是 n 的倍数时,此时,n 就是 m 的最大公约数 。(形参中对应m,好绕好绕……)

同样,循环算法也是类似的道理。

注:你不必管m ,n谁大谁小,因为有个辗转的过程,他们会自动调整。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值