OCaml素数判断函数异常排查:调用isprime(4)(2)返回true而非false
解决OCaml素数函数的两个问题
让我们一步步拆解并解决你的问题:
问题2:调用isprime (4)(2)返回true的原因
这个问题核心是逻辑判断写反了!当n mod d = 0时,说明d是n的因子,n肯定不是素数,这时候应该返回false,但你大概率在这个分支错误地返回了true。
举个典型的错误代码例子:
let rec isprime n d = match () with | _ when d * d > n -> true | _ when n mod d = 0 -> true (* 这里是错误根源! *) | _ -> isprime n (d + 1)
当你调用isprime 4 2时,4 mod 2 = 0触发第二个分支,直接返回true,完全违背预期。
修复方法:把n mod d = 0分支的返回值改成false,正确的代码示例:
let rec isprime n d = if d * d > n then true else if n mod d = 0 then false else isprime n (d + 1)
现在调用isprime 4 2就会返回false,符合预期。
问题1:“match case未使用”的警告
这个警告通常是因为你的match表达式里存在永远不会被执行到的分支,常见场景有两种:
多余的通配符分支:比如你先写了一个匹配所有情况的分支(比如
| x -> ...),后面又加了| _ -> ...,这时候后面的分支永远不会被触发,OCaml就会抛出警告。
错误示例:let rec isprime n d = match d with | x -> if x*x >n then true else if n mod x =0 then false else isprime n (x+1) | _ -> true (* 这个分支永远不会执行 *)修复:直接去掉那个多余的
| _ -> true分支即可。永远不会被匹配到的具体值分支:比如你的函数从
d=2开始调用,但match里写了| 1 -> ...的分支,这个分支永远不会被触发,也会导致警告。
错误示例:let rec isprime n d = match d with | 1 -> isprime n 2 | _ when d*d >n -> true | _ when n mod d =0 -> false | _ -> isprime n (d+1)修复:如果你的调用永远不会传入
d=1,就直接去掉|1 -> ...这个分支;如果需要支持从d=1开始调用,那保留分支就不会有警告(只要实际会触发)。
另外,如果你不需要匹配d的具体值,其实完全可以不用match,改用if-else结构,这样更简洁,也能避免这类警告,就像我上面给出的正确示例那样。
内容的提问来源于stack exchange,提问作者JIJOJJH
相关产品推荐
相关产品推荐

