Python Calculator, specifically getNextNumber function not working properly - python

I tried to work out a simple python calculator using stacks and it works only on situations where a negative number is first and when there isn't a negative number but when a situation arises such as 4*-2 for example, it gives an error (my eyes are on getNextNumber and isNumber and findNextOpr. Is there a way to fix this? Here's the code:
import pdb
class Stack:
def __init__(self):
self.container = []
def isEmpty(self):
return self.size() == 0
def push(self, item):
self.container.append(item)
def pop(self):
return self.container.pop()
def size(self):
return len(self.container)
class stack:
class node:
def __init__(self, value, nextNode):
self.value = value
self.nextNode = nextNode
def __init__(self):
self.top = None
self.last = None
self.size = 0
def __len__(self):
return self.size
def isEmpty(self):
return self.size == 0
def push(self, value):
if self.size == 0:
self.top = self.last = self.node(value, None)
else:
newNode = self.node(value, None)
newNode.nextNode = self.top
self.top = newNode
self.size += 1
def pop(self):
if self.size == 0:
return 'Error: stack.pop'
elif self.size == 1:
value = self.top.value
self.top = self.last = None
self.size -= 1
return value
else:
value = self.top.value
self.top = self.top.nextNode
self.size -= 1
return value
def findNextOpr(s):
if len(s) <= 0 or not isinstance(s, str):
print('Type mismatch error: findNextOpr')
return 'Type mismatch error: findNextOpr'
for n in range(len(s)):
if ord(s[n]) == 42 or ord(s[n]) == 43 or ord(s[n]) == 45 or ord(s[n]) == 47 or ord(s[n]) == 94:
return n
else:
continue
return -1
def isNumber(s):
if len(s) == 0 or not isinstance(s, str):
print('Type mismatch error: isNumber')
return 'Type mismatch error: isNumber'
try:
float(s)
return True
except:
return False
def getNextNumber(expr, pos):
#pdb.set_trace()
if len(expr) == 0 or not isinstance(expr, str) or pos < 0 or pos >= len(expr) or not isinstance(pos, int):
print('Type mismatch error: getNextNumber')
return None, None, 'Type mismatch error: getNextNumber'
m = findNextOpr(expr[pos:])
if m != -1:
opr = expr[m]
if isNumber(expr[pos: m + pos]) is True:
return float(expr[pos: m + pos]), expr[pos + m], m
elif isNumber(expr[pos:m+pos]) is False:
if expr[m+1] == '-':
pos = m+1
num=getNextNumber(expr,pos)
return -float(num),None,None
else:
return None, None, None
elif m == -1:
if isNumber(expr[pos:]) is True:
return float(expr[pos:]), None, None
else:
return None, None, None
def exeOpr(num1, opr, num2):
if opr == '+':
return num1 + num2
elif opr == '-':
return num1 - num2
elif opr == '*':
return num1 * num2
elif opr == '/':
if num2 == 0:
print('Zero division error: exeOpr')
return 'Zero division error: exeOpr'
else:
return num1 / num2
elif opr == '^':
return num1 ** num2
else:
print('Fatal internal error in exeOpr')
return 'Fatal internal error in exeOpr'
def _calc(expr):
if not isinstance(expr, str) or len(expr) <= 0:
print('Argument error: Line A in eval_expr')
return 'Argument error: Line A in eval_expr'
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
if newNumber is None:
print('Input formula error: Line B in eval_expr')
return 'Input formula error: Line B in eval_expr'
elif newOpr is None:
return newNumber
elif newOpr == '+' or newOpr == '-':
mode = 'add'
addResult = newNumber
mulResult = 1
expResult = 0
elif newOpr == '*' or newOpr == '/':
mode = 'mul'
addResult = 0
mulResult = newNumber
expResult = 1
elif newOpr == '^':
mode = 'exp'
addResult = 0
mulResult = 1
expResult = newNumber
pos = oprPos + 1
opr = newOpr
while True:
nextNumber, newOpr, oprPos = getNextNumber(expr, pos)
if nextNumber is None or pos >= len(expr):
print('Input formula error: Line C in calc')
return 'Input formula error: Line C in calc'
elif newOpr is None:
if mode == 'add':
return exeOpr(addResult, opr, nextNumber)
elif mode == 'mul':
return exeOpr(mulResult, opr, nextNumber) + addResult
elif mode == 'exp':
return exeOpr(expResult, opr, nextNumber) * mulResult + addResult
oprPos += pos
pos = oprPos + 1
if mode == 'add':
if newOpr == '+' or newOpr == '-':
addResult = exeOpr(addResult, opr, nextNumber)
mode = 'add'
elif newOpr == '*' or newOpr == '/':
if opr == '+':
mulResult = nextNumber
elif opr == '-':
mulResult = -nextNumber
mode = 'mul'
elif newOpr == '^':
if opr == '+':
expResult = nextNumber
elif opr == '-':
expResult = - nextNumber
mode = 'exp'
elif mode == 'mul':
if newOpr == '*' or newOpr == '/':
mulResult = exeOpr(mulResult, opr, nextNumber)
mode = 'mul'
elif newOpr == '+' or newOpr == '-':
addResult += exeOpr(mulResult, opr, nextNumber)
elif newOpr == '^':
if opr == '*':
expResult = 1 / nextNumber
mode = 'exp'
elif mode == 'exp':
if newOpr == '^':
expResult = exeOpr(expResult, opr, nextNumber)
mode = 'exp'
elif newOpr == '+' or newOpr == '-':
addResult = exeOpr(expResult, opr, nextNumber) * mulResult + addResult
mode = 'add'
elif newOpr == '*' or newOpr == '/':
mulResult = exeOpr(expResult, opr, nextNumber) * mulResult
mode = 'mul'
opr = newOpr
def icheck(expr):
d = None
if expr[0] == '-':
expr = '0' + expr
for i in range(len(expr)):
if expr[i] == '(':
d = i
elif expr[i] == '':
continue
elif d is not None and expr[i] == '-':
for j in range(i + 1, len(expr)):
if expr[j] == '':
continue
else:
expr = expr[0: d + 1] + '0' + expr[d+1:]
d = None
break
else:
d = None
return expr
def pcheck(expr):
expr = expr.replace(' ', '')
per = Stack()
for i in range(len(expr)):
if expr[i] == '(':
if i != 0 and isNumber(expr[i - 1]) == True:
print('Omitting Operator')
return False
per.push(i)
elif expr[i] == ')':
if i != (len(expr) - 1) and isNumber(expr[i + 1]) == True:
print('Omitting Operator')
return False
try:
per.pop()
except IndexError:
print('Parenthesis are unbalanced')
return False
return per.isEmpty()
def calc(e, u=None):
if len(e) == 0:
return 'Empty String'
e = e.replace(' ', '')
if u is None:
e = icheck(e)
tf = pcheck(e)
if tf is False:
return IndexError
st = Stack()
b = None
for i in range(len(e)):
pos = i
if e[i] == '(':
st.push(i)
elif e[i] == ')':
b = st.pop()
c = i
break
if b is None:
return _calc(e)
if st.size() == 0 and (pos == len(e) - 1):
res = _calc(e[b+1:c])
if len(e) > c:
e = e[:b] + str(res) + e[c + 1:]
else:
e = e[:b] + str(res)
return _calc(e)
else:
res = _calc(e[b + 1: c])
e = e[:b] + str(res) + e[c + 1:]
return calc(e, u=1)
print(calc('2.0*-2+5'))
print(calc('-2.0+1'))
print(calc('4*-2'))
print(calc('2+3*(-2 +(-3)*(5^2-2*3^(-2))*(-4))*(2/8+2*(3–1/3))-2/3^2'))
print(calc('1+3-2/30^2/5-1*5*3*4/3-1^2/6/7/8+3-1/2^2*3/2+3+1^2^2+3/3^2'))

