none
Вычисление математических выражений RRS feed

  • Вопрос

  • Здравствуйте, подскажите как просто вычислить значение выражения.

    Есть textBox и в нём записан пример в, котором могут быть основные математические операции(+-*/) и скобки.

    Как вычислить значение этого выражения?

Ответы

  • Или, можно просто ее скомпилировать:

    using System;
    using Microsoft.CSharp;
    using System.CodeDom.Compiler;
    using System.Reflection;
    
    namespace MyTest
    {
    
        class Program
        {
            public delegate double Calc();
    
            private static string begin = @"using System;
    namespace MyNamespace
    {
        public delegate double Calc();
        public static class LambdaCreator 
        {
            public static Calc Create()
            {
                return ()=>";
            private static string end = @";
            }
        }
    }";
            private static void Main()
            {
                string middle = Console.ReadLine();
                CSharpCodeProvider provider = new CSharpCodeProvider();
                CompilerParameters parameters = new CompilerParameters();
                parameters.GenerateInMemory = true;
                parameters.ReferencedAssemblies.Add("System.dll");
                CompilerResults results = provider.CompileAssemblyFromSource(parameters, begin + middle + end);
                var cls = results.CompiledAssembly.GetType("MyNamespace.LambdaCreator");
                var method = cls.GetMethod("Create", BindingFlags.Static | BindingFlags.Public);
                var calc = (method.Invoke(null, null) as Delegate);
                Console.WriteLine(calc.DynamicInvoke());
                Console.ReadKey();
            }
        }
    }

    Вот так это работает:

    Отвечающий

Все ответы

  • "Просто" вряд ли. Необходимо выполнить разбор строки: выделить операции и операнды (например, с помощью регулярных выражений), затем преобразовать значения операндов из текстового представления в числовое, вычислить выражение в соответствии с приоритетом операций.

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

  • Или, можно просто ее скомпилировать:

    using System;
    using Microsoft.CSharp;
    using System.CodeDom.Compiler;
    using System.Reflection;
    
    namespace MyTest
    {
    
        class Program
        {
            public delegate double Calc();
    
            private static string begin = @"using System;
    namespace MyNamespace
    {
        public delegate double Calc();
        public static class LambdaCreator 
        {
            public static Calc Create()
            {
                return ()=>";
            private static string end = @";
            }
        }
    }";
            private static void Main()
            {
                string middle = Console.ReadLine();
                CSharpCodeProvider provider = new CSharpCodeProvider();
                CompilerParameters parameters = new CompilerParameters();
                parameters.GenerateInMemory = true;
                parameters.ReferencedAssemblies.Add("System.dll");
                CompilerResults results = provider.CompileAssemblyFromSource(parameters, begin + middle + end);
                var cls = results.CompiledAssembly.GetType("MyNamespace.LambdaCreator");
                var method = cls.GetMethod("Create", BindingFlags.Static | BindingFlags.Public);
                var calc = (method.Invoke(null, null) as Delegate);
                Console.WriteLine(calc.DynamicInvoke());
                Console.ReadKey();
            }
        }
    }

    Вот так это работает:

    Отвечающий
  • Т.е. вы хотите что-то вроде этого?
  • Или, можно просто ее скомпилировать:

    Алексей так и не понял зачем вы в начале создали делегат Calc?

    Перевел код на VB и попутно разбирался как он работает. Выяснилось, что работает без этой строчки. Вот и стало интересно. Плюс я так до конца и не понял сути делегатов, зачем они и куда )))

    UPD. А на кой там вообще делегаты? Переделал код без них и все работает. Объясните неучу, чего я лишился убрав их?


    VB.Net - WPF, WinRT, WP

    7 июня 2015 г. 10:57
    Отвечающий
  • У меня метод его возвращает. В принципе в данном случае можно и без него. Но если, например, необходимо передать параметры, то лучше сделать лямбду с параметром. Ну и сохранив ее в делегате, можно вызывать несколько раз передавая разные параметры.
    7 июня 2015 г. 17:13
    Отвечающий
  • 1. "... сохранив ее ( лямбду ) в делегате, можно вызывать несколько раз передавая разные параметры..."
    Это как? Желательно код!
    2. Какие операции поддерживаются?
    +,-,*,/ - это понятно, а возведение в степень, извлечение корня, логарифмы, и пр.
    3. 
    public delegate double Calc(); - эта строка в первом случае действительно не нужна,
    а в MyNamespace без этой строчки программа не работает

    • Изменено QazRdx 10 июня 2015 г. 5:37
    10 июня 2015 г. 4:44
  • Блин смотрю у вас тут целая дискуссия по созданию проги для вычисления любого выражения. Согласна, решение прикольное, но у него есть минусы: скорость - так как приходится задействовать жесткий диск, антивирус - он может придираться к вновь созданным программам, компилятор - только он проверяет корректность вычисляемого выражения и еще множество подводных камней лежит на данном пути, который с первого взгляда кажется маной небесной... Парсер выражений программный не простая штука, но много лучше и в конечном итоге оправдывает себя...
    10 июня 2015 г. 7:20
  • 1. "... сохранив ее ( лямбду ) в делегате, можно вызывать несколько раз передавая разные параметры..."
    Это как? Желательно код!

    Вот так:

    namespace MyTest
    {
    
        class Program
        {
            public delegate double Calc(double x);
    
            private static string begin = @"using System;
    namespace MyNamespace
    {
        public delegate double Calc(double x);
        public static class LambdaCreator 
        {
            public static Calc Create()
            {
                return x=>";
            private static string end = @";
            }
        }
    }";
            private static void Main()
            {
                string middle = Console.ReadLine();
                CSharpCodeProvider provider = new CSharpCodeProvider();
                CompilerParameters parameters = new CompilerParameters();
                parameters.GenerateInMemory = true;
                parameters.ReferencedAssemblies.Add("System.dll");
                CompilerResults results = provider.CompileAssemblyFromSource(parameters, begin + middle + end);
                var cls = results.CompiledAssembly.GetType("MyNamespace.LambdaCreator");
                var method = cls.GetMethod("Create", BindingFlags.Static | BindingFlags.Public);
                var calc = (method.Invoke(null, null) as Delegate);
                Console.WriteLine("Значение выражения при x = 10: " + calc.DynamicInvoke(10));
                Console.WriteLine("Значение выражения при x = 20: " + calc.DynamicInvoke(20));
                Console.ReadKey();
            }
        }
    }

    Ну а по поводу операций, можно дать синтаксис c# и пользователь будет вводить все это:

    10 июня 2015 г. 8:41
    Отвечающий
  •  Парсер выражений программный не простая штука, но много лучше и в конечном итоге оправдывает себя...
    Конечно, как человек преподававшие теорию компиляторов, я с вами полностью согласен. Но как известно, каков вопрос, таков ответ. В данном случае это решение простое и рабочее. В реальном проекте я бы так не делал...
    10 июня 2015 г. 8:43
    Отвечающий
  • Парсер выражений программный не простая штука, но много лучше и в конечном итоге оправдывает себя...
    Все завит от конкретной титуации. Я использовал решение Алексея впроге, которая установлена на 4х компьютерах. В данной ситуации минимальные трудозатраты оправдывают вероятные проблемы

    VB.Net - WPF, WinRT, WP

    10 июня 2015 г. 16:55
    Отвечающий
  • Всем спасибо!
    10 июня 2015 г. 16:59