suma reglas potencias potenciacion potencia negativo negativa los igual exponentes exponente elevada ejemplos prolog exponentiation

prolog - potencias - reglas de los exponentes



¿Regla para calcular la potencia de un número cuando el exponente es Negativo en Prolog? (3)

No olvide que a^(2b) = (a^b)^2 y x^2 = x*x . Está bien llamar a un predicado de trabajo recursivo de cola con un acumulador, sin cola, desde un predicado "UI" de nivel superior. De esta forma, no es necesario implementar el predicado de trabajo para las potencias negativas, sino reutilizar el de potencia positiva y alterar su resultado en el predicado de nivel superior (veo que esto ya se ha sugerido):

pow(B, E, R):- E<0 -> ... ; E=:=0 -> ... ; E>0 -> ... .

Tengo un pow función de pow que intenta calcular el valor de B a la potencia de E Hasta ahora yo manejo los casos-
1. exponente es 0
2. exponente no es cero

pow(B,0,1). pow(B,E,Result):- E2 is E - 1, pow(B,E2,Result2), Result is B*Result2.

¿Cómo puedo agregar otro caso donde la función de potencia puede manejar exponentes negativos?


Para empezar, su segunda cláusula es no recursiva (puede leer sobre el tema aquí ). Significa que eventualmente, se quedará sin memoria de la pila de llamadas cuando la ejecute. Una cosa buena sería usar un acumulador para que sea recursivo en la cola. Puedes lograrlo de la siguiente manera:

% we add an accumulator to poW/3, making it pow/4. pow(B, E, Result) :- pow(B, E, 1, Result). % when we hit 0, our accumulator holds B^E so we unify it with result. pow(_, 0, Accu, Accu) :- !. % at each step, we multiply our accumulator by B pow(B, E, Accu, Result) :- NewE is E - 1, NewAccu is Accu * B, pow(B, NewE, NewAccu, Result).

Entonces, simplemente puede manejar el caso negativo agregando esta cláusula encima de las demás (simplemente le dice a prolog que un poder negativo es el inverso del positivo):

pow(B, E, Result) :- E < 0, PositiveE is - E, pow(B, PositiveE, 1, R), !, Result is 1 / R.

Tenga en cuenta que puede hacerlo directamente con su código:

pow(B, E, Result) :- E < 0, PositiveE is - E, pow(B, PositiveE, R), !, Result is 1 / R.

Además, ahora presentamos un corte muy rojo (consulte aquí el significado del corte rojo si es necesario). Entonces sería mejor convertirlo en un corte verde con esta modificación:

pow(B, E, Result) :- E < 0, PositiveE is - E, pow(B, PositiveE, 1, R), !, Result is 1 / R. % we add an accumulator to poW/3, making it pow/4. pow(B, E, Result) :- E >= 0, %************* HERE ***************** pow(B, E, 1, Result). % when we hit 0, our accumulator holds B^E so we unify it with result. pow(_, 0, Accu, Accu) :- !. % at each step, we multiply our accumulator by B pow(B, E, Accu, Result) :- NewE is E - 1, NewAccu is Accu * B, pow(B, NewE, NewAccu, Result).


Primero, uno debe considerar cómo definir 0 0 . Formalmente hablando, es indeterminado . Podría ser cero o podría ser 1. Como dice el Mundo matemático de Wolfram en su artículo sobre poderes y en su artículo sobre cero :

0 0 (cero a la potencia zeroth) no está definido. La falta de un significado bien definido para esta cantidad se deduce de los hechos mutuamente contradictorios que un 0 es siempre 1, entonces 0 0 debería ser igual a 1, pero 0 a es siempre 0 (para a > 0), entonces 0 a debería ser igual a 0 La elección de la definición para 0 0 generalmente se define como indeterminada, aunque la definición de 0 0 = 1 permite que algunas fórmulas se expresen de manera simple (Knuth 1992; Knuth 1997, p.57).

Entonces, primero debe elegir cómo definir el caso especial de 0 0 : ¿Es 0? ¿Es 1? ¿Está indefinido?

Elijo mirarlo como indefinido.

Dicho esto, puede observar un exponente positivo como se indica en la multiplicación repetida (por ej., 10 3 es 10 * 10 * 10 o 1,000), y puede ver un exponente negativo como una división repetida (p. Ej., 10 -3 es [ ((1/10) / 10) / 10) o 0.001). Mi inclinación, en parte porque me gusta la simetría de este enfoque y en parte para evitar los cortes (ya que un corte a menudo es una señal de que no ha definido la solución correctamente), sería algo como esto:

% ----------------------------- % The external/public predicate % ----------------------------- pow( 0 , 0 , _ ) :- ! , fail . pow( X , N , R ) :- pow( X , N , 1 , R ) . % ----------------------------------- % the tail-recursive worker predicate % ----------------------------------- pow( _ , 0 , R , R ). pow( X , N , T , R ) :- N > 0 , T1 is T * X , N1 is N-1 , pow( X , N1 , T1 , R ) . pow( _ , 0 , R , R ) :- N < 0 , T1 is T / X , N1 is N+1 , pow( X , N1 , T1 , R ) .

El otro enfoque, como otros lo han notado, es definir un exponente positivo como indicativo de una multiplicación repetida, y un exponente negativo como el que indica el recíproco del exponente positivo, entonces 10 3 es 10 * 10 * 10 o 1,000, y 10 -3 es 1 / (10 3 ), o 1 / 1,000 o 0.001. Para usar esta definición, evitaría nuevamente los cortes y haré algo como esto:

% ----------------------------- % the external/public predicate % ----------------------------- pow( 0 , 0 , _ ) :- % 0^0 is indeterminate. Is it 1? Is it 0? Could be either. ! , fail . pow( X , N , R ) :- N > 0 , pow( X , N , 1 , R ) . pow( X , N , R ) :- N < 0 , N1 = - N , pow( X , N1 , 1 , R1 ) , R is 1 / R1 . % ----------------------------------- % The tail-recursive worker predicate % ----------------------------------- pow( _ , 0 , R , R ). pow( X , N , T , R ) :- N > 0 , T1 is T * X , N1 is N-1 , pow( X , N1 , T1 , R ) .