Calculator methods

  • In C#
  • Sunday, August 07, 2016
  • 2083 Views

Calculator Mot(Cong(Mot)) Tru Nhan Chia Mu using Stack or Tree

Use stack

Convert equation to Postfix

 

using System;
using System.Collections;

namespace BanTinIT.Calculator
{

    public class Calc : ICalc
    {
        #region Private members
        private readonly Stack stack;
        private const string plus = "+", minus = "-", multiply = "*", divide = "/", pow = "^";
        #endregion

        #region Constructor
        public Calc()
        {
            stack = new Stack();
        }
        #endregion

        #region Number Calculate methods
        public double Mot(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 1;
            string input = Mot() + operatorOptional;
            return Evaluation(input);
        }
        public double Hai(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 2;
            string input = Hai() + operatorOptional;
            return Evaluation(input);
        }
        public double Ba(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 3;
            string input = Ba() + operatorOptional;
            return Evaluation(input);
        }
        public double Bon(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 4;
            string input = Bon() + operatorOptional;
            return Evaluation(input);
        }
        public double Nam(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 5;
            string input = Nam() + operatorOptional;
            return Evaluation(input);
        }
        public double Sau(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 6;
            string input = Sau() + operatorOptional;
            return Evaluation(input);
        }
        public double Bay(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 7;
            string input = Bay() + operatorOptional;
            return Evaluation(input);
        }
        public double Tam(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 8;
            string input = Tam() + operatorOptional;
            return Evaluation(input);
        }
        public double Chin(string operatorOptional = "")
        {
            if (string.IsNullOrEmpty(operatorOptional))
                return 9;
            string input = Chin() + operatorOptional;
            return Evaluation(input);
        }

        #endregion

        #region Operator methods
        public string Cong(double number)
        {
            return string.Format("{0}{1}", plus, number);
        }

        public string Tru(double number)
        {
            return string.Format("{0}{1}", minus, number);
        }
        public string Nhan(double number)
        {
            return string.Format("{0}{1}", multiply, number);
        }
        public string Chia(double number)
        {
            return string.Format("{0}{1}", divide, number);
        }

        //public string Mu(int number)
        //{
        //    return string.Format("{0}{1}", pow, number);
        //}
        #endregion

        #region Private methods
        /// <summary>
        /// Get priority of operator
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private int Priority(string c)
        {
            if ((c == plus) || (c == minus))
                return 0;
            if ((c == multiply) || (c == divide))
                return 1;
            if (c == pow)
                return 2;
            if ((c == "Log") || (c == "Sin") || (c == "Cos") || (c == "Tan") || (c == "Exp"))
                return 3;
            return -1;
        }

