none
(Sumber: milist DOTNET) Algoritma Membaca Rumus

    Question

  •  

    Mohon pencerahan,

    asumsikan saya punya rumus  seperti ini "(a+b)-c".

    nah dari contoh diatas tersebut, "a", "b" dan "c" nanti akan diganti dengan angka yang akan dinput oleh user.

    yang menjadi pertanyaan saya adalah, bagaimana caranya membaca suatu rumus dalam notasi teks menjadi suatu rumus yang bisa dihitung/dijalankan ? adakah algoritmanya ? (mungkin mirip seperti excel)

    Terima kasih sebelumnya


    Agnes Sannie [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 22, 2012 3:16 AM
    Moderator

Answers

All replies

  •  

    Halo,

    Coba baca tutorial dari Yohanes Nugroho:

    http://yohan.es/compiler/tutorial1/

    Di chapter 1 Dragon Book karangan Alfred Aho, Jeffrey Ullman juga langsung bahas bikin beginian tanpa banyak teori.

    Dijawab oleh:

    Dicky Arinal


    Agnes Sannie [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 22, 2012 3:16 AM
    Moderator
  •  

    terima kasih atas pencerahannya,

    saya menemukan apa yang saya cari di

    http://www.codeproject.com/Articles/23061/MathParser-Math-Formula-Parser

    terima kasih banyak.


    Agnes Sannie [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 22, 2012 3:17 AM
    Moderator
  •  

    Sekedar pembelajaran, saya iseng-iseng bikin karena kurang kerjaan, mungkin masih beberapa yang buggy karena baru dibikin :) Algoritma sangat sederhana, bisa dipelajari pada chapter 1 buku Dragon book, top down parser dengan rekursif.

    Cara penggunaan:

    var parser = new ArithmeticParser("3 + x + y")

        .SetVariable("x", 2)

        .SetVariable("y", 3);

    parser.Parse(); // will return 10

    Penggunaan lain bisa menggunakan lambda untuk menambah fungsi baru, ingat penambahan fungsi baru cuma bisa dilakukan at compile time!

    parser = new ArithmeticParser("pow(3 + 1, sin(3))")

        .SetFunction("pow", param => Math.Pow(param[0], param[1]))

        .SetFunction("sin", param => Math.Sin(param[0]));

    Saat parser di-instantiate, semua variabel akan dikenali dan di set menjadi nol, sehingga code di bawah menjadi mungkin:

    var parser = new ArithmeticExpressionParser(Console.ReadLine()); // input ekspresi dari keyboard foreach (var variable in parser.GetVariablesName()) {

        Console.Write("Set variable for {0} : ", variable);

        parser.SetVariable(variable, double.Parse(Console.ReadLine()));

    }

    Console.WriteLine(parser.Parse());

    Just copy paste this to your Console program.

    namespace Konsole

    {

        public class ParserMain

        {

            private static void Main()

            {

                var porsar = new ArithmeticExpressionParser("x + y")

                    .SetVariable("x", 5)

                    .SetVariable("y", 3);

                Console.WriteLine(porsar.Parse());

                Console.Write("Enter expression: ");

                var parser = new ArithmeticExpressionParser(Console.ReadLine())

                    .SetFunction("pow", param => Math.Pow(param[0], param[1]))

                    .SetFunction("sin", param => Math.Sin(param[0]));

                foreach (var symbol in parser.GetVariablesName())

                {

                    Console.Write("Set variable for {0} : ", symbol);

                    parser.SetVariable(symbol, double.Parse(Console.ReadLine()));

                }

                Console.WriteLine(parser.Parse());

            }

        }

        public class ArithmeticExpressionParser

        {

            private IEnumerator<char> _enumerator;

            private string _expression;

            private bool _notFinished;

            private readonly Dictionary<string, double> _variables;

            private readonly Dictionary<string, Func<double[], double>> _functions;

            public string Expression

            {

                get { return _expression; }

                set

                {

                    _expression = value.Trim();

                    _variables.Clear();

                    Parse(); // create variables into symbols dictionary

                }

            }

            public char Current

            {

                get { return _enumerator.Current; }

            }

            public ArithmeticExpressionParser(string expression)

            {

                _variables = new Dictionary<string, double>();

                _functions = new Dictionary<string, Func<double[], double>>();

                Expression = expression;

            }

            public ArithmeticExpressionParser SetVariable(string variableName, double value)

            {

                _variables[variableName] = value;

                return this;

            }

            public ArithmeticExpressionParser SetFunction(string functionName, Func<double[], double> function)

            {

                _functions[functionName] = function;

                return this;

            }

            public IEnumerable<string> GetVariablesName()

            {

                return _variables.Keys.ToArray();

            }

            public IEnumerable<string> GetFunctionsName()

            {

                return _functions.Keys.ToArray();

            }

            public double Parse()

            {

                _notFinished = true;

                _enumerator = Expression.GetEnumerator();

                _enumerator.MoveNext();

                return ParseExpression();

            }

            private double ParseExpression()

            {

                double result = ParseTerm();

                bool done = false;

                while (_notFinished && !done)

                {

                    switch (Current)

                    {

                        case '+':

                            MatchCurrentThenNext('+');

                            result += ParseTerm();

                            break;

                        case '-':

                            MatchCurrentThenNext('-');

                            result -= ParseTerm();

                            break;

                        default:

                            done = true;

                            break;

                    }

                }

                return result;

            }

            private double ParseTerm()

            {

                double result = ParseFactor();

                bool done = false;

                while (_notFinished && !done)

                {

                    switch (Current)

                    {

                        case '*':

                            MatchCurrentThenNext('*');

                            result *= ParseFactor();

                            break;

                        case '/':

                            MatchCurrentThenNext('/');

                            result /= ParseFactor();

                            break;

                        default:

                            done = true;

                            break;

                    }

                }

                return result;

            }

            private double ParseFactor()

            {

                double result;

                if (char.IsDigit(Current))

                    result = ParseNumber();

                else if (Current == '-')

                {

                    MatchCurrentThenNext('-');

                    result = -ParseFactor();

                }

                else if (Current == '(')

                {

                    MatchCurrentThenNext('(');

                    result = ParseExpression();

                    MatchCurrentThenNext(')');

                }

                else if (char.IsLetter(Current))

                    result = ParseSymbol();

                else

                    throw new InvalidOperationException("factor syntax error");

                return result;

            }

            private double ParseSymbol()

            {

                string name = "";

                while (_notFinished && (char.IsDigit(Current) ||

    char.IsLetter(Current)))

                {

                    name += Current;

                    MatchCurrentThenNext();

                }

                double result = _notFinished && Current == '(' ?

    ProcessFunction(name) : ProcessVariable(name);

                if (_notFinished && char.IsSeparator(Current))

                    NextNonWhiteSpace();

                return result;

            }

            private double ProcessVariable(string name)

            {

                // second condition is intended for creating variables when first parsed

                return _variables.ContainsKey(name) ? _variables[name] :

    (_variables[name] = 0);

            }

            private double ProcessFunction(string name)

            {

                double result = 0;

                MatchCurrentThenNext('(');

                var parameters = new List<double>();

                while (Current != ')')

                {

                    parameters.Add(ParseExpression());

                    if (Current == ',')

                    {

                        MatchCurrentThenNext(',');

                        parameters.Add(ParseExpression());

                    }

                }

                if ( _functions.ContainsKey(name) )

                    result = _functions[name](parameters.ToArray());

                else

                    _functions.Add(name, null);

                MatchCurrentThenNext(')');

                return result;

            }

            private double ParseNumber()

            {

                double result = 0.0;

                double restFactor = 0.1;

                bool shouldFindRest = false;

                do

                {

                    if (Current == '.')

                    {

                        MatchCurrentThenNext('.');

                        shouldFindRest = true;

                    }

                    else if (shouldFindRest)

                    {

                        result += CharToDouble(Current) * restFactor;

                        restFactor *= 0.1;

                        MatchCurrentThenNext();

                    }

                    else

                    {

                        result *= 10.0;

                        result += CharToDouble(Current);

                        MatchCurrentThenNext();

                    }

                } while (_notFinished && (char.IsDigit(Current) || Current == '.'));

                return result;

            }

            private void MatchCurrentThenNext(char currentChar)

            {

                if (Current == currentChar)

                    NextNonWhiteSpace();

                else

                    throw new InvalidOperationException("Syntax error");

            }

            private void MatchCurrentThenNext()

            {

                MatchCurrentThenNext(Current);

            }

            private void NextNonWhiteSpace()

            {

                bool hasNext;

                while ((hasNext = _enumerator.MoveNext()) &&

    char.IsWhiteSpace(Current)) { }

                _notFinished = hasNext;

            }

            private double CharToDouble(char numberChar)

            {

                return numberChar - '0';

            }

        }

    }

    Dijawab oleh:

    Dicky Arinal


    Agnes Sannie [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, February 22, 2012 3:19 AM
    Moderator