Evaluación de una expresión en postfija utilizando una pila

Anuncio
4
(25 %) En este ejercicio se desarrollará el motor de evaluación de una función para una
interfaz gráfica de usuario. Dicha interfaz, que se desarrollara en la practica 4 con el
empleo del API Swing, permitirá al usuario introducir una función escrita en forma infija y a
continuación dibujarla en el intervalo deseado. El motor de evaluación básico se compone
de la clase Evaluador, cuya implantación se proporciona parcialmente. Dicha clase permite
evaluar una expresión aritmética, formada únicamente por números y operadores binarios:
suma, resta, multiplicación, división, y exponenciación (-,+ ,*,/,^).
Se pide:

Completar el código de la clase Evaluador de forma que el signo menos pueda actuar
también como operador unario(con un solo operando). Después de la modificación la clase
debe poder evaluar expresiones tales como “-1”, “-(1 – 3)”, “1-(- 1 *8)”, “ 2 * (-2)”, -(-1), etc.
No importa que haya espacios entre el operador menos unario y su operando. Utilizar la
clase TestEvaluador proporcionada para realizar pruebas.

A continuación, créese una clase, Funcion, que tenga como miembro dato una cadena
con la expresión de la función y que herede de la clase Evaluador. La cadena especificara
un función real en la variable real x formada por cualquier combinación de dicha variable
junto con las funciones sin(x),cos(x),tan(x),exp(x) y log(x), por ej.: “3*x + 1 –sin(x)^2 –(2*exp(x)/log(x)) + cos(x)^2 –tan(x) +2/(x^2 + x)”. La clase Funcion deberá tener un método
publico llamado eval que devuelva el valor de la función en el punto de evaluación x.
Utilícese la clase TestFuncion para realizar pruebas con distintas funciones en distintos
puntos de evaluación. Puede verse la ejecución de este fichero sobre la clase Funcion
terminada corriendo el archivo “ejecutableEJ4.bat” (utiliza el jar testFuncionEJ4.jar). En la
dirección http://www.ideas2work.com/CoreJava7.html se explica como crear ejecutables jar.

