Skip to main content

Simple arithmetic expression evaluator in Python

Taking user input for two variables, an arithmetic operator and computing the results is very basic. This article projects a fresh look at extending the simple calculator by evaluating complex arithmetic expressions input by the user while also providing a mechanism to include the last computed value in a follow-up expression. All of these in only a few lines of code, by exploiting the Python's eval function.

Disclaimer: All the source code provided in this article was tested only on Python version 3.12. If the code is being tested on a different Python version, it may or may not work as intended.

Python's eval function is used to evaluate valid Python statement(s). To extend the basic calculator, the user input arithmetic expression can be evaluated using the eval function, store and display the results. To write such an evaluator, the following are added,

  • a simple command line interpreter in a loop
  • a small command parser
  • a set of commands apart from the expressions
  • a parser for validating the expressions
  • an evaluator to store and display the results of the expression


Let's start with the command line interpreter, the function of such an interpreter is to take input from the user an arithmetic expression or a command, evaluate and display back the results. While starting the program, a small help will be shown to the user, and it drops to a command line interpreter, waiting for the user to input a command or expression. Once the user types in the input, the interpreter then offloads the parsing and execution to a different method. The start method and the command loop are coded as follows,

def expr_loop():
    print("Execute arithmetic expressions")
    print("Hint: Use '$' to substitute the last result")
    print("Examples: 3 + 4 will yield 7, followed by $ + 8 will yield 15")
    print("Type 'q' or 'quit' to exit the interpreter")

    while True:
        cmd = input("> ")
        handle_cmd(cmd)


expr_loop()

The command parser is fairly simple, there only command it needs to parse it whether to quit the command line interpreter. It also takes care of empty command (no-op). After validating the input expression, it will hand off the expression to the evaluator for the results. The simple command parser looks like,
def handle_cmd(cmd):
    if cmd is None or cmd == "":
        return
    
    cmd = cmd.strip()
    if cmd.lower() in ["q", "quit"]:
        exit(0)
    
    if not is_valid_expr(cmd):
        print("Invalid arithmetic expression")
        return
    
    evaluate(cmd)

To avoid executing Python statements input by the user, the expression needs to be validated to only have a subset of characters and numbers present in it. The list includes the following,
  • all digits 0 to 9
  • white spaces
  • arithmetic operators (including modulo)
  • open and close brackets (for forcing precedence)
  • dollar ($) sign (used as a substitute for the result from the last operation)
def is_valid_expr(expr):
    for c in expr:
        if not (c.isnumeric() or c.isspace() or c in ['.', '+', '-', '%', '*', '/', '$', ')', '(']):
            return False
    return True

Finally, the evaluator method which does the computation of the expression. The first step is to substitute for the dollar ($) symbol with the last computation result. A global variable is used which hold the value from the most recent computation. It gets overwritten with every new successful evaluation of a command. While using the eval function, a set of exceptions could be thrown. These exceptions are caught and handled accordingly as shown.
g_last_result = 0


def evaluate(expr):
    try:
        global g_last_result
        expr = expr.replace('$', "g_last_result")
        g_last_result = eval(expr)
        print(g_last_result)
    except SyntaxError:
        print("Invalid syntax for the arithmetic expression")
    except NameError:
        print("Invalid arithmetic expression")

The below is the invocation result of a session which covers all the positive and negative test cases.
$> python expr.py
Execute arithmetic expressions
Hint: Use '$' to substitute the last result
Examples: 3 + 4 will yield 7, followed by $ + 8 will yield 15
Type 'q' or 'quit' to exit the interpreter
>
> 3 + 9 + 12
24
> $ + 6
30
> $ * 5
150
> $
150
> $1
Invalid arithmetic expression
> (1+)
Invalid syntax for the arithmetic expression
> print()
Invalid arithmetic expression
> $_1
Invalid arithmetic expression
> (2.5 * 4.2) + (8.1 * 7.9)
74.49000000000001
> $ + 2
76.49000000000001
> q

Thanks for reading, please leave your suggestions, comments or queries in the comment section.

Comments

Popular posts from this blog

BMI Calculator using Python and Tkinter

Body Mass Index can be calculated using a simple formula kg/m 2 , where the weight is represented in kilograms (kg) and the height is represented in metres (m). The article presents code to create a simple GUI to calculate BMI based on user input values. The GUI is implemented using tkinter and tkinter.ttk libraries in Python language.

Using hilite.me API in Python

hilite.me is a light weight website made by Alexander Kojevnikov , used to format source code from various programming languages into formatted HTML snippets which can be added to blogs, articles, and other web pages as needed. I personally use the API to format the source code snippets in this blog, and it has greatly reduced the time taken to complete an article, much thanks to the creator. In this article, an automated way of using the hilite.me API through Python and a simple HTML document is created with formatted code snippets.

Tic-tac-toe game using Python and tkinter

Tic-tac-toe is a popular two player game where each player tries to occupy an empty slot in a 3x3 board until one of them wins or the entire board is filled without any winner. The winner has to occupy three continuous cells in any direction, including the two diagonals. In this article, a version of the tic-tac-toe game is coded using Python and tkinter library.