101 lines
No EOL
16 KiB
HTML
101 lines
No EOL
16 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<title>CLiki: Factorial</title>
|
|
<link rel="alternate" type="application/atom+xml" title="ATOM feed of edits to current article"
|
|
href="https://www.cliki.net/site/feed/article.atom?title=Factorial">
|
|
<link rel="stylesheet" href="static/css/style.css">
|
|
<link rel="stylesheet" href="static/css/colorize.css">
|
|
</head>
|
|
|
|
<body>
|
|
<span class="hidden">CLiki - Factorial</span>
|
|
<div id="content"><div id="content-area"><div id="article-title">Factorial</div><div id="article">The <a href="Factorial.html" class="internal">Factorial</a> of <i>n</i> is the product of all the integers between 1
|
|
and <i>n</i> inclusive. Outside of <a href="mathematics.html" class="category">mathematics</a>, it is a common example to explain recursion.<p><div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> fact <span class="paren2">(<span class="nonparen">n</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_zerop.html" class="symbol">zerop</a> n</span>)</span>
|
|
1
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> n <span class="paren4">(<span class="nonparen">fact <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1-</a> n</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
</span></div>
|
|
Of course, the code here only works for non-negative integers.<p>Here's an iterative implementation:
|
|
<div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> fact <span class="paren2">(<span class="nonparen">n</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_check-type.html" class="symbol">check-type</a> n <a href="https://www.cliki.net/site/HyperSpec/Body/typ_unsigned-byte.html" class="symbol">unsigned-byte</a></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_loop.html" class="symbol"><i><span class="symbol">loop</span></i></a> for i from 0 to n
|
|
for fact = 1 then <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> fact i</span>)</span>
|
|
finally <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_return.html" class="symbol">return</a> fact</span>)</span></span>)</span></span>)</span>
|
|
</span></div><p>CPS:
|
|
<div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> fact <span class="paren2">(<span class="nonparen">x</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="symbol"><i><span class="symbol">labels</span></i></a> <span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen">fact-aux <span class="paren5">(<span class="nonparen">n k</span>)</span>
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren6">(<span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_zerop.html" class="symbol">zerop</a> n</span>)</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> k 1</span>)</span></span>)</span>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
|
|
<span class="paren1">(<span class="nonparen">fact-aux <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1-</a> n</span>)</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren3">(<span class="nonparen">m</span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> k <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> m n</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_check-type.html" class="symbol">check-type</a> x <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/syscla_integer.html" class="symbol">integer</a> 0 <a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a></span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen">fact-aux x #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_identity.html" class="symbol">identity</a></span>)</span></span>)</span></span>)</span>
|
|
</span></div><p><hr>
|
|
There's less wrong with the above than there used to be. It is now the case that these functions simply behave in odd ways when given negative or non-integers; and of course the recursive (first) definition can still overflow the stack.<p>I still prefer my take, of course...:
|
|
<div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> fact <span class="paren2">(<span class="nonparen">n</span>)</span>
|
|
<span class="comment">;; in a _(declarations-are-assertions) compiler like _(CMUCL) or _(SBCL),
|
|
</span> <span class="comment">;; I might write (_H(DECLARE) (TYPE UNSIGNED-BYTE N)) here.
|
|
</span> <span class="paren2">(<span class="nonparen">_H<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_check-type.html" class="symbol">check-type</a></span>)</span> n _H<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/typ_unsigned-byte.html" class="symbol">unsigned-byte</a></span>)</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen">result 1</span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/sym_declare.html" class="symbol">declare</a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_type.html" class="symbol">type</a> <a href="https://www.cliki.net/site/HyperSpec/Body/typ_unsigned-byte.html" class="symbol">unsigned-byte</a> result</span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_docm_dost.html" class="symbol">do</a> <span class="paren4">(<span class="nonparen"><span class="paren5">(<span class="nonparen">i n <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1-</a> i</span>)</span></span>)</span></span>)</span>
|
|
<span class="paren4">(<span class="nonparen"><span class="paren5">(<span class="nonparen">= i 0</span>)</span> result</span>)</span>
|
|
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> result <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> result i</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
</span></div>-- <i><a href="Christophe.html" class="internal">Christophe</a></i><p>Are the HyperSpec references intentional here? -- <a href="Roland Kaufmann.html" class="internal">Roland Kaufmann</a><p>Well, I put them in because people might be interested in the difference between <a href="https://www.cliki.net/site/HyperSpec/Body/mac_check-type.html" class="hyperspec">CHECK-TYPE</a> and <a href="https://www.cliki.net/site/HyperSpec/Body/sym_declare.html" class="hyperspec">DECLARE</a>, and might want to look them up. -- (Christophe)<p><div class="code"><span class="nonparen"><span class="comment">;; A tail-recursive version, w/o an auxiliary function, inspired by Winston's fibonacci function in Lisp, 3rd edition
|
|
</span><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> fact <span class="paren2">(<span class="nonparen">n &optional <span class="paren3">(<span class="nonparen">so-far 1</span>)</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren3">(<span class="nonparen"><= n 1</span>)</span>
|
|
so-far
|
|
<span class="paren3">(<span class="nonparen">fact <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_-.html" class="symbol">-</a> n 1</span>)</span> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> n so-far</span>)</span></span>)</span></span>)</span></span>)</span>
|
|
</span></div><p>--<i>Above function overflows stack on Lispworks.</i>
|
|
--<i>I also use Lispworks (LWM 4.4.5). I don't have any issues with this function, once compiled, for values up to 10000. It seems to hog the machine for (fact 100000), no doubt understandably. Olivier </i>
|
|
--<i>If the result is not diaplayed, (fact 10000) takes 0.5 sec. and (fact 100000) takes 69 sec. on 1.8 MHz G5</i><p><div class="code"><span class="nonparen"><span class="comment">;; Factorial using anonymous recursive function
|
|
</span><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> <span class="paren2">(<span class="nonparen"><span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren4">(<span class="nonparen">f</span>)</span> #'<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren5">(<span class="nonparen">n</span>)</span> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> f f n</span>)</span></span>)</span></span>)</span>
|
|
#'<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren4">(<span class="nonparen">f n</span>)</span>
|
|
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren5">(<span class="nonparen">= n 0</span>)</span>
|
|
1
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> n <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> f f <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_-.html" class="symbol">-</a> n 1</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
x</span>)</span>
|
|
</span></div><p><hr>
|
|
Here's another iterative implementation:<p><div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> factorial<span class="paren2">(<span class="nonparen">x</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_reduce.html" class="symbol">reduce</a> '<a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_loop.html" class="symbol"><i><span class="symbol">loop</span></i></a> for a from x downto 1 collect a</span>)</span></span>)</span></span>)</span>
|
|
</span></div></div></div>
|
|
<div id="footer" class="buttonbar"><ul><li><a href="Factorial.html">Current version</a></li>
|
|
<li><a href="https://www.cliki.net/site/history?article=Factorial">History</a></li>
|
|
<li><a href="https://www.cliki.net/site/backlinks?article=Factorial">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=Factorial&from-revision=3556340924">Edit</a></li><li><a href="https://www.cliki.net/site/edit-article?create=t">Create</a></li></ul></div>
|
|
</div>
|
|
<div id="header-buttons" class="buttonbar">
|
|
<ul>
|
|
<li><a href="https://www.cliki.net/">Home</a></li>
|
|
<li><a href="https://www.cliki.net/site/recent-changes">Recent Changes</a></li>
|
|
<li><a href="CLiki.html">About</a></li>
|
|
<li><a href="Text Formatting.html">Text Formatting</a></li>
|
|
<li><a href="https://www.cliki.net/site/tools">Tools</a></li>
|
|
</ul>
|
|
<div id="search">
|
|
<form action="https://www.cliki.net/site/search">
|
|
<label for="search_query" class="hidden">Search CLiki</label>
|
|
<input type="text" name="query" id="search_query" value="" />
|
|
<input type="submit" value="search" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div id="pageheader">
|
|
<div id="header">
|
|
<span id="logo">CLiki</span>
|
|
<span id="slogan">the common lisp wiki</span>
|
|
<div id="login"><form method="post" action="https://www.cliki.net/site/login">
|
|
<label for="login_name" class="hidden">Account name</label>
|
|
<input type="text" name="name" id="login_name" class="login_input" />
|
|
<label for= "login_password" class="hidden">Password</label>
|
|
<input type="password" name="password" id="login_password" class="login_input" />
|
|
<input type="submit" name="login" value="login" id="login_submit" /><br />
|
|
<div id="register"><a href="https://www.cliki.net/site/register">register</a></div>
|
|
<input type="submit" name="reset-pw" value="reset password" id="reset_pw" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body></html> |