Prolog编写0到N区间素数查找代码无法正确过滤合数问题求助
现有代码问题
你的代码存在几处会直接导致运行错误、逻辑不完整的问题:
- 谓词名不匹配:你定义了
check(N,2)用来判断N能被2整除,但后续代码里调用的是divide/2谓词,Prolog中谓词名称和参数数量完全匹配才能正常调用,这里会直接触发谓词不存在的错误 - 未绑定变量:
plist/2子句中直接写了X>1,但变量X从来没有被赋值过,运行时会抛出参数未实例化的错误 - 筛法逻辑残缺:目前只写了过滤2的倍数的逻辑,完全没有实现其他素因子的筛除步骤,也没有迭代更新筛除基准值的逻辑,根本无法完成全范围素数筛选
- 边界值错误:初始列表从1开始生成,1不属于素数,会被错误保留在结果里
可直接运行的改进版本(埃氏筛实现)
这个实现完全遵循埃拉托斯特尼筛法逻辑,兼容绝大多数Prolog环境:
% 入口谓词:返回0~N范围内的所有素数 primes(N, Primes) :- N < 2, !, Primes = []. primes(N, Primes) :- numlist(2, N, InitList), sieve(InitList, Primes). % 筛法递归逻辑 sieve([], []). sieve([CurPrime|Rest], [CurPrime|ResPrimes]) :- filter_multiples(CurPrime, Rest, RemainList), sieve(RemainList, ResPrimes). % 过滤掉当前素数的所有倍数 filter_multiples(_, [], []). filter_multiples(P, [H|T], Res) :- 0 =:= H mod P, !, filter_multiples(P, T, Res). filter_multiples(P, [H|T], [H|ResT]) :- filter_multiples(P, T, ResT).
用法说明
- 直接调用
primes(目标上限N, 结果变量)即可得到素数列表,比如执行primes(30, R)会返回R = [2,3,5,7,11,13,17,19,23,29] - 入口处加了截断符避免N<2时回溯出多余结果,符合素数的数学定义(大于1、除了1和自身无其他正因子的自然数)
- 没有依赖第三方库内置谓词,手动实现了倍数过滤逻辑,在SWI-Prolog、GNU Prolog等常见实现上都可以直接运行
- 如果需要更高效率,可以在判断倍数时增加优化:只需要筛到当前素数的平方小于等于上限即可,不过对于小范围素数查找当前实现性能足够
内容的提问来源于stack exchange,提问作者User01072022
相关产品推荐
相关产品推荐