        /// <summary>
        /// Check is operator + - * /
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        private bool IsOperator(string o)
        {
            if (char.IsDigit(o, 0) || o == "x")
                return false;

            if (char.IsLetter(o, 0))
                return true;
            return true;
        }
        /// <summary>
        /// Convert equation to Postfix
        /// </summary>
        /// <param name="equation"></param>
        /// <returns></returns>
        private string[] ToPostfix(string equation)
        {
            string[] arrays = new string[20];
            int l = equation.Length;
            int k = 0; int i;
            for (i = 0; i < l; i++)
            {
                var c = equation[i].ToString();
                int band = 0;
                int band3 = 0;
                //toán hạng
                int j;
                if (char.IsDigit(c, 0) || c == "x")
                {
                    j = i;
                    if (j < l)
                    {
                        while (char.IsDigit(equation, j) || equation[j].ToString() == ".")
                        {
                            arrays[k] = arrays[k] + equation[j].ToString();
                            j++;
                            band++;
                            if (j == l)
                            {
                                break;
                            }
                        }
                    }
                    if (band > 0)
                    {
                        k++;
                        j--;
                    }
                    if (c == "x")
                    {
                        arrays[k] = c;
                        k++;
                    }
                    i = j;
                }// (
                else if (c == "(")
                {
                    stack.Push(c);
                }// )
                else if (c == ")")
                {
                    while ((stack.Peek().ToString() != "("))
                    {
                        arrays[k] = stack.Pop().ToString();
                        k++;
                    }
                    stack.Pop();
                }
                //operator 
                //Add, subtract, multiply, divide
                else if (c == minus || c == plus || c == multiply || c == divide || c == "T" || c == "S" || c == "C" || c == "L" || c == "^" || c == "E")
                {
                    j = i;
                    var tmp = "";
                    while (char.IsLetter(equation, j))
                    {
                        tmp = tmp + equation[j].ToString();
                        j++;
                        band3++;
                    }
                    if (band3 > 0)
                    {
                        stack.Push(tmp);
                        j--;
                    }
                    i = j;
                    if (band3 == 0)
                    {
                        while ((stack.Count > 0) && (stack.Peek().ToString() != "(") && (Priority(stack.Peek().ToString()) >= Priority(c)))
                        {
                            arrays[k] = stack.Pop().ToString();
                            k++;
                            band3++;
                        }
                        stack.Push(c);
                    }
                }
            }
            while (stack.Count > 0)
            {
                arrays[k] = stack.Pop().ToString();
                k++;
            }

            return arrays;
        }
        /// <summary>
        /// Evaluate from string equation
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private double Evaluation(string input)
        {
            string[] arrInput = ToPostfix(input);
            return Evaluation(arrInput, 1);
        }
        /// <summary>
        /// Evaluate from string array Postfix
        /// </summary>
        /// <param name="val"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        private double Evaluation(string[] val, double x)
        {           
            // Duyệt vòng lặp trong mảng Input
            foreach (string t in val)
            {
                if (t == null)
                    break;
                var c = t;
                // Nếu gặp toán tử: Pop 2 toán hạng khỏi mảng Stack, tính toán dựa theo toán tử, và Push lại vào Stack
                if (IsOperator(c))
                {
                    // toán tử 2 ngôi
                    string operator1;
                    double op1;
                    double res;
                    if (c == plus || c == minus || c == multiply || c == divide || c == pow)
                    {
                        var operator2 = stack.Pop().ToString();
                        operator1 = stack.Pop().ToString();
                        var op2 = operator2 == "x" ? x : Convert.ToDouble(operator2);
                        op1 = operator1 == "x" ? x : Convert.ToDouble(operator1);
                        switch (c)
                        {
                            case plus:
                                res = op1 + op2;
                                stack.Push(res);
                                break;
                            case minus:
                                res = op1 - op2;
                                stack.Push(res);
                                break;
                            case multiply:
                                res = op1 * op2;
                                stack.Push(res);
                                break;
                            case divide:
                                res = op1 / op2;
                                stack.Push(res);
                                break;
                            case pow:
                                res = Math.Pow(op1, op2);
                                stack.Push(res);
                                break;                            
                        }
                    }
                    else // toán tử 1 ngôi
                    {

                        operator1 = stack.Pop().ToString();
                        op1 = operator1 == "x" ? x : Convert.ToDouble(operator1);
                        switch (c)
                        {

                            case "Tan":
                                res = Math.Tan(op1);
                                stack.Push(res);
                                break;
                            case "Cos":
                                res = Math.Cos(op1);
                                stack.Push(res);
                                break;
                            case "Sin":
                                res = Math.Sin(op1);
                                stack.Push(res);
                                break;
                            case "Log":
                                res = Math.Log(op1);
                                stack.Push(res);
                                break;
                            case "Sqrt":
                                res = Math.Sqrt(op1);
                                stack.Push(res);
                                break;
                            case "Exp":
                                res = Math.Exp(op1);
                                stack.Push(res);
                                break;                           
                        }
                    }
                }
                // Nếu gặp toán hạng: Push vào Stack
                else
                {
                    stack.Push(c);
                }
            }
            // Kết thúc vòng lặp, phần tử duy nhất trong Stack là kết quả cuối cùng
            double eval = Convert.ToDouble(stack.Pop().ToString());
            return eval;
        }
        #endregion
    }
}
Unit test

End