功能语言中的素数分解

时间:2019-06-11 23:41:50

标签: 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) 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,并返回一个对应于lst中最早数字的int * int选项,该选项将{{1}除以}。那将是元组的第一个坐标;第二个坐标将返回素数列表中该素数n的索引。
  • x将获取一个int列表和索引,并将位于索引处的数字加1。

所有这些帮助器功能都会不断创建列表,传递列表等。实际上,我经常觉得我在函数式编程中正在这样做。我经常觉得我不必要遍历列表,而在命令式语言中,我会写效率更高的代码。也许这只是在我的脑海,用命令式语言编写时,我很少会注意到我使用的某些列表操作中有多少资源。但是,如果我错过了一些可能阻止重复扫描列表的重要技术,我很想听到它。

问题:要编写此功能,是否有必要重复创建和遍历列表?

1 个答案:

答案 0 :(得分:2)

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