小ワザ
HSPによる再帰呼び出し †
再帰呼び出しとは次のようにある処理の中で再び自分自身を呼び出すことを指す。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
| #module
#deffunc refunc1 int n
if n<0: return mes n
refunc1 n-1 return
#defcfunc refunc2 int n
if n<=0: return n mes refunc2(n-1) return n
#global
refunc1 5 mes refunc2(5)
|
再帰は処理の中で自分自身を再び呼び出すので、誰かが止まるよう注意してやらなければ永遠と自分を呼び出してしまう。
そのため終了条件となるものが必要になり、この終了条件はその処理内容に応じて異なる。
再帰は自分が呼ばれたときのパラメータをスタックに積みながら深度を増していく。
スタックに積みきれなかった時にはスタックオーバーフローとなる。(実際にはネストに制限を持たせている)
このとき使われるスタックは小ワザ/ポインタを使ってのあれこれを参照してください。
+
| | 再帰による文字列の往復表示
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
|
#module
#deffunc uturn_mes var in, var out, int p1
if peek(in,p1) = 0: return poke out, i, peek(in,p1) i++
uturn_mes in, out, i poke out, i, peek(in,p1) i++
return
#deffunc umes str s
s1 = s
sdim buf, strlen(s1)*2+1
i = 0: uturn_mes s1, buf, i poke buf, i, 0
mes buf
return
#global
umes "abc123"
umes "rats & star &"
|
|
+
| | 再帰による階乗の計算
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
| #module
#defcfunc factorial int n
if n <= 1 : return 1 return n * factorial(n - 1) #global
repeat 10
mes ""+cnt+"! = "+factorial(cnt)
loop
|
logmesでデバッグメッセージを残すバージョン↓
「Debugウィンドウを表示」をチェックして実行してください
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-
|
-
|
|
|
!
| #module
#defcfunc factorial int n
logmes "factorical(" + n + ") が呼び出されました"
if n <= 1 {
stt = 1 } else {
f = factorial(n - 1)
stt = n * f logmes "factorical(" + (n - 1) + ") は factorical(" + n + ") に " + f + " を返しました"
}
return stt
#global
repeat 10, 1
logmes "== ▼ factorical("+ cnt +") 開始 ▼ =="
i = factorial(cnt)
mes "" + cnt + "! = " + i
logmes "factorical(" + cnt + ") は " + i + " です"
loop
|
実数の階乗まで拡張したバージョン
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
| #module
#include "hspmath.as" #define sqrtPIdiv2 0.8862269254527580136490837416705
#defcfunc factorial double n
if n=0.0 :return 1.0
if n=0.5 :return sqrtPIdiv2
if (n<0.0)&(n=int(n)) :return 0.0
if n>0.0 :return n*factorial(n-1.0)
x=n+1.0
i=1.0
answer=1.0
do
mul=pow(1.0+1.0/i,x)/(1.0+x/i)
answer*=mul
i+=1.0
until absf(mul-1.0)>DBL_EPSILON
answer*=1.0/x
return answer
#global
|
|