2 de marzo de 2017

Aprendiendo a usar la notación POSTFIX en PYTHON

Código calculadora postfix en PYTHON

# *-* coding: utf-8 *-*

# http://csis.pace.edu/~wolf/CS122/infix-postfix.htm
# http://hawkee.com/snippet/16636/

def esFloat(a):
    try:
        float(a)
        return True
    except:
        return False

# Funciones

cadena=raw_input("Introduce una cadena con operadores válida: ")

operadores=["+","-","*","/","^","(",")"]
prefoper=[0,0,1,1,2,-1,-1]
stack=[]
postfix=""

# =====================================
# Pretratamiento para números negativos
# =====================================
cadena2=""
previo=""
bandera = 0
for i in cadena:
    if i=="-" and (previo in operadores or previo=="") and bandera==0:
        cadena2+="(0-"
        bandera=1
    elif i in operadores and bandera==1:
        cadena2+=")"+i
        bandera=0
    else:
        cadena2+=i
    previo = i

if bandera==1:
    cadena2+=")"
# ======================
# Fin del pretratamiento
# ======================

print "Esta es la conversión: %s" % (cadena2)

for i in cadena2:
    if i in operadores and prefoper[operadores.index(i)]>=0: # todos menos los paréntesis
        indice = operadores.index(i) # indice del elemento nuevo
        # la 5ª regla, la potencia, se consigue con un while en la siguiente en vez de un if.
        while len(stack)>=1 and prefoper[indice]<=prefoper[operadores.index(stack[len(stack)-1])]:
            # y la preferencia del operador es mayor que la del último del stack
            # el igual incluye la asociación, 4ª regla
            postfix+=" "+stack[len(stack)-1] # añade el último al postfix
            stack.pop() # quita de la pila el último
        stack.append(i) # añade el operador al stack
        postfix+=" "
    elif i=="(":
        stack.append("(") # añade el paréntesis al stack
    elif i==")":
        while len(stack)>1 and stack[len(stack)-1]!="(":
            postfix+=" "+stack[len(stack)-1] # añade al postfix
            stack.pop() # lo quita de la pila
        if stack[len(stack)-1]=="(":
            stack.pop() # lo quita de la pila
    else: # si no está en operadores o no son paréntesis
        postfix+=i
    # imprime la lectura de la cadena, la posición, la cadena postfix y el stack
    print cadena2.index(i), i, stack, postfix

while len(stack)>=1:
    if prefoper[operadores.index(stack[len(stack)-1])]>=0:
        postfix+=" "+stack[len(stack)-1]
    stack.pop()

print postfix

# =======
# Cálculo
# =======

pila=[]
pila=postfix.split(" ")
calculo=[]
# print pila

while len(pila)>0:
   
    item = pila.pop(0)
    # print item
   
    if item=="+" and len(calculo)>1:
        calculo.append(calculo.pop()+calculo.pop())
    elif item=="-" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(calculo.pop()-tmp)
    elif item=="*" and len(calculo)>1:
        calculo.append(calculo.pop()*calculo.pop())
    elif item=="/" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(calculo.pop()/tmp)
    elif item=="^" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(pow(calculo.pop(),tmp))
    elif esFloat(item):
        calculo.append(float(item))
    else:
        pass
       
    print calculo
   
print "El resultado es: %.4f" % (calculo[0])

= = = = = = = = = 

Versión no comprobada demasiado con funciones matemáticas

# *-* coding: utf-8 *-*

import math

# http://csis.pace.edu/~wolf/CS122/infix-postfix.htm
# http://hawkee.com/snippet/16636/

# Funciones

def esFloat(a):
    try:
        float(a)
        return True
    except:
        return False

# Fin de funciones

cadena=raw_input("Introduce una cadena con operadores válida: ")

operadores=["+","-","*","/","^","(",")","sin","cos","tan","sec","cosec","cotan","ln","log","exp","sqr"]
prefoper=[0,0,1,1,2,-1,-1,3,3,3,3,3,3,3,3,3,3]
stack=[]
postfix=""

# =====================================
# Pretratamiento para números negativos
# =====================================
cadena2=""
previo=""
bandera = 0
for i in cadena:
    if i=="-" and (previo in operadores or previo=="") and bandera==0:
        cadena2+="(0-"
        bandera=1
    elif i in operadores and bandera==1:
        cadena2+=")"+i
        bandera=0
    else:
        cadena2+=i
    previo = i

if bandera==1:
    cadena2+=")"
# ======================
# Fin del pretratamiento
# ======================

print "Esta es la conversión: %s" % (cadena2)

bandera = 0

