5

我正在尝试使用 F# 懒惰地创建一个序列。

序列定义如下:

三角形数列的第 n 项由下式给出, tn = ½n(n+1);所以前十个三角形数是:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

这是我到目前为止所拥有的,但它似乎不起作用:

let tri_seq = 1.0 |> Seq.unfold (fun x -> match x with                                         
                                          | _ -> Some (x, 0.5*x*(x + 1.0)))

非常感谢谁能帮我弄清楚展开的工作原理。谢谢

编辑:我将第一个答案标记为正确,但它不起作用,但是我稍微修改了它并且它起作用了。

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0),x + 1.0))
4

4 回答 4

8

match首先,如果你只有一个案例,为什么要使用?

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (x, 0.5 * x * (x + 1.0)))

第二,什么“似乎不起作用”?你知道你产生了一个无限的列表吗?

/编辑:为了完整起见,这是正确的解决方案,OP发现了自己并作为评论发布:

let tri_seq = 
    1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0))
于 2009-02-10T18:57:32.447 回答
4

Brian 发布的代码的另一种替代方法是使用递归而不是命令式“while”循环:

let tri = 
  let rec loop(n, diff) = seq { 
    yield n        
    yield! loop(n + diff, diff + 1.0) }
  loop(1.0, 2.0)
printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)

它的效率要低得多(所以你必须在这里小心一点......),但它是更惯用的功能解决方案,因此可能更容易看到代码的作用。

于 2009-02-10T23:51:19.900 回答
2

这是一个替代方案:

let tri = seq {
    let n = ref 1.0
    let diff = ref 2.0
    while true do
        yield !n
        n := !n + !diff
        diff := !diff + 1.0
    }

printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)
于 2009-02-10T19:12:06.717 回答
1

我知道这是一个很老的问题,但是当您确定 x * (x + 1) 是偶数并且确实可以被 2 整除时,我无法弄清楚为什么要使用浮点数。所以我会简单地使用这个(不多我知道区别,但至少你有一个 int seq):

let tri_seq = 1 |> Seq.unfold (fun x -> Some (x * (x + 1) / 2 , x + 1)) 

tri_seq |> Seq.take 6 |> Seq.toList //[1; 3; 6; 10; 15; 21]

小提琴

(当然,除非你处理大量数字......)

于 2016-05-08T07:02:11.170 回答