如何表达阶乘 n!使用 F# 函数、递归函数还是其他函数?
自然数(大于或等于 0
的任何数字)的阶乘是该数字乘以自身的阶乘减一,其中 0
的阶乘定义为 <代码>1。
例如:
0! = 1
1! = 1 * 0!
2! = 2 * 1!
3! = 3 * 2!
4! = 4 * 3!
5! = 5 * 4!
另一种写法是将 1
和 n
之间的所有自然数相乘,得到 n!
:
5! = 1 * 2 * 3 * 4 * 5
我如何用F# 中的递归函数?我应该用递归函数来实现吗?
//Factorials!
let factorial n =
result = ?
A factorial of a natural number (any number greater or equal than 0
) is that number multiplied by the factorial of itself minus one, where the factorial of 0
is defined as 1
.
For example:
0! = 1
1! = 1 * 0!
2! = 2 * 1!
3! = 3 * 2!
4! = 4 * 3!
5! = 5 * 4!
Another way of writing this is to multiply all natural numbers between 1
and n
for n!
:
5! = 1 * 2 * 3 * 4 * 5
How can I express this with a recursive function in F#? And should I do it with a recursive function?
//Factorials!
let factorial n =
result = ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如何,选项 1:
如何,选项 2(尾递归,编译成循环):
应该:不,请参阅我的答案:
F# 中的While 或尾递归,什么时候使用什么?
我主张经常避免迭代和递归,而选择高阶函数。但如果您刚刚开始,也许还不用太担心这个建议。 (但然后参见@ChaosPandion的答案,或者例如
甚至:
How, option 1:
How, option 2 (tail recursive, compiled into a loop):
Should: no, see my answer to:
While or Tail Recursion in F#, what to use when?
where I advocate often avoiding both iteration and recursion in favor of higher-order functions. But if you're just getting started, maybe don't worry too much about that advice yet. (But then see e.g. @ChaosPandion's answer, or e.g.
Or even:
这是另一个例子:
这个例子可能更清楚一些:
Here is another example:
This example might be a bit clearer:
Brian 的答案是最实用的,但这里是连续传递风格的解决方案:
Brian's answers are most practical, but here is the solution in continuation passing style:
首先,要定义递归函数,您可以使用
let rec
而不是let
(因为let
不允许您引用您递归定义的函数)。要递归地定义阶乘函数,最简单(但不是最有效)的方法是使用阶乘函数的标准数学定义。
更有效的方法是定义一个尾递归辅助函数,它采用第二个参数来存储迄今为止计算的结果。
First of all, to define a recursive function, you'd use
let rec
instead oflet
(becauselet
does not allow you to refer to the function you're defining recursively).To define the factorial function recursively, the easiest (but not most efficient) way would be to use the standard mathematical definition of the factorial function.
A more efficient approach would be to define a tail-recursive helper function taking a second argument which stores the result calculated thus far.
我最喜欢的递归序列 F# 解决方案是...无限尾递归序列!:
我在这里使用 BigIntegers,因为阶乘序列增长得如此之快(继续,尝试第 20,000 项)。
我总体上同意 Brian 的建议,即尽可能在迭代循环或递归循环(尾递归 + 累加器)上使用高阶函数。但我认为在这种情况下,我所展示的无限序列更加灵活,因为它生成阶乘序列的所有项,直到所需的项 (
factTake
),并且每个项只需要一个乘法步骤(n*(n-1))。然而,如果您想要使用折叠解决方案的前 n 项,则每个计算都将独立完成,并且不会从之前的计算中受益。My favorite F# solution to recursive sequences is... infinite, tail-recursive sequences!:
I'm using BigIntegers here since the factorial sequence grows so quickly (go ahead, try the 20,000th term).
I generally agree with Brian's advice to use higher-order functions over iterative loops or recursive loops (tail-recursion + accumulator) whenever possible. But I think in this case, an infinite sequence as I've shown is more flexible since it produces all terms of the factorial sequence up to the desired term (
factTake
), and each term only requires only one multiplication step (n*(n-1)). Whereas, if you wanted the first n terms using a fold solution, each calculation would be done independently and wouldn't benefit from the previous calculation.这是一个更简单的实现
并进行测试
Here is a simpler implementation
And to test