for count, i in enumerate(cadena2):
   
    if bandera>0:
        bandera-=1 # va restando 1
        continue # permite leer funciones
      
    if i in operadores and prefoper[operadores.index(i)]>=0: # todos menos los paréntesis
        indice = operadores.index(i) # indice del elemento nuevo
        # la 5ª regla, la potencia, se consigue con un while en la siguiente en vez de un if.
        while len(stack)>=1 and prefoper[indice]<=prefoper[operadores.index(stack[len(stack)-1])]:
            # y la preferencia del operador es mayor que la del último del stack
            # el igual incluye la asociación, 4ª regla
            postfix+=" "+stack[len(stack)-1] # añade el último al postfix
            stack.pop() # quita de la pila el último
        stack.append(i) # añade el operador al stack
        postfix+=" "
    elif (cadena2[count:count+3]=="sin"
        or cadena2[count:count+3]=="cos"
        or cadena2[count:count+3]=="tan"
        or cadena2[count:count+3]=="sec"
        or cadena2[count:count+3]=="log"
        or cadena2[count:count+3]=="exp"
        or cadena2[count:count+3]=="sqr"): # si son estas funciones, las añade
        stack.append(cadena2[count:count+3])
        bandera=len(cadena2[count:count+3])-1
    elif (cadena2[count:count+5]=="cosec"
        or cadena2[count:count+5]=="cotan"): # si son estas más largas, las añade también
        stack.append(cadena2[count:count+5])
        bandera=len(cadena2[count:count+5])-1
    elif cadena2[count:count+2]=="ln": # si es el ln
        stack.append(cadena2[count:count+2])
        bandera=len(cadena2[count:count+2])-1
    elif cadena2[count:count+2].lower()=="pi": # si es el número pi
        postfix+=str(4*math.atan(1))
        bandera=len(cadena2[count:count+2])-1
    elif (cadena2[count:count+4].lower()=="10e-"
        or cadena2[count:count+4].lower()=="10e+"): # si es exponente positivo o negativo
        postfix+="1"+cadena[count+2:count+4]
        bandera=len(cadena2[count:count+4])-1
    elif cadena2[count:count+3].lower()=="10e": # si es exponente positivo sin el signo más
        postfix+="1e"
        bandera=len(cadena2[count:count+3])-1
    elif i=="e" and (cadena2[count+1:count+2] in operadores[0:7] or cadena2[count+1:count+2]==""): # número e
        postfix+=str(math.exp(1))
    elif i=="(":
        stack.append("(") # añade el paréntesis al stack
    elif i==")":
        while len(stack)>1 and stack[len(stack)-1]!="(":
            postfix+=" "+stack[len(stack)-1] # añade al postfix
            stack.pop() # lo quita de la pila
        if stack[len(stack)-1]=="(":
            stack.pop() # lo quita de la pila
    else: # si no está en operadores o no son paréntesis
        postfix+=i
    # imprime la lectura de la cadena, la posición, la cadena postfix y el stack
    print cadena2.index(i), i, stack, postfix

# termina añadiendo el stack a la cadena postfix
while len(stack)>=1:
    if prefoper[operadores.index(stack[len(stack)-1])]>=0:
        postfix+=" "+stack[len(stack)-1]
    stack.pop()

print postfix

# ============================
# Cálculo de la cadena postfix
# ============================

pila=[]
pila=postfix.split(" ")
calculo=[]
# print pila

while len(pila)>0:
   
    item = pila.pop(0)
    # print item
   
    if item=="+" and len(calculo)>1:
        calculo.append(calculo.pop()+calculo.pop())
    elif item=="-" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(calculo.pop()-tmp)
    elif item=="*" and len(calculo)>1:
        calculo.append(calculo.pop()*calculo.pop())
    elif item=="/" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(calculo.pop()/tmp)
    elif item=="^" and len(calculo)>1:
        tmp = calculo.pop()
        calculo.append(pow(calculo.pop(),tmp))
    elif item=="sin":
        calculo.append(math.sin(calculo.pop()))
    elif item=="cos":
        calculo.append(math.cos(calculo.pop()))
    elif item=="tan":
        calculo.append(math.tan(calculo.pop()))
    elif item=="sec":
        calculo.append(1/math.cos(calculo.pop()))
    elif item=="cosec":
        calculo.append(1/math.sin(calculo.pop()))
    elif item=="cotan":
        calculo.append(1/math.tan(calculo.pop()))
    elif item=="ln":
        calculo.append(math.log(calculo.pop()))
    elif item=="log":
        calculo.append(math.log10(calculo.pop()))
    elif item=="exp":
        calculo.append(math.exp(calculo.pop()))
    elif item=="sqr":
        calculo.append(pow(calculo.pop(),0.5))
    elif esFloat(item):
        calculo.append(float(item))
    else:
        pass
      
    print calculo
   
print "El resultado es: %.4f" % (calculo[0])


   




No hay comentarios:

Publicar un comentario