[Tutor] python arthematics

Francesco Loffredo fal at libero.it
Fri Mar 23 12:52:33 CET 2012



Sukhpreet Sdhu wrote:
> i want to write a program that reads simple arithematic epressions and calculates the result.
> for example input "1*3+2" should generate "5'" as result
I'm happy to learn somebody else took the same path that I did to learn Python!

First of all, a disclaimer: I'm NOT pretending that my program is perfect or that it cannot be improved in many ways; feel free to 
show me all my mistakes!

I tried (and I think I succeeded) to build a "school calculator" that solves any arithmetic expression the same way that we were 
asked to at school.
If you use a calculator, it just gives you the final result, but it doesn't show all the intermediate steps, and I addressed just 
that problem.
I don't want to tell you exactly how I did it, but I'll give you some hints. First, the general look of the program:

------------------------------------------------------------------------ transcript of a real session
Insert expression: {[(3+2)^2*2+5]:10}x3+1


      --- Normalizing Expression ---

from  {[(3+2)^2*2+5]:10}x3+1
     to  (((3+2)^2*2+5)/10)*3+1


             --- SOLUTION ---

(((3+2)^2*2+5)/10)*3+1 =

= ((5^2*2+5)/10)*3+1 =

= ((25*2+5)/10)*3+1 =

= ((50+5)/10)*3+1 =

= (55/10)*3+1 =

= 5.5*3+1 =

= 16.5+1 =

= 17.5 ... solved!

Press just Enter to finish, or
Insert expression:
----------------------------------------------------------------end of transcript-----------------------

As you can see, it's very close to what you want, if not exactly that.

The main loop is really trivial, it just calls repeatedly the main expression solver function. It could be changed to include the 
input prompt, to let E() process strings from any source, but for now it just does
----------------------------------------------------------
while E():
   print "Press just Enter to finish, or"
---------------------------------------------------------

E()  is the interesting function, of course. After the input prompt:

-  it calls a function that "normalizes" the input string, to allow for some symbols Python cannot use in math expressions, but 
often used by little students. For example, you could enter "2 x 2 : 4" and Python must read "2*2/4". Or you could use graphically 
different parentheses: {} or [] instead of (), or you could enter any number of spaces to make the expression more human-readable 
This normalization seems just cosmetic, but it also solves a syntactical problem with raising to a power, as I'll explain later.

- it recognizes the innermost parenthesis (this can be tricky, but you'll have to discover yourself)

- it extracts the contents of that parenthesis in a string

- it repeats calling a function that
     - extracts from the given string the highest-priority operation
     - calculates the result of that operation (!)
     - returns the string with the result substituted for the operation
- until the string just contains a number (!!)

- substitutes the number for the parenthesis in the expression

- records the simplified expression in a list

- starts over, until there are no more operations to calculate and the expression has become a single number (!!)

- prints out the list (this could be moved in the main loop with the input prompt, but again I'm too lazy for that ;-) )


I found some problems in the points with exclamation marks, and I'll give you some hints about those, too:

(!) - I use exec() to calculate the operation (after having thoroughly checked the input, so there's no security problem!), but I 
had to build special functions for division and for raising to a power. I wanted division to return an integer quotient whenever 
possible (both numbers a and b  are integer, and a%b == 0), and a float otherwise. So I wrote the divok() function. Raising to a 
power is written "a ** b" in Python, but my simple parser cannot tell this from a double multiplication symbol, a syntax error. 
That's why I used ^ as a power symbol, and I also changed ** into ^ in my normalization routine to allow for the correct syntax. 
Python, of course, still needs **, so I wrote the powok() function to calculate a**b when it receives a^b.

(!!) - The built-in s.isdigit() string method can be easily used to tell if a string is a number, but it fails recognizing negative 
and floating point numbers:
 >>> a = "7876787564"
 >>> a.isdigit()
True
 >>> a = "7876787.564"
 >>> a.isdigit()
False
 >>> a = "-7876"
 >>> a.isdigit()
False
That's why I wrote younumber() that returns True in the three above cases, and behaves like isdigit() otherwise.

Hope this can be a good starting point for your project.

Francesco



-----
Nessun virus nel messaggio.
Controllato da AVG - www.avg.com
Versione: 2012.0.1913 / Database dei virus: 2114/4886 -  Data di rilascio: 22/03/2012
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20120323/ce86f27e/attachment.html>


More information about the Tutor mailing list