OCaml递归疑问:为何最后一个else未按预期重启递归?
OCaml递归实现孪生素数查找的问题修正
首先看你代码的核心问题:
- 当触发
q mod p !=0 && p mod q !=0的分支时,你只执行了打印,没有发起新的递归调用,程序执行到这里就直接终止了,所以后续的数对不会被处理。 - 你判断孪生素数的逻辑完全错误:
q mod p !=0 && p mod q !=0只能说明两个数互质,但孪生素数要求两个数都是素数且差为2,比如9和11互质,但9不是素数,所以不是孪生素数。 - 条件
q = p + 2是冗余的:因为你每次递归都是p+1和q+1,初始调用的p和q差2,所以这个条件永远为真,最后那个else分支根本不会被触发,这就是你觉得它没工作的原因。
接下来是修正后的实现步骤:
1. 先实现递归的素数判断函数
素数的定义是大于1,且除了1和自身外没有其他因数。递归判断可以检查从2到sqrt(n)的数是否能整除n:
let is_prime n = let rec check_divisor d = d * d > n || (n mod d <> 0 && check_divisor (d + 1)) in n > 1 && check_divisor 2
2. 实现递归的孪生素数查找函数
函数需要遍历从起始对(比如3,5)到(n, n+2)的所有数对,判断每对是否都是素数,是的话输出,然后继续递归直到p超过n:
let rec find_twin_primes p q n = if p > n then () (* 终止条件:超过上限n,停止递归 *) else if is_prime p && is_prime q then begin print_int p; print_string ", "; print_int q; print_newline (); find_twin_primes (p + 1) (q + 1) n (* 打印后继续递归下一对 *) end else find_twin_primes (p + 1) (q + 1) n (* 不满足则直接递归下一对 *) (* 调用示例:查找3到3+2(即5)之间的孪生素数,也就是检查(3,5),(4,6),(5,7) *) find_twin_primes 3 5 3
代码解释
- 终止条件:当p超过n时,递归结束。
- 每次递归先判断当前p和q是否都是素数,是的话打印并继续递归下一对;否则直接递归下一对。
- 素数判断函数
is_prime通过递归检查所有可能的除数,直到除数的平方超过n,确保效率和正确性。
如果你需要返回孪生素数列表而不是打印,也可以修改函数返回(int * int) list类型:
let rec find_twin_primes_list p q n = if p > n then [] else if is_prime p && is_prime q then (p, q) :: find_twin_primes_list (p + 1) (q + 1) n else find_twin_primes_list (p + 1) (q + 1) n (* 调用示例 *) find_twin_primes_list 3 5 11 (* 返回 [(3,5);(5,7);(11,13)] *)
内容的提问来源于stack exchange,提问作者GamersOfDead
相关产品推荐
相关产品推荐

