0

I'm new to python. I want to make a calculator and I am facing a problem right now.

Here's a simplified code I am trying to make:

from math import *
input = "(2)(3)e(sqrt(49))pi" #This is an example of equation
equation = "(2)*(3)*e*(sqrt(49))*pi" #The output

How can I add " * " between every ")(", ")e", "e(", and others based on the equation so that I can eval (equation) without having to put "*" manually, just like real life math?

I have tried to do it by making a code like this:

from math import *
input = "(2)(3)e(sqrt(49))pi"
input = input.replace(")(", ")*(")
input = input.replace(")e", ")*e")
input = input.replace("e(", "e*(")
input = input.replace(")pi", ")*pi")
#^^^I can loop this using for loop^^^
equation = input
print(eval(equation))

This definitely only works in this equation. I can loop the replacing method but that would be very inefficient. I don't want to have 49 iterations to just check if 7 different symbols need "*" between it or not.

GsWt
  • 3
  • 2
  • 1
    I do not know where your input is coming from, but isn't it possible to change the input in a way that every operand is in parenthesis including "e" and "pi"? In which case you only have to worry about the ")*(" case in the replace? – Csaba Benko Apr 08 '20 at 11:18
  • Several comments: (1) You should avoid having variable names such as `input` which are also Python function names that you will possibly be using later. (2) There is a potential danger in using `eval` against input that a user provides. See https://stackoverflow.com/questions/1832940/why-is-using-eval-a-bad-practice. (3) You really need to write a parser to handle your problem correctly so if you are doing that, you wouldn't need `eval` anyway as long as you have a set of well-defined "calculator functions and constants" such as `sqrt` and `pi`. – Booboo Apr 08 '20 at 11:25
  • @Booboo `input` is never used as a function here so there is no issue with that usage. – Andreas T Apr 08 '20 at 11:35
  • @CsabaBenko Thank you for the comment! The input I am trying to make comes from the user typing inside a tkinter entry (which I don't include to simplify the problem). I want to add the "*" whenever the user asks for the result. I need this so that the equation doesn't look messy. :) – GsWt Apr 08 '20 at 11:35
  • And if you are writing a calculator, why is a user entering `(2)(3)` more natural than his entering `2*3`? It is less natural and certainly requires more keystrokes. And my previous comments about `eval` being dangerous still applies. – Booboo Apr 08 '20 at 12:14
  • @Booboo Sry if I respond late. First, thank you so much for your suggestion. I didn't saw your previous comment previously (Maybe I'm a bit tired). I'm new to python so I'm sorry if i act unprofessional. I will try to avoid eval for my next project and i will learn about parser a bit more. Once again, thank you so much, kind Sir! – GsWt Apr 08 '20 at 14:16

1 Answers1

2

The issue you will encounter here is that "e(" should be transformed to "e*(" but "sqrt(" should stay. As comments have suggested, the best or "cleanest" solution would be to write a proper parser for your equation. You could put "calculator parser" into your favorite search engine for a quick solution, or if you are interested in over-engineering but learning a lot, you could have a look at parser generators such as ANTLr.

If, for some reason, neither of those are an option, a quick-and-dirty solution could be this:

import re

def add_multiplication_symbols(equation: str) -> str:
    constants = ['e', 'pi']
    constants_re = '|'.join(f'(?:{re.escape(c)})' for c in constants)
    equation = re.sub(r'(\))(\(|\w+)', r'\1*\2', equation)
    equation = re.sub(f'({constants_re})' + r'(\()', r'\1*\2', equation)
    return equation

Then print(add_multiplication_symbols("(2)(3)e(sqrt(49))pi")) results in (2)*(3)*e*(sqrt(49))*pi.

The function makes use of the re module (regular expressions) to group the cases for all constants together. It tries to work around the issue I described above by defining a set of constant variables (e.g. "e" and "pi") by hand.

Andreas T
  • 733
  • 7
  • 22
  • Thank you so much for your answer! I tried the dirty solution and it works. Maybe I will try to learn the cleaner way soon. Once again, thank you, it helps a lot! – GsWt Apr 08 '20 at 13:51