This is an expected issue. To overcome this, electronic calculators usually use minus and negative signs seperately (which are the same in Python, causing your problem). You can apply this by creating an operator classes for these, assign them spesific purposes.
Alternatively, you can enforce the correct usage of paranthesis when the input is taken, or pre-check the input and convert it without bothering the user, make it a computer usable format (add paranthesis or whatsoever).

Related

TypeError: cannot unpack non-iterable NoneType object Error

I looked at the other answers but they didn't seem to work for me, or I could just be doing something wrong, or not understanding what I am supposed to do in the context of this code. On line 78, it talks about how there is a Nonetype value, even though I assigned a value to both variables no matter what.
Here is a link to a similar problem (I think):
[https://stackoverflow.com/questions/53680913/typeerror-cannot-unpack-non-iterable-nonetype-object][1]
Here is where I think the faulty code lies:
def check_win(turn, gamestate):
if turn == 1:
if gamestate[0] == gamestate[1] == gamestate[2] != '-' or gamestate[3] == gamestate[4] == gamestate[5] != '-' or gamestate[6] == gamestate[7] == gamestate[8] != '-':
winner = 1
win = True
return winner, win
elif gamestate[0] == gamestate[3] == gamestate[6] != '-' or gamestate[1] == gamestate[4] == gamestate[7] != '-' or gamestate[2] == gamestate[5] == gamestate[8] != '-':
winner = 1
win = True
return winner, win
elif gamestate[0] == gamestate[4] == gamestate[8] != '-' or gamestate[2] == gamestate[4] == gamestate[6] != '-':
winner = 1
win = True
return winner, win
elif turn == 2:
if gamestate[0] == gamestate[1] == gamestate[2] or gamestate[3] == gamestate[4] == gamestate[5] or gamestate[6] == gamestate[7] == gamestate[8]:
winner = 2
win = True
return winner, win
elif gamestate[0] == gamestate[3] == gamestate[6] or gamestate[1] == gamestate[4] == gamestate[7] or gamestate[2] == gamestate[5] == gamestate[8]:
winner = 2
win = True
return winner, win
elif gamestate[0] == gamestate[4] == gamestate[8] or gamestate[2] == gamestate[4] == gamestate[6]:
winner = 2
win = True
return winner, win
else:
winner = 'None'
win = False
return winner, win
Later on when I try to alter those values in another function:
winner, win = check_win(turn, gamestate) <--- Where error was found
Here is the code in its entirety :
print('Tic Tac Toe:')
pos = 0
turn = 1
gamestate = ['-', '-', '-', '-', '-', '-', '-', '-', '-']
def display_board(gamestate):
print(gamestate[0:3])
print(gamestate[3:6])
print(gamestate[6:9])
def move_validity(pos, gamestate):
if str(gamestate[int(pos)]) != '-':
print('Invalid move.')
valid = False
return valid
else:
valid = True
return valid
def update(gamestate, pos):
if turn == 1:
gamestate[int(pos)] = 'X'
if turn == 2:
gamestate[int(pos)] = 'O'
else:
print('ERROR')
def check_win(turn, gamestate):
if turn == 1:
if gamestate[0] == gamestate[1] == gamestate[2] != '-' or gamestate[3] == gamestate[4] == gamestate[5] != '-' or gamestate[6] == gamestate[7] == gamestate[8] != '-':
winner = 1
win = True
return winner, win
elif gamestate[0] == gamestate[3] == gamestate[6] != '-' or gamestate[1] == gamestate[4] == gamestate[7] != '-' or gamestate[2] == gamestate[5] == gamestate[8] != '-':
winner = 1
win = True
return winner, win
elif gamestate[0] == gamestate[4] == gamestate[8] != '-' or gamestate[2] == gamestate[4] == gamestate[6] != '-':
winner = 1
win = True
return winner, win
elif turn == 2:
if gamestate[0] == gamestate[1] == gamestate[2] or gamestate[3] == gamestate[4] == gamestate[5] or gamestate[6] == gamestate[7] == gamestate[8]:
winner = 2
win = True
return winner, win
elif gamestate[0] == gamestate[3] == gamestate[6] or gamestate[1] == gamestate[4] == gamestate[7] or gamestate[2] == gamestate[5] == gamestate[8]:
winner = 2
win = True
return winner, win
elif gamestate[0] == gamestate[4] == gamestate[8] or gamestate[2] == gamestate[4] == gamestate[6]:
winner = 2
win = True
return winner, win
else:
winner = 'None'
win = False
return winner, win
def restart():
gamestate = ['-', '-', '-', '-', '-', '-', '-', '-', '-']
turn = 1
win = False
return gamestate, turn, win
def choose_position():
pos = input('Player ' + str(turn) + ': ')
if int(pos) < 0 or int(pos) > 8:
print('Invalid move')
else:
return pos
def Tic_Tac_Toe():
while True:
global pos
global turn
if turn == 1:
pos = choose_position()
valid = move_validity(pos, gamestate)
if valid == True:
update(gamestate, pos)
if valid == False:
break
winner, win = check_win(turn, gamestate)
if win == True:
print(str(winner) + ' wins!')
break
if '-' not in gamestate:
print('Tie game.')
break
if turn == 2:
pos = choose_position()
if move_validity(pos, gamestate) == True:
continue
if move_validity(pos, gamestate) == False:
break
update(gamestate, pos)
winner, win = check_win(turn, gamestate)
if win == True:
print(str(winner) + ' wins!')
break
turn = 1
if '-' not in gamestate:
print('Tie game.')
break
display_board(gamestate)
display_board(gamestate)
Tic_Tac_Toe()
restart_case = input('y/n Would you like to play? ')
if restart_case == 'y':
gameboard, turn, win = restart()
Thank you so much, and sorry if the solution was a small typo, I am really new to this and have spent way too much time on this. :D
There are certain cases where you don't return anything in the function check_win.
For example, when turn == 1, you have an if, elif, elif block within that, but nothing for else. So, when turn == 1, if none of the if statements within the block for that are true, your function will return nothing. There is a similar problem for turn == 2. You may want to add the code you have in the else block for that function as an else block for both turn == 1 and turn == 2, as this will fix your problem.

Separating out 'While' function

I currently have defined my object (is_matched) that contains a while loop and also the checking of a string. I am trying to pull out the while loop into it's own object but am having trouble completing the coding. I also need the while loop to continue running until a user enters 'q' into the input.
def is_matched():
while True:
expr = input("Enter string (q to quit): ")
if expr == "q":
break
stack = Stack()
for i in expr:
if i == '{' or i == '(' or i == '[':
stack.push(i)
elif i == '}':
if len(expr) != 0:
c = stack.top()
if c == '{':
stack.pop()
else:
return "Unbalanced"
elif i == ')':
if len(expr) != 0:
c = stack.top()
if c == '(':
stack.pop()
else:
return "Unbalanced"
elif i == ']':
if len(expr) != 0:
c = stack.top()
if c == '[':
stack.pop()
else:
return "Unbalanced"
else:
return "Unbalanced"
if len(stack) != 0:
return "Unblanced"
return "Balanced"
result = is_matched()
print(result)
I am trying to pull out the while loop from above and enter into its own object as follows:
def main():
while True:
expr = input("Enter string (q to quit): ")
if expr == "q":
break
else:
return is_matched()
your is_matched function will take one argument which will be the expression to evaluate.
def is_matched(expr):
stack = Stack()
for i in expr:
if i == '{' or i == '(' or i == '[':
stack.push(i)
elif i == '}':
if len(expr) != 0:
c = stack.top()
if c == '{':
stack.pop()
else:
return "Unbalanced"
elif i == ')':
if len(expr) != 0:
c = stack.top()
if c == '(':
stack.pop()
else:
return "Unbalanced"
elif i == ']':
if len(expr) != 0:
c = stack.top()
if c == '[':
stack.pop()
else:
return "Unbalanced"
else:
return "Unbalanced"
if len(stack) != 0:
return "Unblanced"
return "Balanced"
main function.
def main():
while True:
expr = input("Enter string (q to quit): ")
if expr == "q":
break
else:
print(is_matched(expr))

Calculator output wrong answer

import math
def findNextOpr(txt):
if len(txt)<=0 or not isinstance(txt,str):
return "type error: findNextOpr"
# --- YOU CODE STARTS HERE
if type(txt) == str:
opr_list = ["+", "-", "*", "/", '^']
for i in range(len(txt)):
if txt[i] in opr_list:
return(i)
return(-1)
# --- CODE ENDS HERE
def isNumber(txt):
if not isinstance(txt, str):
return "type error: isNumber"
if len(txt)==0:
return False
# --- YOU CODE STARTS HERE
if type(txt) == str:
try:
float(txt)
return True
except ValueError:
return False
def getNextNumber(expr, pos):
if len(expr)==0 or not isinstance(expr, str) or pos<0 or pos>=len(expr) or not isinstance(pos, int):
return None, None, "type error: getNextNumber"
# --- YOU CODE STARTS HERE
txt = expr[pos:]
oprPos = findNextOpr(txt)
if oprPos != -1:
if isNumber(txt[:oprPos]) == True:
return float(txt[:oprPos]), txt[oprPos], oprPos+pos
else:
return None, txt[oprPos], oprPos+pos
else:
if isNumber(txt):
return float(txt), None, None
else:
return None,None,None
# --- CODE ENDS HERE
def exeOpr(num1, opr, num2):
#This function is just an utility function for calculator(expr). It is skipping type check
if opr=="+":
return num1+num2
elif opr=="-":
return num1-num2
elif opr=="*":
return num1*num2
elif opr=="/":
return num1/num2
elif opr=="^":
return num1**num2
else:
return "error in exeOpr"
def calculator(expr):
if len(expr)<=0 or not isinstance(expr,str):
return "error"
expr = expr.strip()
if expr[0]!="-":
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
else:
newNumber, newOpr, oprPos = getNextNumber(expr, 1)
newNumber *= -1
if newNumber is None:
return "error"
elif newOpr is None:
return newNumber
elif newOpr=="+" or newOpr=="-":
mode="add"
addResult=newNumber
mulResult=None
expResult=None
elif newOpr=="*" or newOpr=="/":
mode="mul"
addResult=0
mulResult=newNumber
expResult=None
elif newOpr=="^":
mode="exp"
expResult=newNumber
addResult=0
mulResult=None
pos=oprPos+1
opr=newOpr
oldopr=None
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
if newNumber is None:
return "input error: line B in calculator"
elif newOpr is None:
if mode=='add':
if opr=='*':
return exeOpr(addResult, oldopr, mulResult*newNumber)
elif opr=='/':
return exeOpr(addResult, oldopr, mulResult/newNumber)
else:
return exeOpr(addResult, opr, newNumber)
elif mode=='mul':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
return addResult + exeOpr(mulResult, opr, newNumber)
elif mode=="exp":
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
else:
expResult=exeOpr(expResult,opr,newNumber)
if mulResult!=0 and (oldopr=='*' or oldopr=='/'):
mulResult=exeOpr(mulResult,oldopr,expResult)
expResult=0
elif newOpr=='+' or newOpr=='-':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
if mode=='add':
addResult = exeOpr(addResult, opr, newNumber)
mulResult = 0
expResult= 0
elif mode=='mul':
addResult += exeOpr(mulResult, opr, newNumber)
mulResult = 0
expResult= 0
elif mode=='exp':
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
addResult+=expResult
else:
addResult+=exeOpr(expResult,opr,newNumber)
if oldopr=='*' or oldopr=='/':
expResult=exeOpr(expResult,opr,newNumber)
mulResult=exeOpr(mulResult,oldopr,expResult)
addResult+=mulResult
mulResult = 0
expResult = 0
mode='add'
elif newOpr=="*" or newOpr=="/":
if mode=='add':
if opr=='-':
oldopr='-'
mulResult = newNumber
elif opr=='+':
#print('here1')
oldopr='+'
mulResult = newNumber
mode='mul'
else:
mulResult = newNumber
elif mode=='mul':
mulResult = exeOpr(mulResult, opr, newNumber)
elif mode=='exp':
if expResult<0:
expResult=exeOpr(expResult,opr,newNumber)
if expResult>0:
expResult=-1*expResult
else:
expResult=exeOpr(expResult,opr,newNumber)
if mulResult !=0 and (oldopr=='*' or oldopr=='/'):
mulResult=exeOpr(mulResult,oldopr,expResult)
expResult=0
else:
mulResult=expResult
expResult=0
mode='mul'
elif newOpr=='^':
if mode=='add':
if expResult==None:
expResult=0
if mulResult==None:
mulResult=0
if opr=='-':
expResult = -newNumber
else:
expResult = newNumber
oldopr=opr
elif mode=='mul':
expResult=newNumber
oldopr=opr
mode='exp'
if oprPos==None:
break
pos=oprPos + 1
opr=newOpr
if mulResult== None:
mulResult=0
if expResult==None:
expResult=0
return addResult+mulResult+expResult
Above is my code for a functional calculator no errors at all but when I run the code and try
calculator('-5 + 60 / 3^3 * 4 - 2 * 4^2')
I get 35.888888888888886 but the answer should be -28.11111111111111
Is there a mistake someone in my code that I cannot find?
I think it might be in the calculator section since everything else works perfectly fine with tests but I just can't find where.
I was told that one way to solve in class was that maybe using a node/stack class might help but is there any other solution than creating another class
In the calculator big loop, when opr is -, you forgot to change the sign of mulResult.
In order to debug it, I added a print statement to the exeOpr function, so that we could see what the calculator is doing at each step. Then it was easy to determine by looking at the partial results.
The full new code is like this:
import math
def findNextOpr(txt):
if len(txt) <= 0 or not isinstance(txt, str):
return "type error: findNextOpr"
# --- YOU CODE STARTS HERE
if type(txt) == str:
opr_list = ["+", "-", "*", "/", '^']
for i in range(len(txt)):
if txt[i] in opr_list:
return (i)
return (-1)
# --- CODE ENDS HERE
def isNumber(txt):
if not isinstance(txt, str):
return "type error: isNumber"
if len(txt) == 0:
return False
# --- YOU CODE STARTS HERE
if type(txt) == str:
try:
float(txt)
return True
except ValueError:
return False
def getNextNumber(expr, pos):
if len(expr) == 0 or not isinstance(expr, str) or pos < 0 or pos >= len(expr) or not isinstance(pos, int):
return None, None, "type error: getNextNumber"
# --- YOU CODE STARTS HERE
txt = expr[pos:]
oprPos = findNextOpr(txt)
if oprPos != -1:
if isNumber(txt[:oprPos]):
return float(txt[:oprPos]), txt[oprPos], oprPos + pos
else:
return None, txt[oprPos], oprPos + pos
else:
if isNumber(txt):
return float(txt), None, None
else:
return None, None, None
# --- CODE ENDS HERE
def exeOpr(num1, opr, num2):
# This function is just an utility function for calculator(expr). It is skipping type check
print("%s %s %s" % (num1, opr, num2)) # <==== DEBUGGING PRINT
if opr == "+":
return num1 + num2
elif opr == "-":
return num1 - num2
elif opr == "*":
return num1 * num2
elif opr == "/":
return num1 / num2
elif opr == "^":
return num1 ** num2
else:
return "error in exeOpr"
def calculator(expr):
if len(expr) <= 0 or not isinstance(expr, str):
return "error"
expr = expr.strip()
if expr[0] != "-":
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
else:
newNumber, newOpr, oprPos = getNextNumber(expr, 1)
newNumber *= -1
if newNumber is None:
return "error"
elif newOpr is None:
return newNumber
elif newOpr == "+" or newOpr == "-":
mode = "add"
addResult = newNumber
mulResult = None
expResult = None
elif newOpr == "*" or newOpr == "/":
mode = "mul"
addResult = 0
mulResult = newNumber
expResult = None
elif newOpr == "^":
mode = "exp"
expResult = newNumber
addResult = 0
mulResult = None
pos = oprPos + 1
opr = newOpr
oldopr = None
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
if newNumber is None:
return "input error: line B in calculator"
elif newOpr is None:
if mode == 'add':
if opr == '*':
return exeOpr(addResult, oldopr, mulResult * newNumber)
elif opr == '/':
return exeOpr(addResult, oldopr, mulResult / newNumber)
else:
return exeOpr(addResult, opr, newNumber)
elif mode == 'mul':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
return addResult + exeOpr(mulResult, opr, newNumber)
elif mode == "exp":
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
else:
expResult = exeOpr(expResult, opr, newNumber)
if mulResult != 0 and (oldopr == '*' or oldopr == '/'):
mulResult = exeOpr(mulResult, oldopr, expResult)
expResult = 0
elif newOpr == '+' or newOpr == '-':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
if mode == 'add':
addResult = exeOpr(addResult, opr, newNumber)
mulResult = 0
expResult = 0
elif mode == 'mul':
addResult += exeOpr(mulResult, opr, newNumber)
mulResult = 0
expResult = 0
elif mode == 'exp':
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
addResult += expResult
else:
addResult += exeOpr(expResult, opr, newNumber)
if oldopr == '*' or oldopr == '/':
expResult = exeOpr(expResult, opr, newNumber)
mulResult = exeOpr(mulResult, oldopr, expResult)
addResult += mulResult
mulResult = 0
expResult = 0
mode = 'add'
elif newOpr == "*" or newOpr == "/":
if mode == 'add':
if opr == '-':
oldopr = '-'
mulResult = -newNumber # <====== THIS IS THE PLACE I CHANGED
elif opr == '+':
# print('here1')
oldopr = '+'
mulResult = newNumber
mode = 'mul'
else:
mulResult = newNumber
elif mode == 'mul':
mulResult = exeOpr(mulResult, opr, newNumber)
elif mode == 'exp':
if expResult < 0:
expResult = exeOpr(expResult, opr, newNumber)
if expResult > 0:
expResult = -1 * expResult
else:
expResult = exeOpr(expResult, opr, newNumber)
if mulResult != 0 and (oldopr == '*' or oldopr == '/'):
mulResult = exeOpr(mulResult, oldopr, expResult)
expResult = 0
else:
mulResult = expResult
expResult = 0
mode = 'mul'
elif newOpr == '^':
if mode == 'add':
if expResult == None:
expResult = 0
if mulResult == None:
mulResult = 0
if opr == '-':
expResult = -newNumber
else:
expResult = newNumber
oldopr = opr
elif mode == 'mul':
expResult = newNumber
oldopr = opr
mode = 'exp'
if oprPos == None:
break
pos = oprPos + 1
opr = newOpr
if mulResult == None:
mulResult = 0
if expResult == None:
expResult = 0
return addResult + mulResult + expResult
x = calculator('-5 + 60 / 3^3 * 4 - 2 * 4^2')
print(x)

Turning a string to an integer - TypeError: '>' not supported between instances of 'str' and 'int'

I am having the error come up as the >not supported between instances of 'str' and 'int'. This is at the part where it says 'if guess[1] in secretNum > 1'. I realise that this is comparing a string to an integer but i don't know how to change that. Any Help?
clue0 = []
clue1 = []
clue2 = []
clue3 = []
if guess[0] in secretNum:
clue0 = ['Pico']
if guess[0] == secretNum[0]:
clue0 = ['Fermi']
if guess[1] in secretNum or guess[1] == guess[0]:
if guess[1] == guess[0]:
if guess[1] in secretNum > 1:
clue1 == ['Pico']
else:
clue1 == []
else:
clue1 = ['Pico']
if guess[1] == secretNum[1]:
clue1 == ['Fermi']
if guess[2] in secretNum or guess[2] == guess[0] or guess[2] == guess[1]:
if guess[2] == guess[1] or guess[2] == guess[0]:
if guess[2] in secretNum > 2:
clue2 == ['Pico']
else:
clue2 == []
else:
clue2 = ['Pico']
if guess[2] == secretNum[2]:
clue2 == ['Fermi']
if guess[3] in secretNum or guess[3] == guess[0] or guess[3] == guess[1] or guess[3] == guess[2]:
if guess[3] == guess[1] or guess[3] == guess[0] or guess[3] == guess[2]:
if guess[3] in secretNum > 3:
clue3 == ['Pico']
else:
clue3 == []
else:
clue3 = ['Pico']
if guess[3] == secretNum[3]:
clue3 == ['Fermi']
clue = clue0 + clue1 + clue2 + clue3
if len(clue) == 0:
return 'Bagels'
clue.sort()
return ' '.join(clue)
guess[1] in secretNum > 1 equals to guess[1] in secretNum and secretNum > 1, secretNum seems to be string so the comparison after and is invalid (str > int)
if you want to count how many times guess[1] is in secretNumber you should use secretNumber.count(guess[1])

changing numbers to letters in Python

So this function takes inputs from the user and converts their input into a value. For example, if they put in 1k, the output would be 1000. I want to be able to go backwards. So say if I had a value of 325000, I want to change that to 325k. Any ideas on how I could achieve this?
class Parsing:
def __init__(self, instring):
self.instring = instring
def valueParsing(self):
self.instring = self.instring.strip()
self.parsedString = ''
self.scalerDict = {'K': 1000, 'MEG': 1000000, 'G': 1000000000, 'M': 0.001, 'U': 0.000001, 'N': 0.000000001, 'P': 0.000000000001}
self.scaler = 1.0
self.stringCounter = 0
self.errorflag = False
self.Parsedvalue = 0.0
self.inStringLength = len(self.instring)
for self.stringCounter in range (self.inStringLength):
if ((self.instring[self.stringCounter].upper()) == 'K'):
self.scaler = self.scalerDict['K']
elif ((self.instring[self.stringCounter].upper()) == 'G'):
self.scaler = self.scalerDict['G']
elif ((self.instring[self.stringCounter].upper()) == 'U'):
self.scaler = self.scalerDict['U']
elif ((self.instring[self.stringCounter].upper()) == 'N'):
self.scaler = self.scalerDict['N']
elif ((self.instring[self.stringCounter].upper()) == 'P'):
self.scaler = self.scalerDict['P']
elif ((self.instring[self.stringCounter].upper()) == 'M'):
if (((self.instring.upper()).count('MEG'))):
self.scaler = self.scalerDict['MEG']
else:
self.scaler = self.scalerDict['M']
elif (( self.instring[ self.stringCounter ].upper() ) == 'F' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'W' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'S' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == '%' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'V' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'A' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'H' ):
break
elif (( self.instring[ self.stringCounter ].upper() ) == 'Z' ):
break
elif (( self.instring[ self.stringCounter ]) == '.' ):
self.parsedString = self.parsedString + self.instring[ self.stringCounter ]
elif (self.instring[self.stringCounter].isdigit()):
if(int(self.instring[self.stringCounter]) >= 0):
if(int(self.instring[self.stringCounter]) <= 9):
self.parsedString = self.parsedString + self.instring[self.stringCounter]
else:
self.errorflag = True
break
else:
self.errorflag = True
print('Invalid input, Try again.')
if (self.errorflag):
self.parsedvalue = -1
else:
self.parsedvalue = long(self.parsedString)*self.scaler
return self.parsedvalue
print '1. Resistors in series\n',\
'2. Resistors in Parallel\n',\
'3. Voltage Divider\n'
iput = int(input("Enter your choice: "))
if iput == 1:
r1 = raw_input("Enter first resistor:")
r2 = raw_input("Enter second resistor:")
R1 = Parsing(r1)
R2 = Parsing(r2)
req = R1.valueParsing() + R2.valueParsing()
print "The value of the series resistors is %s." % req
Try this:
import math
def fmtnum(num):
k = (1e3, 'k')
M = (1e6, 'M')
G = (1e9, 'G')
table = {3: k, 4: k, 5: k, 6: M, 7: M, 8: M, 9: G, 10: G, 11: G}
num = float(num)
exp = math.log10(num)
if num < 0:
exp = int(exp)-1
else:
exp = int(exp)
try:
denum, suffix = table[exp]
return '{:g} {}'.format(num/denum, suffix)
except KeyError:
return '{:g}'.format(num)
Extending this solution for negative powers of 10 has been left as an exercise for the reader. :-)
Examples:
In [50]: fmtnum(3250)
Out[50]: '3.25 k'
In [51]: fmtnum(32500)
Out[51]: '32.5 k'
In [52]: fmtnum(325000)
Out[52]: '325 k'
In [53]: fmtnum(3250000)
Out[53]: '3.25 M'
In [54]: fmtnum(32500000)
Out[54]: '32.5 M'
In [55]: fmtnum(325000000)
Out[55]: '325 M'
In [56]: fmtnum(3250000000)
Out[56]: '3.25 G'
how about:
n = 1000
for exp, name in zip(range(9, -13, -3), ('GMk1munp')):
if exp == 0:
continue
if isinstance(n, int):
if n % 10**exp == 0:
n = '{0:d}{1}'.format(n / 10**exp, name)
break
elif isinstance(n, basestring):
if n[-exp:] == '0' * exp:
n = '{0}{1}'.format(n[:-exp], name)
break
elif n[-1] == name:
n = n[:-1] + '0' * exp
break
by running exponents backwards you make sure that you find the right match.

Categories

Resources