F# 当达到条件时,获取无限序列中的数字计数
我想用函数式的方法来计算,我想有效地计算它们,所以我不想存储序列,只需遍历它并计算数字F# 当达到条件时,获取无限序列中的数字计数,f#,F#,我想用函数式的方法来计算,我想有效地计算它们,所以我不想存储序列,只需遍历它并计算数字 let conjv2 x = let next n = match n%2 with |0 -> n/2 |_ -> n*3+1 Seq.initInfinite next |> Seq.takeWhile(fun n -> n > 1) |> Seq.length 这不起
let conjv2 x =
let next n = match n%2 with
|0 -> n/2
|_ -> n*3+1
Seq.initInfinite next
|> Seq.takeWhile(fun n -> n > 1)
|> Seq.length
这不起作用,对于任何正数都返回0,这是3n+1猜想,我发现很难有效地计算它们,这段代码工作正常,但我想用函数的方式来计算:
let conj x =
let mutable ansa = x
let mutable cycles = 1
while ansa > 1 do
cycles <- cycles+1
ansa <- match ansa%2 with
|0 -> ansa/2
|_ -> ansa*3+1
cycles
let conj x=
设可变ansa=x
设可变圈=1
而ansa>1
周期ansa*3+1
周期
该示例的关键问题是您使用的是Seq.initInfinite
而不是Seq.unfold
调用指定函数,将元素的索引作为参数(0、1、2、…)Seq.initInfinite
使用上一次迭代生成的状态调用指定函数Seq.unfold
x
,因此您的函数最终是'a->int
,而不是您所期望的int->int
——这很好地表明存在错误
要解决此问题,请尝试以下方法:
let conjv2 x =
let next n = match n%2 with
|0 -> n/2
|_ -> n*3+1
Seq.unfold (fun st -> let n = next st in Some(n, n)) x
|> Seq.takeWhile(fun n -> n > 1)
|> Seq.map (fun v -> printfn "%A" v; v)
|> Seq.length
传递给unfold
的函数需要返回一个带有新状态的选项&一个要发出的值。为了生成无限序列,我们总是返回Some
,并且发出的值是中间状态
这将返回比原始的
conj
小2的值,因为conj
以1开始(而不是0),并且它还计算最后一个值(在此,我们在ansa=1
之前停止)。因此,您需要在结果中添加2。Seq.unfold(fun st->Some(st,next st))x这很好,但添加了第一个元素,这正是我需要的,但除此之外,谢谢。但是对于效率问题,这仍然比conj慢得多。是否有方法在遍历元素时使序列计数,而不是保存它们然后执行.length?如果在函数中保留“|>Seq.map(fun v->printfn”%a“v;v'),则速度会变慢。我打赌Tomas添加它是为了观察序列的展开,但这不是必需的。