Functional programming 函数语言中的素因子分解

Functional programming 函数语言中的素因子分解,functional-programming,ocaml,primes,prime-factoring,Functional Programming,Ocaml,Primes,Prime Factoring,我正在用OCaml编写,试图给出(某种程度上)素因子分解的高效实现。我认为一个数字2或更多的最佳表示是在指数列表中。为了简单起见,我将按素数的降序来做。所以2是[1],3是[1;0],4是[2],5是[1;0;0] 我正在考虑使用筛子的思想来获取一个数字n,并寻找2和sqrt(n)之间所有可能的除数。然后除以任何除数并递归。然而,我所能想到的每一个实现似乎都涉及到对列表的重复搜索,这似乎是不必要的低效。我的解决方案的概要最好在这段代码中说明 let rec pf n = if (n=2) t

我正在用OCaml编写,试图给出(某种程度上)素因子分解的高效实现。我认为一个数字2或更多的最佳表示是在指数列表中。为了简单起见,我将按素数的降序来做。所以2是[1],3是[1;0],4是[2],5是[1;0;0]

我正在考虑使用筛子的思想来获取一个数字
n
,并寻找2和
sqrt(n)
之间所有可能的除数。然后除以任何除数并递归。然而,我所能想到的每一个实现似乎都涉及到对列表的重复搜索,这似乎是不必要的低效。我的解决方案的概要最好在这段代码中说明

let rec pf n =
  if (n=2) then ([1], 0)
  else let sq = int_of_float ( (float_of_int n) ** 0.5 ) in
  let primes = getPrimes sq in
  match earliestDiv n primes with
  | None -> n::(zero_list (n-1))
  | Some (x, i) -> let subproblem pf (n/x) in
              increment subproblem i
这里的助手函数是:

  • getPrimes
    它接受一个int并返回一个所有小于或等于它的素数的列表
  • earliestDiv
    取整数
    n
    和整数列表
    lst
    ,返回一个int*int选项,该选项对应于
    lst
    中最早的数字,该数字除以
    n
    。这将是元组的第一个坐标;第二个坐标将返回素数列表中该素数的索引
    x
  • increment
    将获取一个int列表和索引,并将位于索引处的数字增加1
所有这些助手函数都会不断生成列表、传递列表等等。事实上,我经常觉得我在函数式编程中这样做。我经常感觉到我在不必要地迭代列表,而在命令式语言中,我会编写更高效的代码。也许这只是在我的脑海中,当我用命令式语言写作时,我很少注意到我使用的一些列表操作中有多少资源。但如果我遗漏了一些可以防止重复扫描列表的重要技术,我会很想听听


问题是:为了编写此函数,是否有必要重复创建和迭代列表?

如果最终为列表编制索引,或使用默认元素将列表填充到固定大小,则列表很可能是错误的数据结构。对于素因子分解,您可能需要稀疏数组的实现。与固定大小的列表相比,“地图”将是一个更好的(如果不是最佳的)实现。

@Ken White问题在于是否有必要重复创建和迭代列表。对我来说,这听起来像是一个编程问题。@KenWhite问题已更新。作为旁注,您可能需要尝试编写代码,将表示中的两个数字相乘。我的主张是,排列相应的素数会很麻烦。如果列表以指数2开头,对齐是自动的。另一方面,在列表中迭代并不比在数组中迭代慢。当你需要随机访问时,有不同之处。你也可以考虑一下你的表示对于一个100位数的素数来说是什么样子(比如说)。