2016-08-11 9 views
3

저는 파이썬에 익숙하지 않아 조금만 노력해 왔지만 문제가 있습니다. 여기 내 코드입니다 :Python의 가변 범위 문제

def collatz(num,ctr): 
    if(num != 1): 
     ctr+=1 
     if(num%2==0): 
      collatz(num/2,ctr) 
     else: 
      collatz(num*3+1,ctr) 
    return ctr 
test=collatz(9,0) 

내가 num에 대한 넣어 숫자를 들어, 항상 1로 나오는 ctr에 대한 예를 들어 90, ctr을 가정 해 봅시다. ctr 변수를 잘못 사용하고 있습니까?

편집 : 함수가 반복되는 횟수를 출력하려고합니다. 따라서 ctr은 각 재귀의 카운터가됩니다.

+0

가 의도 한 결과 무엇이며, 당신이 원하는 이것으로 달성할까요? – harshil9968

+0

'ctr = collatz (num // 2, ctr)'. 또한 파이썬 3에서 작업해야하며'/ 2'는 부동 소수점 나누기입니다. '// 2'는 정수 나누기입니다. –

답변

3

될 것이라고 말했습니다 귀하의 예제에서 변수 ctr은 재귀 호출 스택의 순서 때문에 항상 1이됩니다. ctr 중 하나의 값이 반환되면 호출 스택은 이전 값 ctr을 반환하기 시작합니다. 기본적으로 가장 마지막 재귀 호출에서 가장 높은 값인 ctr이 반환됩니다. 그러나 호출 스택 맨 아래의 메서드 호출은 test에 저장 될 값인 마지막 값을 반환하기 때문에 test은 항상 1이됩니다. 메서드의 총 호출 수가 5 개가되는 collatz에 매개 변수를 입력한다고 가정 해 보겠습니다. 호출 스택에 상관없이, 1 항상 반환됩니다라고 몇 번 collatz

collatz returns ctr --> 5 
collatz returns ctr --> 4 
collatz returns ctr --> 3 
collatz returns ctr --> 2 
collatz returns ctr --> 1 //what matters because ctr is being returned with every method call 

당신이 볼 수 있듯이,이 내려오고 같을 것이다 호출 스택의 맨 아래에있는 호출이 ctr1을 같게 때문에 .

해결 방법은 많은 일이 될 수 있지만 실제로 달성하고자하는 목적에 따라 달라지며 이는 궁금한 점에 분명하게 설명되어 있지 않습니다.

EDIT : ctr이 재귀 호출 횟수가되고 싶다면 을 메서드 호출의 값에 할당하면됩니다.

def collatz(num,ctr): 
    if(num != 1): 
     ctr+=1 
     if(num%2==0): 
      ctr = collatz(num/2,ctr) 
     else: 
      ttr = collatz(num*3+1,ctr) 
    return ctr 
test=collatz(9,0) 
+0

재귀가 어떻게 작동하는지 설명해 주셔서 감사합니다. 나는 지금 훨씬 나아 졌음을 안다. 최종 결과에서 내가 원하는 것을 설명하는 것이 좋지 않아서 질문을 편집 할 것입니다. – Webtron

+0

@Webtron은 내 결과를 처리해야한다고 생각하기 때문에 편집을 확인합니다. –

+0

완벽한 감사합니다! – Webtron

3

재귀 호출로부터받은 값을 다시 ctr로 설정하기 위해 재귀 호출을 변경했습니다. 당신이 그것을 쓴대로, 당신은 재귀에서 돌아온 가치를 폐기하고있었습니다.

def collatz(num,ctr): 
    if(num != 1): 
      ctr+=1 
      if(num%2==0): 
        ctr=collatz(num/2,ctr) 
      else: 
        ctr=collatz(num*3+1,ctr) 
    return ctr 

test=collatz(9,0) 
+0

이것은 동일합니다. 차이점은 무엇입니까? – harshil9968

+1

