I know this question isn’t off topic because I couldn’t place it in any other category, so I chose this one. My question is can I take user input where the user inputs something in the form of PEMDAS in Python. For example, let’s say you wanted to enter your height in feet and you enter 72/(10+2). However, when I tried doing that and converting it to a float, the message popped: ValueError: could not convert string to float: 72/(10+2). So, is there a way to work around that?
When you accept input from the user using the input()
method, the value type you get is string
:
x = input("Some number: ")
#prints: Some number: #example input: 7
print(x)
#prints 7
print(type(x))
#prints <type 'str'>
When you cast int
to float
, you can’t have non-numerical characters (so you can only have 1234567890.
in the string).
So, is there no way to input PEMDAS expressions?
Not that I’m aware of, but you could create one. Take input as a string, then, depending on the characters, perform certain operations on the numbers…
I’m having trouble thinking how I should start off. Would regex be a good first step to validate user input?
Yes; you could check for any characters that do not match PEMDAS characters or numbers…
You can kinda use eval( ) to do this, but it won’t work with the P
I made this script to compare two and return True if they equal the same and False if they don’t
prub_1 = input(“1 “)
calc_one = eval(prub_1)
print(”=”, calc_one)
prub_2 = input(“2 “)
calc_two = eval(prub_2)
print(”=”, calc_two)
resu = (calc_one == calc_two)
if resu == True:
print(“True it do”)
elif resu == False:
print(“False it do’nt”)
I still haven’t figured out how to take input in the form of PEMDAS yet. Using the eval function, it only checks if the provided expression is valid Python syntax and executes it afterwards. How can I use this to allow user input in the form of PEMDAS? For example, the user inputs something like 5+(1/12)*7^2 and Python simplifies this to 9.083333333… How can I allow this type of input?
We would be getting textual information from the user who one would assume is given directions as to what character inputs are allowed. From there we would need to validate the input to make sure all of the characters are allowed. Then we would have to make slight operator and shorthand corrections.
Eg.
^ => **
and,
2(5+12) => 2 * 17
It would be simple to say, ‘evaluate the string’, but what will that entail? How constrained is the expected input? We can see what a nightmare this could be if we placed no limits on the user input in terms of complexity.
How would we go about turning the example expression above into the simplified form,
49
5 + ----
12
?
You should know that ^
is a valid Python Bitwise operator that is nothing to do with exponents.
>>> 2 ^ 2
0
>>> 2 ^ 1
3
>>>
Two squared is not 0; and, two to the first power is not 3. Hmmm, what have we here?
10
10
---
0
10
01
---
11
That looks like an eXclusive OR operation. If we let Python evaluate it, that’s the logic it will follow since it keeps its promise on what operators perform what operation.
111
010
----
101
7 XOR 2 is 5
Python will give us, the value, but the math will be,
5
5 + ----
12
Do we dare change operators in the user input knowing that ^
is a valid operator? This is what I meant by constraints. If we forbid bitwise operations then we can translate the ^
to **
.
Bottom line, the program you will have to write to parse out operations in a user provided string will not be a simple one.
Let’s say we did not forbid bitwise operations and instead denoted ** for exponentiation. As you pointed out, the program to write will not be an easy one. I still have trouble grasping how to go about writing this program given these conditions.
Chances are one would end up writing a library of specialized code, akin to writing a compiler. That is the stuff of computer scientists and engineers.
Consider how Python syntax checking works, or any programming language. We give it raw text and it interprets it by tokenizing the parts it recognizes.
A program to interpret user input of string data representing a mathematical expression would be doing the same thing. Tokenizing special characters to be used as operators, and isolating numeric values.
Using an interface would be the easier approach. Rather than taking string data from a user, they would be selecting tokens from the interface, much the way we do some of the CC quizzes where we click or drag and drop tokens into a workspace in a particular order. How smart we make that interface will determine how much validation needs to be done to the finished expression.
Of course this is going down a different road now. Something to explore through the cold winter months.
I actually did this in Java a few months ago. The short version is that you need to read the input, convert the entire operation into postfix notation (also called Reverse Polish Notation), then do the actual math from there.
It’s pretty complicated to be honest. It will likely be easier in python though.
You can view it on replit if you want: https://replit.com/@DaveAndrea/SmartCalculator#Main.java
Just make sure to put spaces between your numbers and operands
I had actually envisioned working out the order of operations, then piling the numbers in a stack in the determined order, then winding down the stack. It’s way over my head, just now. Just took a look at your code and must say it is impressive. It follows along the same line as my compiler analogy, it would appear?
Basically, yes. It tokenizes everything, then converts into postfix notation, which makes the final step of calculating everything a lot easier. Putting it into postfix notation takes care of the order of operations because it is written so that you can just do the math from left to right. That was probably the hardest part.
For evaluating it, I did use a stack, but it was a simpler situation because the order if operations was already taken care of by the postfix notation. When iterating through the array of tokens, we push the numbers onto the stack until we get to an operator, then pop the numbers off to perform the operation, then push the result back onto the stack so that the result will be used again in the next operation,
I think it is probably just a slightly more modular way of doing what you said you would do. Your stack would be more complex if you made it do order of operations and calculating at the same time.
To be completely honest, this was a project from JetBrains Academy. You can see the overall structure of it without a subscription. https://hyperskill.org/projects/42?track=15
I certainly did not dream up my solution on my own. I used a lot of resources and I was even comparing my code to some C++ code I found online at one point while trying to get one of the algorithms just right. I appreciate you saying it is impressive, but I am honestly more impressed that you were able to articulate a possible solution without having gone through it already. I can only explain it in retrospect.
My best memory of RPN was an HP handheld calculator that used it. A and B were pushed to the stack, and the operator was entered. There wasn’t an =
sign if memory serves. The value was just held until the next op. We’re talking forty years ago so memory is vague and diluted. It’s the only RPN calculator I ever had. Mind, I’ve never been big on calculators, anyway. Used a solar powered TI-53 through high school maths and sciences, and once we learned how to sketch curves using calculus, set aside the school provided graphing calculator. Give me graph paper, any day.
As for the articulation, that’s where my head is at, these days. Theorizing and envisioning. Still, I try to get in new snippets nearly every day to play with and explore, and discover new things. The perpetual beginner is where I find myself, albeit not without insight, not without curiosity, not without resolve.
A cool winter project would be porting your code to Python and see where philosophies collide, or not. Data structures differ, as does syntax. Is there an outline we could start with? Can we represent the processes with pseudo code that might be simpler to translate given the symbolic representation? Or has all this been done, already? It’s the web. Stuff happens, ideas overlap or occur simultaneously, and there is nothing new under the Sun.