Foros del Web » Programando para Internet » Python »

[Aporte] Evaluar expresiones aritmeticas

Estas en el tema de [Aporte] Evaluar expresiones aritmeticas en el foro de Python en Foros del Web. Siempre trato de evitar el uso de la función eval pero hay situaciones en que su uso es simplemente tentador. Uno de estos casos es ...
  #1 (permalink)  
Antiguo 25/08/2011, 17:00
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 1 mes
Puntos: 1360
[Aporte] Evaluar expresiones aritmeticas

Siempre trato de evitar el uso de la función eval pero hay situaciones en que su uso es simplemente tentador.

Uno de estos casos es al momento de evaluar expresiones aritméticas. Tener una cadena de este modo:
Código:
"2 * 2 + 3"
Parece irresistible pasarlo por la función eval para que nos regrese su valor numérico.

En vista de esto, me puse a estudiar e implementar uno de los muchos algoritmos de Dijkstra llamado Shunting-yard para pasar de expresiones infijas a expresiones prefijas.

Aquí dejo el código.
Código Python:
Ver original
  1. from collections import deque
  2.  
  3. class Stack:
  4.     def __init__(self):
  5.         self.__stack = []
  6.        
  7.     def top(self):
  8.         return self.__stack[-1]
  9.    
  10.     def pop(self):
  11.         self.__stack.pop()
  12.        
  13.     def push(self, value):
  14.         self.__stack.append(value)
  15.        
  16.     def empty(self):
  17.         return not bool(self.__stack)
  18.        
  19. class Queue:
  20.     def __init__(self):
  21.         self.__queue = deque()
  22.    
  23.     def enqueue(self, value):
  24.         self.__queue.append(value)
  25.        
  26.     def dequeue(self):
  27.         self.__queue.popleft()
  28.    
  29.     def top(self):
  30.         return self.__queue[0]
  31.    
  32.     def empty(self):
  33.         return not bool(self.__queue)
  34.    
  35.     def __iter__(self):
  36.         return iter(self.__queue)
  37.  
  38. precedence = {
  39.               "*" : 10,
  40.               "/" : 10,
  41.               "+" : 9,
  42.               "-" : 9,
  43.               "(" : -1,
  44.               ")" : -1,
  45.               }
  46.  
  47. operations = {
  48.               "*" : lambda x, y: x * y,
  49.               "/" : lambda x, y: x / y,
  50.               "+" : lambda x, y: x + y,
  51.               "-" : lambda x, y: x - y,
  52.               }
  53.  
  54. expr = ["3", "-", "(", "2", "+", "30", ")"]
  55.  
  56. def infixTOprefix(expr, precedence):
  57.     stack = Stack()
  58.     output = Queue()
  59.    
  60.     for token in expr:
  61.         if token not in precedence:
  62.             output.enqueue(token)
  63.         elif token == ")":
  64.             while not stack.empty():
  65.                 if stack.top() == "(":
  66.                     stack.pop()
  67.                     break
  68.                 else:
  69.                     output.enqueue(stack.top())
  70.                     stack.pop()
  71.         else:
  72.             if stack.empty() or token == "(":
  73.                 stack.push(token)
  74.             else:
  75.                 while not stack.empty() and precedence[token] <= precedence[stack.top()]:
  76.                     output.enqueue(stack.top())
  77.                     stack.pop()
  78.                 stack.push(token)
  79.    
  80.     while not stack.empty():
  81.         output.enqueue(stack.top())
  82.         stack.pop()
  83.     return list(output)
  84.  
  85. def evaluate(expr, operations):
  86.     stack = Stack()
  87.     for token in expr:
  88.         if token not in operations:
  89.             stack.push(float(token))
  90.         else:
  91.             a = stack.top()
  92.             stack.pop()
  93.             b = stack.top()
  94.             stack.pop()
  95.             stack.push(operations[token](b, a))
  96.     return stack.top()
  97.  
  98. prefix = infixTOprefix(expr, precedence)
  99. print expr
  100. print prefix
  101. print evaluate(prefix, operations)
  #2 (permalink)  
Antiguo 10/09/2011, 20:30
Avatar de Hazuki  
Fecha de Ingreso: mayo-2011
Mensajes: 34
Antigüedad: 12 años, 11 meses
Puntos: 7
Respuesta: [Aporte] Evaluar expresiones aritmeticas

Me recuerda a una vez que intenté hacer una función para resolver ecuaciones. Conseguí que pudiera resolver algunas ecuaciones de primer grado... luego lo dejé por pereza xD.

Etiquetas: evaluar, expresiones
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 2 personas




La zona horaria es GMT -6. Ahora son las 23:47.