The idea is to accept an English string of math operations and evaluate it from left to right.
Regarding Order of Operations: when speaking operations aloud, it is often with implied parenthesis that denotes a left-to-right chain.
For example:
4 plus 3 times 2 squared === (((4 plus 3) times 2) squared)
The rhythm which it was spoken dictates whether or not to square the 2 before multiplying — but in this case the goal is to go strictly left-to-right.
The starting point to my review here was my answer to a StackOverflow question which was direct, correct, but unsatisfying in design and style.
import math
import re
import operator
# try "3 add 4 times 5"
inputs = input(">").lower()
# Using RE to find all numbers in string.
numInString = [int(d) for d in re.findall(r'-?\d+', inputs)]
inputs = inputs.split()
print('Numbers found: ', numInString)
print('Inputs found: ', inputs)
# Define all of the operators
def multiplication():
multAns = operator.mul(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, multAns)
print(multAns)
def division():
divAns = operator.truediv(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, divAns)
print(divAns)
def addition():
addAns = operator.add(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, addAns)
print(addAns)
def subtraction():
subAns = operator.sub(numInString.pop(0) , numInString.pop(0))
numInString.insert(0, subAns)
print(subAns)
def squareRoot():
SqrtAns = math.sqrt(numInString.pop(0))
numInString.insert(0, SqrtAns)
print(SqrtAns)
def squared():
SquareAns = math.pow(numInString.pop(0), 2)
numInString.insert(0, SquareAns)
print(SquareAns)
def cubed():
CubedAns = math.pow(numInString.pop(0), 3)
numInString.insert(0, CubedAns)
print(CubedAns)
def power():
PowerAns = math.pow(numInString.pop(0), numInString[1])
numInString.insert(0, PowerAns)
print(PowerAns)
# Dictionary mapping search words to operator function
Operation = {
'multiply': multiplication,
'times' : multiplication,
'multiplied': multiplication,
'divide': division,
'divided': division,
'into': division,
'add': addition,
'sum': addition,
'added': addition,
'subtract': subtraction,
'minus': subtraction,
'take': subtraction,
'subtracted': subtraction,
}
for words in inputs:
if words in Operation:
print(Operation[words]())
How should I be naming variables? Are
Operation
andnumInString
good names?Should I print the result of a function operator?
Should I be storing the numbers in a global list (e.g.
numInString
) instead of passing them to operator functions?Should I print errors like this?:
print('NO OPERATION GIVEN')
Is it okay to assume all numbers will be of type
int
?Should I leave unguarded script code such as
input('>')
?