【问题标题】:Prime factorization in a functional language函数式语言中的素数分解
【发布时间】:2019-10-26 10:06:21
【问题描述】:

我正在用 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 位素数(例如)的样子。

标签: functional-programming ocaml primes prime-factoring


【解决方案1】:

如果你最终为一个列表建立索引,或者用一个固定大小的默认元素填充一个列表,那么列表很可能是错误的数据结构。对于素数分解,您可能需要一个稀疏数组的实现。与固定大小的列表相比,地图将是更好(如果不是最优的话)实现。

【讨论】:

    猜你喜欢
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 2014-11-10
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多