Por último, y para poner en práctica el dispatching dinámico de métodos, crear una clase
abstracta Funcion2 que herede de la clase Evaluador, con las mismas características que
la clase Funcion, salvo que ahora el método eval se declara abstracto. A continuación
créense tres clases, FuncionTrigonometrica, FuncionExponencial, y FuncionPolinomica,
que heredando de la clase Funcion2 implementen el método eval(no serán mas que casos
particulares del método eval de la clase Funcion). Por tales funciones se entenderá que
sólo contienen combinaciones de [sin(x) cos(x) tan(x)], exp(x), y x respectivamente. En un
archivo de aplicación TestPolimorfismoApp.java, declarar:
Funcion2 f2[]=new Funcion2[3];
;f2[0]=new FuncionTrigonometrica(“2*sin(x)*cos(x)”); // seno del ángulo doble
;f2[1]=new FuncionPolinomica(“32*x^5 –160*x^3 +120”);//polinomio de Hermite de orden 5
;f2[2]=new FuncionExponencial(“(exp(x) – exp(x)^(-1))/2”) //función seno hiperbólico
A continuación permitir que sea el usuario quien decida en tiempo de ejecución que función
evaluar mediante la llamada a f2[i].eval(x). Se le pedirá por teclado la función que desea
evaluar y el punto de evaluación.
INDICACIONES
Como indicación para el apartado 1, hacer notar que el signo menos unario es equivalente a la
multiplicación por –1 de su operando, lo cual a su vez, es equivalente a (0-1)*operando.
Con respecto al apartado 2, decir que las funciones sin(x), cos(x), etc., en la cadena de la
expresión deberán de ser reemplazadas por su valor numérico correspondiente mediante
replaceAll(“cos(x)”,””+Math.cos(x)).A continuación se procederá del mismo modo con las x.
Finalmente se hará uso de los métodos heredados de la clase Evaluador para obtener el
resultado. Hay que tener en cuenta que cuando un double es menor que 10^3 y mayor que
10^7 la conversión a String se expresa en notación científica, con lo cual el número 0.00001 se
convertirá en el String 1E-5, que al sustituir en la expresión no podrá evaluarse como un
numero, produciendo un error fatal en el motor de evaluación (clase Evaluador). Es necesario,
pues, dar formato al double mediante las siguientes líneas:
Double d=(double) 1/1000000;
NumberFormat nf = NumberFormat.getInstance(Locale.ENGLISH);
nf.setMaximumFractionDigits(20);
String correcto =nf.format(d);
Produciendo el resultado deseado.
Ayuda para la realización del ejercicio 4
A continuación se explica como evaluar una expresión matemática empleando Pilas. Para
quien no tenga idea de lo que es una pila puede documentarse con cualquier libro de estructura
de datos, o más sencillamente, buscando en google por “estructura de datos pila”. Antes de
nada, decir que en el paquete java.util.* se proporcionan bastante implementaciones de
estructuras de datos (entre las que se incluye una pila (Stack) además de algoritmos
aplicados a ellas. El siguiente código declara y usa una pila de dicho paquete:
Stack s=new Stack();
//Apilamos (push) A,B,C en la pila
s.push(“A”);
s.push(“B”);
s.push(“C”);
//Sacamos(pop) C,B,A de la pila
while(s.size() >0)
System.out.println(“”+s.pop);
Aunque podría haberse utilizado esta clase, se ha desarrollado una clase propia para
implementar una pila. Decir también, que en la clase Pila que se proporciona, push es apilar y
pop desapilar.
EXPRESION INFIJA, POSTFIJA Y SU ALGORITMO DE EVALUACION
La forma habitual de escribir expresiones matemáticas es la infija, que básicamente consiste en
un operador binario junto con argumentos a su izquierda y derecha. La evaluación de una
expresión en forma inflija puede llegar a ser un tanto tediosa, por esa razón suelen utilizarse
otro tipo de notaciones, como son la sufija y postfija. En estas formas la evaluación de una
expresión aritmética resulta bastante sencilla de implementar utilizando pilas. A continuación se
expone el algoritmo de conversión entre ambas representaciones. El alumno que desee
conocer más acerca la notación postfija puede consultar cualquier libro de estructura de datos(
en la parte de pilas).
Conversión de Notación Inflija a Postfija:
Todo lo que se desapila pasa a la salida.
Operandos : Pasan inmediatamente a la salida.
Paréntesis derecho: Desapilamos todos los símbolos hasta que encontremos un paréntesis
izquierdo.
Operador: Desapilamos todos los símbolos hasta que encontremos uno de menor precedencia
o de igual precedencia con asociatividad por la derecha. A continuación, apilaremos el
operador encontrado.
Fin de entrada: Desapilamos lo que quede en pila.
En la tabla siguiente se resumen la precedencia(de menor a mayor) y asociatividad de cada
operador:
Operador
^
/
*
+
-
Precedencia
3
2
2
1
1
Asociatividad
Derecha
Izquierda
Izquierda
Izquierda
Izquierda
Con un ejemplo quedará claro:
Sea la expresión infija: 1 – 2 ^ 3 ^ 3 – (4 + 5 *6) *7
Leemos
1
2
^
3
^
3
(
4
+
5
*
6
)
*
7
Fin de entrada
Salida
1
1
12
12
123
123
1233
1233
1233
1233
1233
1233
1233
1233
1233
1233
1233
1233
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
^
- 4
- 4
-45
-45
-456
-456
-456
-456
-456
*+
*+
*+7
*+7*-
Evolución de la Pila
Vacía
-^
-^
-^^
-^^
- (
- (
- (+
-(+
-(+*
-(+*
-*
-*
La expresión en postfija, será, pues: 1 2 3 3 ^ ^ - 4 5 6 * + 7 * -
Evaluación de una expresión en postfija utilizando una pila
Dada una expresión en postfija, para evaluarla se seguirán dos sencillos pasos:
1-Leemos un carácter de la expresión en infijo.
2-Si es un operando lo metemos en la pila. (Hacemos push(operando))
Si es un operador, desapilamos los dos últimos elementos de la pila y los operamos. El primer
elemento desapilado se convertirá en el parámetro derecho del operador, y el segundo en el
izquierdo. (Hacemos
A=pop(), B=pop() , push( B operado A).
Ejemplo: 1 2 – 4 5 ^ 3 * 6 *7 2 2 ^ ^ / -
Leemos
1
2
-
Evolución de la pila
1
1 2
-1
4
5
^
3
*
6
*
7
2
2
^
^
/
El resultado de la evaluación es –8.
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-8
4
4 5
1024
1024 3
3072
3072 6
18432
18432 7
18432 7 2
18432 7 2 2
18432 7 4
18432 2401
7
Descargar