write sistemas sintaxis resueltos reglas predicados funciones expertos ejercicios consultas prolog primes

sistemas - Programa Prolog para verificar si un número es primer



sintaxis de prolog (5)

Escribí el siguiente programa basado en la lógica de que un número primo solo es divisible por 1 y por sí mismo. Así que simplemente sigo el proceso de dividirlo entre todos los números que son más de uno y menos que sí mismo, pero parece que tengo un problema ya que obtengo todos los números ingresados ​​como verdaderos. Aquí está mi código ...

divisible(X,Y) :- Y < X, X mod Y is 0, Y1 is Y+1, divisible(X,Y1). isprime(X) :- integer(X), X > 1, /+ divisible(X,2).

Gracias por adelantado :)


X mod Y is 0 siempre falla, porque no se permiten expresiones a la izquierda de is .

Cambiar a 0 is X mod Y , o, mejor, a X mod Y =:= 0


Soy un principiante en Prolog pero logré solucionar tu problema.

divisible(X,Y) :- 0 is X mod Y, !. divisible(X,Y) :- X > Y+1, divisible(X, Y+1). isPrime(2) :- true,!. isPrime(X) :- X < 2,!,false. isPrime(X) :- not(divisible(X, 2)).

El problema principal fue la declaración X mod Y is 0 . Predicado tiene dos argumentos (izquierdo y derecho), pero el argumento de la izquierda tiene que ser una constante o una variable que ya está unificada en el momento en que se está ejecutando el predicado. Acabo de intercambiar estos valores. El resto del código es para verificar el número 2 (que es el número primo) y el número menor que 2 (que no son números primos)

Olvidé mencionar que la comparación Y < X tiene errores, porque quiere probar todos los números entre 2 y X-1, esa comparación incluye X.


Creo que es una manera elegante:

isPrime(A):-not((A1 is A-1,between(2,A1,N), 0 is mod(A,N))),not(A is 1).

1 NO ES PRIME NUMBER, pero si no lo crees, simplemente elimina no (A es 1) .


Esta respuesta es una continuación de la respuesta previa de @ lefunction .

isPrime2/1 está lo más cerca posible de isPrime1/1 con algunos cambios cruciales (resaltados a continuación):

isPrime2(2) :- !. isPrime2(3) :- !. isPrime2(X) :- X > 3, X mod 2 =/= 0, N_max is ceiling(sqrt(X)), isPrime2_(X,3,N_max). isPrime2_(X,N,N_max) :- ( N > N_max -> true ; 0 =/= X mod N, M is N + 2, isPrime2_(X,M,N_max) ).

¡Vamos a preguntar!

?- time(isPrime1(99999989)). % 99,999,990 inferences, 5.082 CPU in 5.078 seconds (100% CPU, 19678881 Lips) true. ?- time(isPrime2(99999989)). % 20,002 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 13615185 Lips) true.


La respuesta aceptada de agarwaen no funciona bien en números grandes. Esto se debe a que no es cola recursiva (creo). Además, puede acelerar todo con algunos datos sobre números primos.

1) 2 es el único número primo par

2) Cualquier número mayor que la mitad del original no se divide de manera uniforme

isPrime1(2) :- !. isPrime1(3) :- !. isPrime1(X) :- X > 3, ( 0 is X mod 2 -> false ; Half is X/2, isPrime1_(X,3,Half) ). isPrime1_(X,N,Half) :- ( N > Half -> true ; 0 is X mod N -> false ; M is N + 2, isPrime1_(X,M,Half) ).

1 ?- time(isPrime1(999983)). % 1,249,983 inferences, 0.031 CPU in 0.039 seconds (80% CPU, 39999456 Lips) true.

EDIT1

¿Es posible dar un paso más? isPrime_/3 es más eficiente que isPrime2/1 porque solo se compara con los primos conocidos anteriormente. Sin embargo, el problema es generar esta lista.

allPrimes(Max,Y) :- allPrimes(3,Max,[2],Y). allPrimes(X,Max,L,Y) :- Z is X+2, N_max is ceiling(sqrt(X)), ( X >= Max -> Y = L; ( isPrime_(X,L,N_max) -> append(L,[X],K), %major bottleneck allPrimes(Z,Max,K,Y) ; allPrimes(Z,Max,L,Y) )). isPrime_(_,[],_). isPrime_(X,[P|Ps],N_max) :- ( P > N_max -> true %could append here but still slow ; 0 =/= X mod P, isPrime_(X,Ps,N_max) ).