F# 此素数分解代码适用于小数字,但失败,大数字出现OutOfMemoryException?

F# 此素数分解代码适用于小数字,但失败,大数字出现OutOfMemoryException?,f#,primes,ml,F#,Primes,Ml,我试图得到一个大数的主因子 let factors (x:int64) = [1L..x] |> Seq.filter(fun n -> x%n = 0L) let isPrime (x:int64) = factors x |> Seq.length = 2 let primeFactors (x:int64)= factors x |> Seq.filter isPrime 这适用于13195,但因600851475143的OutOfMe

我试图得到一个大数的主因子

let factors (x:int64) =
  [1L..x]
  |> Seq.filter(fun n ->  x%n = 0L)

let isPrime (x:int64) = 
 factors x
 |> Seq.length = 2

let primeFactors (x:int64)= 
 factors x 
 |> Seq.filter isPrime
这适用于13195,但因600851475143的OutOfMemoryException而失败


抱歉,如果我遗漏了一些明显的东西,这是我在F#上的第三天,直到今天早上我才知道主要因素是什么。

表达式
[1L..x]
创建了一个列表,在您的示例中,该列表太大,无法存储在内存中

相反,序列是惰性的,因此如果小心使用,可以避免计算整个中间列表。您的代码已经使用了序列,但如前所述,为了避免从列表转换,可以使用大括号:
{1L..x}

使用序列表达式是另一个选项:

let factors (x:int64) = seq {
    for i = 1L to x do
        if x%i = 0L then yield i}

在解决了
OutOfMemoryException
问题后,您的素函数速度非常慢,您可以按照注释中的建议,在找到1与其平方根之间的除数后立即返回
false
,对其进行优化。进一步的优化可以通过将数值除以找到的素数因子来实现,并对素数进行筛选,您还可以查看一些有效的算法。

表达式
[…]
创建指定项的列表。在F#中,
列表可以这样定义:

type List<'t> = 
    | empty
    | item of 't * List<'t>
item(1, item(2, item(3, item(4, item(5, empty)))))
正如您所看到的,对于少量项目来说,这不是问题,但是对于大量项目来说,这最终会耗尽所有可用内存,并导致
OutOfMemoryExcepion
。正如Gustavo所提到的,为了避免这种情况,您可以使用一个序列,它将根据需要创建每个项目,而不是一开始就创建所有项目。这样可以一次减少内存中的内容数量,从而避免出现
OutOfMemoryException


由于您已经在使用
Seq
模块而不是
List
模块(即
Seq.filter
vs
List.filter
等),您可以简单地使用一个序列而不是如下所示的列表:
{1L..x}
您的问题是什么?
OutOfMemoryException
是像你这样使用大量内存的正常结果。观察:要计算一个数字的因子,你只需要上升到
sqrt x
,而不是
x
@mydogisbox。你认为OutOfMemoryException是理想的结果吗?当然不是。你还没有解释你的问题是什么。您只描述了代码示例的行为。您是否希望通过当前代码避免OOM异常?你想要一个完全不同的解决问题的方法吗?你想解释一下为什么会有OOM异常吗?描述您正在寻找的信息,我们可以给您一个解释。否则我们只是猜测您想要什么。@mydogisbox很明显,我希望避免出现异常,并找出导致异常的代码部分。