2012-03-16 2 views
6

내가 계획에 Collatz 추측을 작성했습니다 :Scheme에서 스택 오버플로를 일으키는 꼬리 재귀 Collatz 추측이 왜 발생합니까?

(define C 
    (lambda (n) 
    (cond 
    ((eq? n 1) 1) 
    ((even? n) (C (/ n 2))) 
    (else (C (+ (* n 3) 1)))))) 

이 꼬리 재귀 호출이다, 그러나 나는 (C 121)를 호출 할 때 스택 오버 플로우를 얻을 :

guile> (trace C) 
(C) 
guile> (C 121) 
[C 121] 
[C 364] 
[C 182] 
[C 91] 
[C 274] 
[C 137] 
[C 412] 
[C 206] 
[C 103] 
[C 310] 
[C 155] 
[C 466] 
[C 233] 
[C 700] 
[C 350] 
[C 175] 
[C 526] 
[C 263] 
[C 790] 
[C 395] 
[C 1186] 
ERROR: Stack overflow 
ABORT: (stack-overflow) 

왜 적절한 꼬리 재귀입니다 오버플로가 발생 했습니까? 보시다시피, 나는 Guile을 Scheme 인터프리터 (버전 1.8.7)로 사용하고 있습니다. 항상 1을 반환처럼

+0

함수 호출을 추적하지 않으면 어떻게됩니까? 다른 체계 체계를 사용하면 어떻게됩니까? – knivil

+0

추적 기능을 사용할 수 없습니다. 주어진 예제에서는 Racket이 정상적으로 작동합니다. –

+7

이것은 버그 일 수 있습니다. 그 정의는 꼬리 재귀 적으로 보입니다. (대부분의 추적 라이브러리는 tail-recursiveness를 파괴 할 것입니다.) –

답변

2

정의 된 절차는 Racket에서 잘 작동합니다. 그것은 저에게 버그 또는 귀하의 환경에 매우 특정한 버그처럼 보입니다.

거의 확실하게 문제와 관련이 없지만 조금 따기 : (eq? n 1) 대신 숫자로 (= n 1)을 사용하십시오.

0
(define C 
    (lambda (n) 
    (cond 
    ((eq? n 1) 1) 
    ((even? n) (C (/ n 2))) 
    (else (C (+ (* n 3) 1)))))) 

이 보인다 (또는 무한 루프 - 추측이 증명되지 않은 남아있다). 재귀 호출 주위에 (+1 ...)이 숨겨져있는 오류가 있습니까?

관련 문제