Calculator changes for Anant

This commit is contained in:
Piotr Mitros
2012-02-03 18:48:44 -05:00
parent 81e1a8dc12
commit 6304feefd6
2 changed files with 33 additions and 9 deletions

View File

@@ -1,17 +1,41 @@
import copy
import math
import operator
import numpy
from pyparsing import Word, alphas, nums, oneOf, Literal
from pyparsing import ZeroOrMore, OneOrMore, StringStart
from pyparsing import StringEnd, Optional, Forward
from pyparsing import CaselessLiteral, Group, StringEnd
from pyparsing import NoMatch, stringEnd
default_functions = {'sin' : numpy.sin,
'cos' : numpy.cos,
'tan' : numpy.tan,
'sqrt': numpy.sqrt,
'log10':numpy.log10,
'log2':numpy.log2,
'ln': numpy.log,
'arccos':numpy.arccos,
'arcsin':numpy.arcsin,
'arctan':numpy.arctan,
'abs':numpy.abs
}
default_variables = {'j':numpy.complex(0,1),
'e':numpy.complex(numpy.e)
}
def evaluator(variables, functions, string):
''' Evaluate an expression. Variables are passed as a dictionary
from string to value. Unary functions are passed as a dictionary
from string to function '''
all_variables = copy.copy(default_variables)
all_variables.update(variables)
all_functions = copy.copy(default_functions)
all_functions.update(functions)
if string.strip() == "":
return float('nan')
ops = { "^" : operator.pow,
@@ -38,7 +62,7 @@ def evaluator(variables, functions, string):
def number_parse_action(x): # [ '7' ] -> [ 7 ]
return [super_float("".join(x))]
def exp_parse_action(x): # [ 2 ^ 3 ^ 2 ] -> 512
x = [e for e in x if type(e) == float] # Ignore ^
x = [e for e in x if type(e) in [float, numpy.float64, numpy.complex]] # Ignore ^
x.reverse()
x=reduce(lambda a,b:b**a, x)
return x
@@ -68,7 +92,7 @@ def evaluator(variables, functions, string):
prod=op(prod, e)
return prod
def func_parse_action(x):
return [functions[x[0]](x[1])]
return [all_functions[x[0]](x[1])]
number_suffix=reduce(lambda a,b:a|b, map(Literal,suffixes.keys()), NoMatch()) # SI suffixes and percent
(dot,minus,plus,times,div,lpar,rpar,exp)=map(Literal,".-+*/()^")
@@ -94,14 +118,14 @@ def evaluator(variables, functions, string):
# Handle variables passed in. E.g. if we have {'R':0.5}, we make the substitution.
# Special case for no variables because of how we understand PyParsing is put together
if len(variables)>0:
varnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), variables.keys()))
varnames.setParseAction(lambda x:map(lambda y:variables[y], x))
if len(all_variables)>0:
varnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), all_variables.keys()))
varnames.setParseAction(lambda x:map(lambda y:all_variables[y], x))
else:
varnames=NoMatch()
# Same thing for functions.
if len(functions)>0:
funcnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), functions.keys()))
if len(all_functions)>0:
funcnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), all_functions.keys()))
function = funcnames+lpar.suppress()+expr+rpar.suppress()
function.setParseAction(func_parse_action)
else:
@@ -119,7 +143,7 @@ def evaluator(variables, functions, string):
if __name__=='__main__':
variables={'R1':2.0, 'R3':4.0}
functions={'sin':math.sin, 'cos':math.cos}
functions={'sin':numpy.sin, 'cos':numpy.cos}
print "X",evaluator(variables, functions, "10000||sin(7+5)-6k")
print "X",evaluator(variables, functions, "13")
print evaluator({'R1': 2.0, 'R3':4.0}, {}, "13")

View File

@@ -25,7 +25,7 @@ def calculate(request):
'equation':equation}
track.views.server_track(request, 'error:calc', event, page='calc')
return HttpResponse(json.dumps({'result':'Invalid syntax'}))
return HttpResponse(json.dumps({'result':result}))
return HttpResponse(json.dumps({'result':str(result)}))
def send_feedback(request):
''' Feeback mechanism in footer of every page. '''