2011-11-19 2 views
7

내가 이런 식으로, 매스 매 티카에서 재귀 계승을 정의한 상상 :Mathematica에서 재귀 함수의 대체가 종료되지 않는 이유는 무엇입니까?

Clear[fact] 
fact[0] = 1 
fact[n_] := n fact[n - 1] 

사실 [10] 평가 기능이 작동하고 종료 있음을 확인합니다.

스테이플 예의 비트이지만이 질문에서 그 목적을 수행합니다. 사실, 제 질문은 일반적으로 재귀 함수 정의와 관련이 있습니다.

: 나는 같은 것을 볼 것으로 예상

$RecursionLimit::reclim: Recursion depth of 256 exceeded. 

:

x fact[x-1] /. x -> 2 

아아, 그것은 재귀 깊이 한계에서 실행 :

은 나뿐만 아니라 종료 다음 교체를 평가 예상

2 fact[2-1] 

또는 값이

(210)
2 

UPDATE : 사실의 또 다른 재귀 정의않습니다 예상대로 작동 :

Clear[fact] 
fact[n_] := If[n < 1, 1, n fact[n - 1]] 

그러나이 사실 (말장난이 ;-)이 더욱 신비 나에게한다 : 그것을 수행하는 이유 순전히 다르게 행동 하는가?

내 질문은 두 가지이다 :

심지어 티카 분명히에서 주장하는 이유 내장 도움과 단서의 순을 검색, 나는 상징적 인 결과를 유지하기보다는 평가, 설명 할 수와
  1. '중급'결과와 잘 종료. 실행 가능한 설명을 모험하는 사람은 누구입니까?

  2. []를 사용하는 대안을 사용하는 것 외에 다른 방법으로 Mathematica가 수행하도록 설득하려면 어떻게해야합니까?

저는이 부분에 당황스럽고, 저를 도와 줄 누군가가 있기를 바랍니다.

/TWAN

답변

6

u[x_] := x; Trace[x*u[x] /. x -> 2]는 노력 먼저 xu[x] 평가한다. 그런 다음 x을 2로 바꾸기 전에 먼저 fact[x-1]을 평가하고 재귀 제한에 도달합니다.

Attributes[ReplaceAll]은 속성이 HoldFirst이 아니므로 첫 번째 인수를 평가하여 시작합니다. 그것이 첫 번째 인수를 보유하고 대체로 예를 들어,

[email protected][Hold[x*fact[x - 1]], x -> 2] 

당신이 의도 한대로 다음, 보류를 해제, 예상 2을 제공합니다.

또 다른 방법은

Unprotect[ReplaceAll] 
SetAttributes[ReplaceAll, HoldFirst] 
ReplaceAll[x*fact[x - 1], x -> 2] 

하지만 이렇게하지 할 수 있습니다.

누군가가 곧 더 나은 설명을 줄 것입니다.

편집 :

Clear[factif] 
factif[n_] := If[n < 1, 1, n factif[n - 1]] 

는 무한 재귀가 발생하지 않는 이유에 대한 추가 질문에 대한 응답 : x<1 평가 할 수 없기 때문에이 방법을 정의 factif[x]If[x < 1, 1, x factif[x - 1]]로 평가합니다. 이 ReplaceAll의 첫 번째 인수의 시도 평가 한 후이 양식에 남아 그렇다면, 대체 당신이 평가하고 있기 때문입니다

+0

아하, 이해할 수있다. Mathematica는 먼저 /의 LHS를 계산한다. _then_이 대체를 수행합니다.그리고 Hold []를 사용하면 '열망하는'평가를 연기 할 수 있습니다. 훌륭한 답변 주셔서 감사합니다. 효과적이고 관련성이 높으며 명확하고 간결합니다! 내 칭찬 – nanitous

+0

@nanitous 건배! 세 가지 대답 중 하나가 질문에 대한 답을하면, 대답을 허용 대답으로 표시하여 맨 위에 나타낼 수 있습니다 (답변자에게 평판이 향상됩니다). – acl

+0

그 점을 지적 해 주셔서 감사합니다! – nanitous

5

등이 발생 교체가 발생

fact[x-1] 

전에. 그냥 fact[x-1]을하면 오류가 발생합니다.

당신은 다음처럼 fact 기능을 수정할 수 있습니다

Clear[fact] 
fact[0] = 1 
fact[n_Integer?Positive] := n fact[n - 1] 

그런 다음 x fact[x - 1] /. x -> 2 반환 2 올바른 보인다.

함수 인수 패턴 fact[n_]이며 극히입니다. 예를 들어 fact[Integrate[Sin[x], x]]과 같은 것을 사용할 수 있습니다. 이는 의도 한 것이 아닐 수 있습니다. fact[n_Integer]을 사용하면 훨씬 정확 해지고 fact 함수가 원하는대로 작동 할 수 있습니다. 당신이 더 나은이 함수를 정의하려면

, 당신은 같은 작업을 수행 할 수 있습니다

fact["x"] 같은 메시지와 함께 실패 할 수 있도록
Clear[fact] 
fact::nicetrybuddy = "fact[``] is not defined."; 
fact[0] = 1 
fact[n_Integer?Positive] := n fact[n - 1] 
fact[n_] := (Message[fact::nicetrybuddy, n]; $Failed) 

:

fact::nicetrybuddy: fact[x] is not defined. 
+0

catch-all 절을 추가하는 좋은 방법입니다! 나는 그 것을 기억해야 할 것이다. – nanitous

1

다른 답변이 정확 : fact은 인수가 대체되기 전에 평가됩니다. 근본적인 문제는 정수 입력을 염두에두고 fact을 정의했으며 비 정수 입력에 대한 종료 조건을 제공하지 않았다는 것입니다. 대신 다음

Clear[fact] 
fact[0] = 1 
fact[n_Integer?Positive] := n fact[n - 1] 

을 한 경우는 양의 정수를 일치하는 뭔가를 할 때까지 fact는 평가되지 않은 남아있을 것입니다.

교체 진술을 Evaluate으로 감싸고 인수를 바꾸면 fact에 대한 정의를 실행해야 할 수도 있습니다.

# fact[#-1]& @ 2 

조기에 평가해서는 안 :

다른 방법은 순수한 기능을 사용할 수 있습니다.

+0

나는 지금 막 큰 시뮬레이션을하고있다. (400,000 Hodrick-Prescott filters!) 그래서 나는 순수한 함수로 마지막 제안을 체크하지 않았다. – Verbeia

+0

나는 이것을 고려했다. 하지만 다른 재귀 함수를 사용해 보았습니다. 목록. 그리고 나는 같은 행동을 만났습니다. 그래서 나는 가능한 한 일반적인 질문을 게시했다. 그러나 예를 들어 다시 구체화합니다. 그 죄송합니다. – nanitous

관련 문제