Simple RPN calculator

ddanbe 1 Tallied Votes 526 Views Share

The idea for this snippet came from vegaseat, who wrote a very nifty RPN calculator in Python, simulating a switch/case statement, something that Python is missing. See this code on page 19 in the projects for beginners thread on the Python software development forum. In my opinion, he did a very good job. So I posed myself a goal: write something equal in C# and, although it was tempting to use: don’t use a case statement. Here is the result. The only thing that C# seems to lack here is the use of variable parameters. One could play with different directories of course. Has anyone a better solution? Can my code be improved? Please let me know.Remarks good and bad are as always welcome. Enjoy.

using System;
using System.Collections.Generic;

// DM 14/nov/2014
namespace TestFuncDelegate
{
    class Program
    {
        static public Dictionary<string, Func<double, double, double>> dict = new Dictionary<string, Func<double, double, double>>();

        static void Main(string[] args)
        {
            InitDictionary();
            Console.WriteLine("          ++++ Simple RPN calculator ++++");
            Console.WriteLine();
            Console.WriteLine(" Approximation of pi: 355.0/113.0 = {0}", do_op("/", 355, 113));
            Console.WriteLine(" Square root of 25 = {0}", do_op("**", 25, 0.5));
            Console.WriteLine(" The addition of {0} and {1} equals {2}", 2.3, 8.18, do_op("+", 2.3, 8.18));
            Console.WriteLine(" The sine of an angle of 30° = {0}", do_op("sin", Math.PI/6, 0));
            Console.WriteLine(" The arcsine of a sine: {0}" , do_op("asin", do_op("sin", 0.7, 0), 0));
            Console.WriteLine(" The hypothenuse of a right triangle with sides 3 and 4:  {0}",do_op("hypo", 3, 4));
            Console.ReadKey();
        }

        static public void InitDictionary()
        {
            // Other way, more verbose but perhaps clearer?
            // Func<double, double, double> AddFunc = (x, y) => x + y;
            // dict.Add("+", AddFunc);

            // Shorter, let compiler worry about Func delegates.
            dict.Add("+", (x, y) => x + y);            
            dict.Add("-", (x, y) => x - y);            
            dict.Add("*", (x, y) => x * y);
            dict.Add("/", (x, y) => x / y);
            dict.Add("//", (x, y) => Math.Floor(x / y));
            dict.Add("**", (x, y) => Math.Pow(x,y));
            dict.Add("sin", (x, y) => Math.Sin(x));  // y dummy
            dict.Add("cos", (x, y) => Math.Cos(x));  // y dummy
            dict.Add("tan", (x, y) => Math.Tan(x));  // y dummy
            dict.Add("asin", (x, y) => Math.Asin(x));  // y dummy
            dict.Add("acos", (x, y) => Math.Acos(x));  // y dummy
            dict.Add("atan", (x, y) => Math.Atan(x));  // y dummy
            dict.Add("hypo", (x, y) => Math.Sqrt(x * x + y * y));  // y dummy
        }

        static public double do_op(string oper,double x, double y)
        {
            try
            {
                double result;
                Func<double, double, double> theFunc;
                dict.TryGetValue(oper, out theFunc);
                result = theFunc(x, y);
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return double.NaN;
            }                     
        }
    }
}
ddanbe 2,724 Professional Procrastinator Featured Poster

On line 44 the y is not dummy of course!
Those damn copy-pastes...

xrjf 213 Posting Whiz Premium Member

Before getting variables into play, why not consider parentheses? As a hint, a parser could look into the most inner parentheses, calculate the enclosed expression and then focus on the next more outer parentheses. In order to calculate each enclosed parentheses expression, first one could look for ^operators, then /operators and so on. I did try something similar -but without dictionaries instances- and it's not a simple task. The most confusing was that during the coding and testing, more and more obstacles appeared.

ddanbe 2,724 Professional Procrastinator Featured Poster

@xrj It was never my intention to play around with parsers here(altough it's fun!) I just wanted to try to immitate a bit in c# what vegaseat did in Python.

O, and the sentence One could play with different directories of course should read One could play with different dictionaries of course

xrjf 213 Posting Whiz Premium Member

Well, I think I see. Actually, it's none of my business to evaluate the work of
others, just to do my work, though one should not be blind, of course.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.