Show me your calculator program.

After readingthis thread in the pit, I’m curious as to what a “simple command line calculator program that will do basic arithmetic(±/*^())” would look like in the various languages available today. Most respondants in that thread seemed to think that this was a trivial excercise, so I want to see some code!

I’ll start, and as I’m a sysprog on a z/OS mainframe with not very much exposure to C, C++, VB, etc., I’m going to fall back on what I know, which is REXX. This program will do exactly what is asked for.

I don’t propose this to be a contest or anything like that, but I’m genuinely interested in how this problem is solved in different languages.

My contribution:



/*=============================== Rexx ===============================*/
  true = (0 = 0)                                                        
  false = (0 = 1)                                                       
  continue? = true                                                      
  Say 'Enter Expression:'                                               
  Parse External expr                                                   
                                                                        
  Call Get_next_char                                                    
  result = Expression()                                                 
  If nextchar = '' & continue? Then                                     
    Say 'The Result is: ' result                                        
  Else                                                                  
    Say 'Syntax Error'                                                  
                                                                        
  Exit                                                                  
                                                                        
/*====================================================================*/
Get_next_char:                                                          
  nextchar = ' '                                                        
  Do Until nextchar ¬= ' ' | Length(expr) = 0                           
    Parse Var expr nextchar 2 expr                                      
  End                                                                   
                                                                        
  Return                                                                
                                                                        
/*====================================================================*/
Expression: Procedure Expose nextchar continue? expr true false         
  value = Term()                                                        
  Do Forever                                                            
    Select                                                              
      When nextchar = '+' Then                                          
        Do                                                              
          Call Get_next_char                                            
          value = value + Term()                                        
        End                                                             
      When nextchar = '-' Then                                          
        Do                                                              
          Call Get_next_char                                            
          value = value - Term()                                        
        End                                                             
      Otherwise                                                         
        Leave                                                           
    End                                                                 
  End                                                                   
                                                                        
  Return value                                                          
                                                                        
/*====================================================================*/
Term: Procedure Expose nextchar continue? expr true false               
  value = Factor()                                                      
  Do Forever                                                            
    Select                                                              
      When nextchar = '*' Then                                          
        Do                                                              
          Call Get_next_char                                            
          value = value * Factor()                                      
        End                                                             
      When nextchar = '#' Then                                          
        Do                                                              
          Call Get_next_char                                            
          value = value ** Term()                                       
        End                                                             
      When nextchar = '/' Then                                          
        Do                                                              
          Call Get_next_char                                            
          divisor = Factor()                                            
          If divisor ¬= 0 Then                                          
            value = value / divisor                                     
          Else                                                          
            Do                                                          
              Say 'Division by Zero'                                    
              Exit                                                      
            End                                                         
        End                                                             
      Otherwise                                                         
        Leave                                                           
    End                                                                 
  End                                                                    
                                                                         
  Return value                                                           
                                                                         
/*====================================================================*/ 
Factor: Procedure Expose continue? nextchar expr true false              
  value = 0                                                              
  count = 0                                                              
  decimal_point? = false                                                 
                                                                         
  If (nextchar <= 9) & (nextchar >= 0) Then                              
    Do                                                                   
      Do While (nextchar <= 9 & nextchar >= 0)                           
        value = value * 10 + nextchar                                    
        Call Get_next_char                                               
        If decimal_point? Then                                           
          count = count + 1                                              
        If nextchar = '.' Then                                           
          Do                                                             
            Call Get_next_char                                           
            decimal_point? = true                                        
          End                                                            
      End                                                                
                                                                         
      Do i = 0 By 1 While i < count                                      
        value = value / 10                                               
      End                                                                
      Return value                                                       
    End                                                                  
  Else                                                                   
    Select                                                               
      When nextchar = '-' Then                                           
        Do                                                               
          Call Get_next_char                                             
          Return -1 * Factor()                                           
        End                                                              
      When nextchar = '(' Then                                           
        Do                                                               
          Call Get_next_char                                             
                                                                         
          value = Expression()                                          
          If nextchar ¬= ')' Then                                       
            Do                                                          
              Say 'Mismatched Parentheses'                              
              Exit                                                      
            End                                                         
          Else                                                          
            Do                                                          
              Call Get_next_char                                        
              Return value                                              
            End                                                         
        End                                                             
      When nextchar = '.' Then                                          
        decimal_point? = true                                           
      Otherwise                                                         
        continue? = false                                               
    End                                                                 
                                                                        
  Return 0

Mine would look like this



#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

int main(int argc, char* argv[])
{
char  s[1];
cout << "enter what you want to do:";
cin >> s;
double a,b;
cout << "enter first number:"  ;
cin >> a;
cout << "enter second number:";
cin >> b;

if (s == '*') cout <<  "answer is :" << a*b << "Hit any key to end"; 
//same thing for the rest.
//might not be able to use == for char*. Might have to use strcmp() or something. 
getch();

return 0;
}


That’s pretty trivial. I’d probably not be able to remember all of the proper headers, or if I needed the “strcmp” call. That shouldn’t make or break you, though.



perl -e 'print eval <>'


Yeah, I’m a dick.

Technically, eval(“your expression here”), would work from the Python command line.

However, to make things a little more fun, I’ll ignore the eval command (except for converting numbers into strings):



operators = ["+","-","*","/","^"]
leftbrackets = ["(","{","["]
rightbrackets = [")","}","]"]

def tgeval(expression):
    while 1 <> 2:
        a = -1
        b = -1
        for j in range(len(expression)):
            if leftbrackets.count(expression[j:j+1]) == 1:
                a = j
            if rightbrackets.count(expression[j:j+1]) == 1:
                b = j
                break
        if a == -1 and b == -1:
            expression = str(arith(expression))
            return expression
        elif a == -1 or b == -1:
            return "Error: Mismatched Parentheses"
        else:
            expression = replace(expression,a,b+1,str(arith(expression[a+1:b])))
        

def arith(chunk):
    for k in range(len(chunk)-1):
        if operators.count(chunk[k+1:k+2]) == 1:
            if operators.count(chunk[k+2:len(chunk)]) == 1:
                arith(chunk[k+2:len(chunk)])
            else:
                if chunk[k+1:k+2] == "+":
                    return eval(chunk[0:k+1])*1.0 + eval(chunk[k+2:len(chunk)])*1.0
                if chunk[k+1:k+2] == "-":
                    return eval(chunk[0:k+1])*1.0 - eval(chunk[k+2:len(chunk)])*1.0
                if chunk[k+1:k+2] == "*":
                    return eval(chunk[0:k+1])*1.0 * eval(chunk[k+2:len(chunk)])*1.0
                if chunk[k+1:k+2] == "/":
                    if eval(chunk[k+2:len(chunk)]) == 0:
                        return "Error: Divide by Zero"
                    return eval(chunk[0:k+1])*1.0 / eval(chunk[k+2:len(chunk)])*1.0
                if chunk[k+1:k+2] == "^":
                    return (eval(chunk[0:k+1])*1.0) ** (eval(chunk[k+2:len(chunk)])*1.0)

def replace(rstring,rstart,rend,newchunk):
    rstring = rstring[0:rstart] + newchunk + rstring[rend:len(rstring)]
    return rstring


Expressions are then evaluated from the command line using tgeval(your expression here)

It’s not 100%, since it ignores the order of operations. An expression like 7*2+3 would be evaluated incorrectly as 35, instead of 17. This is because it takes an ambiguous string of commands like a?b?c?d?e and simply turns it into (a?(b?(c?(d?e)))). Additionally, it doesn’t check for people entering non-mathematical stuff. I could get it to work properly, but I need to get to sleep!

Something I initially overlooked was the potential ambiguity between “–” where it denotes a negative number, and “–” as an operator.

That took just over an hour, and that’s with the ability to test the whole time. There are likely to be errors in there. I’ve done things that would probably amuse, and perhaps even scare a real programmer. But I do this as a hobby - I’m not pretending I can program, and I’m definitely not applying for software engineering jobs!