Prolog查找前10个梅森素数报错问题排查与修正
问题原因
当前find_mersenne_primes/2的逻辑存在漏洞:当检查的数N不是梅森素数时,没有对应的分支继续尝试下一个数,直接导致谓词失败,程序提前终止,因此仅能输出前2个梅森素数后就触发「Initialization goal failed」警告。
修正后的完整代码
% 定义判断素数的谓词 is_prime(N) :- N > 1, \+ has_divisor(N, 2). % 定义判断是否存在除1和自身外的因数的谓词 has_divisor(N, D) :- D =< sqrt(N), 0 is N mod D, D > 1, !. has_divisor(N, D) :- D_new is D + 1, D_new =< sqrt(N), has_divisor(N, D_new). % 补充递归检查下一个除数,原代码缺失此子句会导致is_prime判断错误 % 定义判断梅森素数的谓词 is_mersenne_prime(P) :- is_prime(P), Mersenne is 2^P - 1, is_prime(Mersenne). % 查找前Count个梅森素数 find_mersenne_primes(N, Count) :- Count > 0, is_mersenne_prime(N), write(N), write(' 2^'), write(N), write('-1'), nl, NewCount is Count - 1, NewN is N + 1, find_mersenne_primes(NewN, NewCount). % 新增分支:当前N不是梅森素数时,继续尝试下一个数 find_mersenne_primes(N, Count) :- Count > 0, \+ is_mersenne_prime(N), NewN is N + 1, find_mersenne_primes(NewN, Count). find_mersenne_primes(_, 0). main :- write('Calculating the first 10 Mersenne prime numbers:'), nl, find_mersenne_primes(2, 10). % 加载文件时自动运行程序 :- initialization(main).
关键修改说明
- 补充
has_divisor/2的递归子句:原代码仅检查初始除数D,未递归检查后续除数,会导致is_prime/1对部分合数(如9、15)判断错误,补充后才能正确识别素数。 - 新增
find_mersenne_primes/2的分支处理非梅森素数:当当前N不满足梅森素数条件时,递归调用N+1且保持计数不变,确保程序会持续查找直到收集够10个梅森素数。
运行修正后的代码,会依次输出前10个梅森素数对应的指数:2、3、5、7、13、17、19、31、61、89(对应的梅森数为2^P-1)。
内容的提问来源于stack exchange,提问作者Little
相关产品推荐
相关产品推荐

