2014-12-18 5 views
3

이것은 동전 교환 방법을 계산할 수있는 재귀 함수이며 완벽하게 작동 할 수 있습니다.재귀에서이 두 가지 방법의 차이점은 무엇입니까?

/*** WAY 2 ***/ 
return (s.stk[++s.top] = k, cc(n - d[k - 1], k)) + (s.top--, cc(n, k - 1)); 
//  |<-----    A    ----->| |<----- B ----->| 

그들은 해당되지 않습니다 다음과 같이 내가 두 의견 사이의 코드를 변경하는 경우

int cc(int n, int k) 
{ 
    if (n < 0 || k == 0) 
    return 0; 
    else if (n == 0) 
    return 1; 
    else 
    { 
    /*** WAY 1 : START ***/ 
    s.stk[++s.top] = k; 
    int tmp = cc(n - d[k - 1], k); 
    s.top--; 
    return tmp + cc(n, k - 1); 
    /*** WAY 1 : END ***/ 
    } 
} 

하지만, 왜 그것이 잘못된 답을 얻기 시작?

P. 그런 식으로 작성하는 것이 좋은 방법은 아니지만 (방법 2), 나는 그것이 왜 효과가 없는지 궁금합니다.

편집 :

우리가 A 또는 B 먼저 할 것인지, 내가 어떤 실험을하려고 노력 모르겠어요하지만.

결론은 return A+B;도 아니고 return B+A;도 올바른 답을 얻을 수 없다는 것입니다.

+1

그렇지 않습니다. 또한이 코드는 완성 된 코드이므로 스택 오버플로가 아닌 코드 검토에이 코드를 넣으십시오. – bobtheboy

+0

UB로 보입니다 (정의되지 않은 동작). – BLUEPIXY

+0

왜? 이 코드에는 UB가 있습니까? –

답변

2

자세한 내용은 @delnan에서 제공하는 "정의되지 않은 동작 및 순서 포인트"링크를 참조하십시오. 그러나 가장 단순한 설명은 A + B 사이에 시퀀스 포인트가 없다는 것입니다. 따라서 A와 B 중 어느 것이 먼저 평가 될지에 대한 보장이 없습니다. 그렇기 때문에 웨이 1과 웨이 2는 동등하지 않습니다. 귀하의 경우에는

:

A = (s.stk[++s.top] = k, cc(n - d[k - 1], k)) 
B = (s.top--, cc(n, k - 1)) 

지금, CC에 재귀 호출(), 때로는 경로 A의 (안 런타임에 컴파일시에 결정)하고 때로는 같이 경로 B.에 무작위로 발생합니다 전화의 순서가 엉망이됩니다.

일련 번호와 인수를 새 줄에 인쇄하는 print 문을 함수 맨 위에 추가 할 수 있습니다. 그런 다음 같은 초기 데이터를 사용하여 way 1 및 way 2로 실행하십시오. 두 개의 텍스트 파일에 출력을 수집하십시오. 이 두 파일을 서로 비교하고 어디서 잘못되는지보십시오.

+0

좋은 점. A 나 B가 먼저 할 지 모르지만 몇 가지 실험을 시도했습니다. 'return A + B'도 아니고'return B + A'도 올바른 답을 얻을 수 없습니다. –

+0

시퀀스 포인트는 어느 것을 먼저 실행하는지 보증하지 않습니다. (즉,/또는 아닙니다). 시퀀스 포인트가 없다는 것은 동작이 * 완전히 * 정의되지 않았 음을 의미합니다. –

+1

@OliverCharlesworth이 경우 정의되지 않은 부분이 아닌가? A보다 먼저 B를 계산할지 또는 A 앞에 B를 계산할지 결정하는 것입니다. – RD445

관련 문제