我得到了函数gcd,其定义如下:
def gcd(a, b):
if (0 == a % b):
return b
return gcd(b, a%b)
现在我被要求编写递归函数gcd2(a,b)
,该函数返回三个数字(g, s, t)
的列表,其中g = gcd(a, b)
和g = s*a + t*b
。
这意味着您要在(a and b)
函数中输入两个值gcd(a, b)
。它返回的值等于下一个函数中的g
。
然后将这些相同的a
和b
值调入gcd2(a, b)
。然后使用递归部分来查找s和t的值,以便g = s*a + t*b
。
我不知道如何处理这个因为我无法真正想象“停止条件”会是什么,或者我究竟要通过递归循环来实际查找{{ 1}}和s
。任何人都可以帮助我吗?
答案 0 :(得分:2)
关键的洞察力是我们可以向后工作,在递归中为每个s
和t
找到a
和b
。所以说我们有a = 21
和b = 15
。我们需要使用多个值来完成每次迭代 - a
,b
,b % a
,和 c
其中a = c * b + a % b
。首先,让我们考虑基本GCD算法的每一步:
21 = 1 * 15 + 6
15 = 2 * 6 + 3
6 = 2 * 3 + 0 -> end recursion
所以我们的gcd(g
)是3.一旦我们得到了,我们就确定s
和t
为6和3.为此,我们从{{1}开始},用g
:
(a, b, s, t = 3, 0, 1, -1)
现在我们要消除0期。从基本算法的最后一行,我们知道0 = 6 - 2 * 3:
3 = 1 * 3 + -1 * 0
简化,我们得到
3 = 1 * 3 + -1 * (6 - 2 * 3)
现在我们交换条款:
3 = 1 * 3 + -1 * 6 + 2 * 3
3 = 3 * 3 + -1 * 6
因此3 = -1 * 6 + 3 * 3
和s == -1
有t == 3
和a = 6
。因此,鉴于b = 3
和a
的值,b
应返回gcd2
。
现在我们退回到递归,我们想要消除3个术语。从基本算法的倒数第二行开始,我们知道3 = 15 - 2 * 6.再次简化和交换(慢慢地,以便您可以清楚地看到步骤......):
(3, -1, 3)
因此,对于这种递归级别,我们返回3 = -1 * 6 + 3 * (15 - 2 * 6)
3 = -1 * 6 + 3 * 15 - 6 * 6
3 = -7 * 6 + 3 * 15
3 = 3 * 15 + -7 * 6
。现在我们要消除6个学期。
(3, 3, -7)
瞧,我们已经为21和15计算了3 = 3 * 15 + -7 * (21 - 1 * 15)
3 = 3 * 15 + 7 * 15 - 7 * 21
3 = 10 * 15 - 7 * 21
3 = -7 * 21 + 10 * 15
和s
。
如图所示,递归函数如下所示:
t
请注意,出于我们的目的,使用略有不同的基本案例简化了事情:
def gcd2(a, b):
if (0 == a % b):
# calculate s and t
return b, s, t
else:
g, s, t = gcd2(b, a % b)
# calculate new_s and new_t
return g, new_s, new_t
答案 1 :(得分:1)
基本情况(停止条件)是:
if a%b == 0:
# a = b*k for the integer k=a/b
# rearranges to b = -1*a + (k+1)*b
# ( g = s*a + t*b )
return (b, -1, a/b+1) # (g, s, t)
然而,练习是重写递归部分:
g1, s1, t1 = gcd(b, a%b) # where g1 = s1*b + t1*(a%b)
g, s, t = ??? # where g = s*a + t*b
return (g, s, t)
就g1
,s1
和t1
... 而言,归结为以{{1}为单位重写a%b
}和a
。
答案 2 :(得分:0)
“在Python中写一个递归函数”,至少在CPython中,为此哭泣:注意http://docs.python.org/library/sys.html#sys.getrecursionlimit。在我看来,这是这个问题最重要的答案之一。请自行研究一下这个话题。此外,这个主题可能很有见地:Python: What is the hard recursion limit for Linux, Mac and Windows?
总之,尽可能尝试在Python中使用迭代而不是递归方法。
答案 3 :(得分:0)
它基于Euclidian算法,使用更好的while循环连续递归甚至更好,更少执行
def gcd(m,n):
#assume m>= n
if m <n:
(m,n) = (n,m)
if (m%n) == 0:
return(n)
else:
diff =m-n
#diff >n ?Possible!
return(gcd(max(n,diff),min(n,diff)))
while循环可以更好
def gcd(m,n):
if m<n :
(m,n) =(n,m)
while (m%n) !=0:
diff =m-n
(m,n) =(max(n,diff),min(n,diff))
return(n)