我在F#中完成了第七个欧拉问题*,但对我的不满意
实现。在函数primes
中,我创建了一个我估计包含第10,001个素数的序列。当我尝试使用Seq.initInfinite懒惰地生成候选素数时,我的代码只是在抛出内存异常之前挂起。
有人可以建议我用延迟生成的序列替换文字序列,一旦找到所需的素数,该序列会被短路吗?
let isPrime n =
let bound = int (sqrt (float n))
seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)
let primeAsync n =
async { return (n, isPrime n)}
let primes =
{1..1000000}
|> Seq.map primeAsync
|> Async.Parallel
|> Async.RunSynchronously
|> Array.filter snd
|> Array.map fst
|> Array.mapi (fun i el -> (i, el))
|> Array.find (fun (fst, snd) -> fst = 10001)
primes
*“通过列出前六个素数:2,3,5,7,11和13,我们可以看到第6个素数是13.什么是第10,001个素数?”
答案 0 :(得分:2)
我认为问题在于Async.RunSynchronously是不是懒惰并且试图评估整个无限序列。虽然有更好的解决方案,但你的算法足够快,所以你甚至不需要并行化;这非常有效:
open System
let isPrime n =
let bound = n |> float |> sqrt |> int
seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)
let prime =
Seq.initInfinite ((+) 2)
|> Seq.filter isPrime
|> Seq.skip 10000
|> Seq.head
答案 1 :(得分:2)
一旦将序列提供给Async.Parallel
,序列就会被“提升”。如果要最小化内存消耗,请按顺序运行计算或将其拆分为延迟块,每个块中的元素将并行运行。