재귀 호출을 다시 변경하여 재귀 호출에서받은 값을'ctr'으로 설정했습니다. 당신이 그것을 쓴대로, 당신은 재귀에서 돌아온 가치를 폐기하고있었습니다. –

+2

당신은 그 대답에서 단순히 –

0

예 :.

def collatz(number): 

    if number % 2 == 0: 
     print(number // 2) 
     return number // 2 

    elif number % 2 == 1: 
     result = 3 * number + 1 
     print(result) 
     return result 

n = input("Give me a number: ") 
while n != 1: 
    n = collatz(int(n)) 
+0

정확히 묻는 사람이 찾고있는 것은 아닙니다. 그의 함수는 1에 도달하기 전에 몇 번 실행해야하는지 계산하려고 시도합니다. –

-3

당신이 넣어 어떤 번호에서 시작 collatz 시퀀스의 마지막 수를 반환 할 변수는 콜라 츠 추측이 항상 1

+0

수학적으로, 그렇습니다. 그러나이 메소드가 리턴하는 이유는 아닙니다. –

+0

이 함수는 도달 할 단계의 수를 반환해야합니다. * 1. – chepner

0

파이썬의 함수 매개 변수는 참조가 아닌 값으로 전달됩니다. 함수에 숫자를 전달하면 함수는 해당 숫자의 사본을받습니다. 함수의 매개 변수를 수정하는 경우, 그 변화는 함수 밖에 볼 수 없습니다 : 귀하의 경우

def foo(y): 
    y += 1 
    print("y=", y) # prints 11 

x = 10 
foo(x) 
print("x=", x) # Still 10 

을, 가장 직접적인 수정은 전역 변수로 클릭률을 확인하는 것입니다. 매우 추한 이유는 collatz 함수를 다시 호출하기를 원할 경우 글로벌을 다시 0으로 재설정해야하기 때문입니다. 그러나 참조 비트를 제외하고 로직이 정확한지 보여주기 위해이 대안을 보여줍니다. (collatz 함수는 현재 아무것도 반환하지 않으며, 응답은 전역 변수에 있음을주의하십시오.)파이썬은 꼬리 호출 최적화되어 있지 않기 때문에 collatz 순서가 이상 1,000 단계 (이 비단뱀 기본 스택 한계입니다) 인 경우

ctr = 0 
def collatz(num): 
    global ctr 
    if(num != 1): 
     ctr+=1 
     if(num%2==0): 
       collatz(num/2) 
     else: 
       collatz(num*3+1) 

ctr = 0 
collatz(9) 
print(ctr) 

, 현재 재귀 코드는 스택 오버 플로우와 충돌합니다. 재귀 대신 루프를 사용하면이 문제를 피할 수 있습니다. 이것은 또한 문제가있는 전역 변수를 제거하는 데 사용할 수 있습니다. 최종 결과는 내 의견으로는, 좀 더 관용적 인 파이썬입니다 :

def collats(num): 
    ctr = 0 
    while num != 1: 
     ctr += 1 
     if num % 2 == 0: 
      num = num/2 
     else: 
      num = 3*num + 1 
    return ctr 

print(collatz(9)) 

당신이 재귀 함수를 사용하여 고수 할 경우, 그 당신이하려고하는 같은 가변 할당을 사용하지 않는 것이 보통 청소기. 함수를 상태를 수정하는 "서브 루틴"대신에 값을 받고 입력에만 의존하는 결과를 반환하는 수학 함수에 더 가깝게 만듭니다. 이렇게하면 재귀에 대해 추론하는 것이 훨씬 쉬울 수 있습니다. 나는 운동을하지만 재귀 함수는이하는 것입니다의 전형적인 "골격"로이 떠날 경우 기본 케이스와 재귀 경우에 검사 문 :

def collatz(n): 
    if n == 1: 
     return 0 
    else if n % 2 == 0: 
     # tip: something involving collatz(n/2) 
     return #??? 
    else: 
     # tip: something involving collatz(3*n+1) 
     return #???