Prolog 写経記 その 52 fac/2
(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.
- 作者: ボグダンフィリピッチ,中島誠,伊藤哲郎
- 出版社/メーカー: 海文堂出版
- 発売日: 1990/08
- メディア: 単行本
- 購入: 4人 クリック: 33回
- この商品を含むブログ (68件) を見る
今日は
fac/2
を写経します.解説
fac(N, Fact)
はFact
をN
の階乗N! (=1*2*3*…(N-1)*N)
に具体化するか,あるいはFact
がN!
と等しいかどうかを調べる.
ふむ.
再帰の例としてお馴染みの奴ですね.
モード
fac(+, ?).
ふむ.
定義
では,こいつの定義を写経しませう.
fac(0, 1) :- !. fac(N, Fact) :- integer(N), N > 0, M is N - 1, fac(M, F), Fact is N * F, !.
最初の節で,0 の階乗は 1 であるという事実を定義しています.
次の節で 1 より大きな整数の階乗を求めています.
integer(N)
と N > 0
はガード条件ですね.
そして N - 1
の階乗を再帰的に求めてその結果に N を乗じることで N
の階乗を求めています.
注記
引数
N
は正の整数でなくてはならない.負の整数であればfac
は失敗する.N
の値の増加に比べてFact
の値の増加は非常に速いため,たとえfac
が失敗してもオーバーフローか否かを調べること.
失敗しても? オーバーフローすると失敗するの? 失敗した理由か何かを調べられるの?
日本語的には「成功してもオーバーフローか否かを調べること」の方がピンときますが...
例
では使用例を写経しませう.
2 ?- fac(15, F). F = 1.30767e+012 Yes 3 ?- fac(9.1, X). No 4 ?- fac(7, 5040). Yes
最初の例は...
成功しているけれどオーバーフローの例になっているような気のせいが.精度足りてないよね.
まぁ,この程度じゃ甘いという事でしょうか.
そんなわけで (どんなわけで?),もっと N
を増やしてみるテスト.
9 ?- fac(200, F). ERROR: Arithmetic: evaluation error: `float_overflow'
float としてオーバーフローすると失敗します.
この場合にオーバーフローか否かってどうやって調べるの?
やっぱり注記は「成功してもオーバーフローか否かを調べること」だと思うなぁ.
そんなわけで (どんなわけで?),それも述語に組み込んでみるテスト.
fac(0, 1) :- !. fac(N, Fact) :- integer(N), N > 0, M is N - 1, fac(M, F), Fact is N * F, !, integer(Fact).
お試し.
13 ?- fac(10, F). F = 3628800 Yes 14 ?- fac(50, F). No
悪くない感じ.