如何表达阶乘 n!使用 F# 函数、递归函数还是其他函数?

发布于 2024-09-30 16:51:51 字数 444 浏览 9 评论 0原文

自然数(大于或等于 0 的任何数字)的阶乘是该数字乘以自身的阶乘减一,其中 0 的阶乘定义为 <代码>1。

例如:

0! = 1
1! = 1 * 0!
2! = 2 * 1!
3! = 3 * 2!
4! = 4 * 3!
5! = 5 * 4!

另一种写法是将 1n 之间的所有自然数相乘,得到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

人生戏 2024-10-07 16:51:51

如何,选项 1:

let rec factorial n =
    match n with
    | 0 | 1 -> 1
    | _ -> n * factorial(n-1)

如何,选项 2(尾递归,编译成循环):

let factorial n =
    let rec loop i acc =
        match i with
        | 0 | 1 -> acc
        | _ -> loop (i-1) (acc * i)
    loop n 1

应该:不,请参阅我的答案:

F# 中的While 或尾递归,什么时候使用什么?

我主张经常避免迭代和递归,而选择高阶函数。但如果您刚刚开始,也许还不用太担心这个建议。 (但然后参见@ChaosPandion的答案,或者例如

let factorial n = [1..n] |> List.fold (*) 1

甚至:

let factorial n = [1..n] |> List.reduce (*) // doesn't require the 2nd parameter

How, option 1:

let rec factorial n =
    match n with
    | 0 | 1 -> 1
    | _ -> n * factorial(n-1)

How, option 2 (tail recursive, compiled into a loop):

let factorial n =
    let rec loop i acc =
        match i with
        | 0 | 1 -> acc
        | _ -> loop (i-1) (acc * i)
    loop n 1

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.

let factorial n = [1..n] |> List.fold (*) 1

Or even:

let factorial n = [1..n] |> List.reduce (*) // doesn't require the 2nd parameter
坐在坟头思考人生 2024-10-07 16:51:51

这是另一个例子:

let factorial (num:int) =
    seq { for n in [1..num] -> n }
    |> Seq.reduce (fun acc n -> acc * n)

这个例子可能更清楚一些:

let factorial num =
    [1..num] |> Seq.fold (fun acc n -> acc * n) 1

Here is another example:

let factorial (num:int) =
    seq { for n in [1..num] -> n }
    |> Seq.reduce (fun acc n -> acc * n)

This example might be a bit clearer:

let factorial num =
    [1..num] |> Seq.fold (fun acc n -> acc * n) 1
探春 2024-10-07 16:51:51

Brian 的答案是最实用的,但这里是连续传递风格的解决方案:

let rec factorial n = 
  let rec loopk i k = 
    match i with
    | 0 | 1 -> k i
    | _ -> loopk (i-1) (fun r -> k (i * r))
  in loopk n (fun r -> r)

Brian's answers are most practical, but here is the solution in continuation passing style:

let rec factorial n = 
  let rec loopk i k = 
    match i with
    | 0 | 1 -> k i
    | _ -> loopk (i-1) (fun r -> k (i * r))
  in loopk n (fun r -> r)
浅黛梨妆こ 2024-10-07 16:51:51

我如何为此声明一个递归函数?

首先,要定义递归函数,您可以使用 let rec 而不是 let (因为 let 不允许您引用您递归定义的函数)。

要递归地定义阶乘函数,最简单(但不是最有效)的方法是使用阶乘函数的标准数学定义。

更有效的方法是定义一个尾递归辅助函数,它采用第二个参数来存储迄今为止计算的结果。

How would I declare a recursive function for this?

First of all, to define a recursive function, you'd use let rec instead of let (because let 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.

最佳男配角 2024-10-07 16:51:51

我最喜欢的递归序列 F# 解决方案是...无限尾递归序列!:

let factSeq =    
    let rec factSeq m n = 
        seq { let m = m * n
              yield m
              yield! factSeq m (n+1I) }
    seq { yield 1I ; yield 2I ; yield! (factSeq 2I 3I) }

let factTake n = factSeq |> Seq.take n //the first n terms
let fact n = factSeq |> Seq.nth (n-1) //the nth term

我在这里使用 BigIntegers,因为阶乘序列增长得如此之快(继续,尝试第 20,000 项)。

我总体上同意 Brian 的建议,即尽可能在迭代循环或递归循环(尾递归 + 累加器)上使用高阶函数。但我认为在这种情况下,我所展示的无限序列更加灵活,因为它生成阶乘序列的所有项,直到所需的项 (factTake),并且每个项只需要一个乘法步骤(n*(n-1))。然而,如果您想要使用折叠解决方案的前 n 项,则每个计算都将独立完成,并且不会从之前的计算中受益。

My favorite F# solution to recursive sequences is... infinite, tail-recursive sequences!:

let factSeq =    
    let rec factSeq m n = 
        seq { let m = m * n
              yield m
              yield! factSeq m (n+1I) }
    seq { yield 1I ; yield 2I ; yield! (factSeq 2I 3I) }

let factTake n = factSeq |> Seq.take n //the first n terms
let fact n = factSeq |> Seq.nth (n-1) //the nth term

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.

时光无声 2024-10-07 16:51:51

这是一个更简单的实现

let rec bfact (n):bigint = 
    match n with
        | i when i<0 -> bigint.Zero
        | 0 | 1 -> bigint(1)
        | _ -> ( bfact(n-1) * bigint(n) )

并进行测试

bfact(50)

val bfact : n:int -> bigint
val it : bigint =
  30414093201713378043612608166064768844377641568960512000000000000

Here is a simpler implementation

let rec bfact (n):bigint = 
    match n with
        | i when i<0 -> bigint.Zero
        | 0 | 1 -> bigint(1)
        | _ -> ( bfact(n-1) * bigint(n) )

And to test

bfact(50)

val bfact : n:int -> bigint
val it : bigint =
  30414093201713378043612608166064768844377641568960512000000000000
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文