Модераторы: diadiavova, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как вычислить выражение записанное в виде строки, строку - в арифметическое выражение 
V
    Опции темы
lvvas
Дата 1.4.2009, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.4.2009

Репутация: нет
Всего: нет



Числовой переменной можно присвоить значение арифметического выражения и результат вывести в текстовую строку
например:

Dim a As Decimal = (2 + 2) * 3
TextBox1.Text = a

А как сделать так, чтобы строковые данные воспринимались как арифметическое выражение?
То есть, например, типа так:

TextBox1.Text = "(2 + 2) * 3"
Dim a As Decimal =TextBox1.Text
TextBox1.Text = a

(но не работает и не должно, поскольку переменной типа Decimal пытаюсь присвоить строковое выражение)

В общем, нужно чтобы вычислялось выражение, введённое в текстовую строку... 
Есть ли простые способы решения этой проблемы?





PM MAIL   Вверх
diadiavova
Дата 1.4.2009, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(lvvas @  1.4.2009,  15:47 Найти цитируемый пост)
Есть ли простые способы решения этой проблемы?

Можно использовать готовые библиотеки, коих вполне достаточно даже среди оупенсорс-проектов
Например:
http://flee.codeplex.com/
 или используй динамическую компиляцию. Например Так
http://www.interface.ru/home.asp?artId=4703.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
-Mikle-
Дата 1.4.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 3
Всего: 59



Цитата(diadiavova @  1.4.2009,  18:59 Найти цитируемый пост)
или используй динамическую компиляцию

Когда-то я таким способом делал. Имей ввиду, штука весьма противная, так как компиляция - процесс не быстрый уже по своему определению. Время выполнения составляло 100 мс, то есть 10 вычислений в секунду. Сложность выражения пркактически не влияла на скорость.

Вот код на C#, если будет не понятно, попроси, переведем на VB.NET
Код

    public static class Evaluator
    {
        static CodeDomProvider csharpProvider;
        static CompilerParameters compilerParameters;
        static string baseCodeBegin;
        static string baseCodeEnd;

        static Evaluator()
        {
            compilerParameters = new CompilerParameters();
            compilerParameters.GenerateInMemory = true;
            compilerParameters.ReferencedAssemblies.Add("mscorlib.dll");

            csharpProvider = CodeDomProvider.CreateProvider("c#");

            baseCodeBegin = "using System; public static class DynamicExpression { public static double Eval() { return \r\n";
            baseCodeEnd = "\r\n; } }";
        }

        public static double Evaluate(string expression)
        {
            CompilerResults result = csharpProvider.CompileAssemblyFromSource(compilerParameters, string.Concat(baseCodeBegin, expression, baseCodeEnd));
            if (result.Errors.HasErrors)
            {
                StringBuilder strB = new StringBuilder();
                foreach (CompilerError error in result.Errors)
                    strB.AppendLine(string.Format("[pos: {0}] - {1}", error.Column, error.ErrorText));
                throw new ArgumentException("Ошибка в выражении:\r\n" + strB.ToString(), "expression");
            }

            return (double)result.CompiledAssembly.GetType("DynamicExpression").GetMethod("Eval").Invoke(null, null);
        }
    }


Использование простое:
Код

            try
            {
                double res = Evaluator.Evaluate("2 + 2");
                MessageBox.Show(this, "Eval: " + res);
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }



--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
diadiavova
Дата 1.4.2009, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Чтобы было быстро надо собственный парсер писать, а такое решение вряд ли можно назвать простым.
Кроме того: если надо производить много вычислений, то можно их все оформить в одну сборку и скомпилировать 1 раз. Хотя, в любом случае, я не агитирую за этот способ. smile 
ЗЫ
В моей второй ссылке пример на васике, сам не проверял, но, как мне кажется я эту статью видел несколько лет назад на другом сайте, если это она, то всё работает.

ЗЫ
Можно использовать генератор парсеров, но тоже к простым этот способ не относится, тк грамматику прийдётся описывать.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
source777
Дата 1.4.2009, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1878
Регистрация: 12.3.2007

Репутация: нет
Всего: 56



Цитата(diadiavova @  1.4.2009,  17:23 Найти цитируемый пост)
Чтобы было быстро надо собственный парсер писать, а такое решение вряд ли можно назвать простым.
Зато можно назвать наиболее адекватным, т.к. строка может содержать функции, которых попросту нет в .NET, а если речь идёт исключительно о +-*/, то написать такой парсер будет самому даже быстрее, чем разобраться с CodeDomProvider.



--------------------
Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте
PM MAIL   Вверх
diadiavova
Дата 1.4.2009, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Вопрос был о простом способе. А большинство операций, даже если их нет в Net, то можно добавить, описав свои функции. Другое дело, если речь идёт о каком-нибудь очень специфическом синтаксисе, тогда конечно, стандартные компиляторы тут не помогут.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
source777
Дата 1.4.2009, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1878
Регистрация: 12.3.2007

Репутация: нет
Всего: 56



Цитата(diadiavova @  1.4.2009,  18:12 Найти цитируемый пост)
Вопрос был о простом способе. А большинство операций, даже если их нет в Net, то можно добавить, описав свои функции. 
В .NET, славбогу, нет глобальных функций, но заставлять пользователя твоего приложения писать System.Math.Sqrt вместо sqrt, System.Math.Power вместо ^ и т.д. и т.п, мягко говоря, негуманно.
 А простота к-л способа сильно зависит от того с какой целью понадобилось считать выражение в строке, зачастую динамическая компиляция далеко не самое простое решение данной задачи.



--------------------
Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте
PM MAIL   Вверх
diadiavova
Дата 1.4.2009, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Объясню, как выполняется то, о чём я написал. 
Для выполнения операции текст фактически вставляется в тело кода сборки. То есть: для того, чтобы вычислить строку 2+2*2 надо написать что-то в этом роде
Код

using System;
namespace ns
{
     public class MyClass
      {
           int GetValue()
            {
                   return 2+2*2;
             }
       }
}


Такой код компилится, далее создаётся экземпляр класса MyClass и у него вызывается метод GetValue.
Если тебе надо добавить пару-тройку функций, то просто запихни их в этот класс и дело в шляпе.

Что до выражения 3^2 ,то это синтаксис бейсика и если использовать его компилятор и формировать код на нём же, то всё будет нормуль.



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
diadiavova
Дата 1.4.2009, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Выкладываю пример. Здесь можно выполнять операции в соответствии с синтаксисомвасика(включая степени), так же можно использовать все функции класса Math напрямую (то есть не Sysytem.Math.Sin, а просто Sin или sin), кроме того: я добавил свою функцию Factorial, которую тоже можно использовать в выражениях.

Присоединённый файл ( Кол-во скачиваний: 35 )
Присоединённый файл  Calculate.rar 67,35 Kb


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
lvvas
Дата 2.4.2009, 07:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.4.2009

Репутация: нет
Всего: нет



ОГРОМНЕЙШЕЕ всем спасибо. Сижу, разбираюсь...
PM MAIL   Вверх
source777
Дата 2.4.2009, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1878
Регистрация: 12.3.2007

Репутация: нет
Всего: 56



Цитата(diadiavova @  1.4.2009,  21:42 Найти цитируемый пост)
то есть не Sysytem.Math.Sin, а просто Sin или sin
И бейсик всё это проглотит? ужос какой...

Цитата(diadiavova @  1.4.2009,  21:42 Найти цитируемый пост)
кроме того: я добавил свою функцию Factorial, которую тоже можно использовать в выражениях. 
Ну вот чему ты детей учишь? Если уж решил похвастаться, что понятие "рекурсия" тебе знакомо, то сделал бы её хотя бы хвостовой...




--------------------
Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте
PM MAIL   Вверх
diadiavova
Дата 2.4.2009, 15:28 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(source777 @  2.4.2009,  15:20 Найти цитируемый пост)
И бейсик всё это проглотит? ужос какой

Дело не в бейсике. Просто код посмотри, обрати внимание на инструкцию импорта(using по вашему smile ). А о том, что лучше регистрозависимые языки или нет можно, конечно поспорить, только это тема для другой категории.
Цитата(source777 @  2.4.2009,  15:20 Найти цитируемый пост)
Ну вот чему ты детей учишь? 

Не знал, что ты ребёнок...извини smile 
Цитата(source777 @  2.4.2009,  15:20 Найти цитируемый пост)
Если уж решил похвастаться, что понятие "рекурсия" тебе знакомо, то сделал бы её хотя бы хвостовой...

Какая рекурсия, ты вообще о чём? smile 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
-Mikle-
Дата 2.4.2009, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 3
Всего: 59



Цитата(source777 @  2.4.2009,  18:20 Найти цитируемый пост)
И бейсик всё это проглотит? ужос какой...

и не только это  smile , еще и это:
Код

            Dim calc = res.CompiledAssembly.CreateInstance("Ns.ExprCalc")
            msg = calc.GetValue().ToString



--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
source777
Дата 2.4.2009, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1878
Регистрация: 12.3.2007

Репутация: нет
Всего: 56



Цитата(diadiavova @  2.4.2009,  15:28 Найти цитируемый пост)
Дело не в бейсике. Просто код посмотри

Я посмотрел, потому и говорю, что ужос полный. И тут дело именно в бейсике!

Цитата(diadiavova @  2.4.2009,  15:28 Найти цитируемый пост)
Не знал, что ты ребёнок...извини smile 
Я не про себя, а про lvvas и ему подобных, они ведь могут твой код воспринять всерьёз и не понять злобной шутки:
Код

    Function Factorial(ByVal n As UInteger) As Integer
        If n = 0 OrElse n = 1 Then
            Return 1
        End If
        Return n * Factorial(n - 1)
    End Function






Это сообщение отредактировал(а) source777 - 2.4.2009, 20:28


--------------------
Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте
PM MAIL   Вверх
diadiavova
Дата 2.4.2009, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 8
Всего: 142



Цитата(source777 @  2.4.2009,  20:26 Найти цитируемый пост)
Я не про себя, а про lvvas и ему подобных, они ведь могут твой код воспринять всерьёз и не понять злобной шутки:

Эта "злобная шутка" была всего лишь иллюстрацией вот этого
Цитата(diadiavova @  1.4.2009,  18:12 Найти цитируемый пост)
А большинство операций, даже если их нет в Net, то можно добавить, описав свои функции.

и адресована была лично тебе. И честно говоря мне и в голову не пришло, что кто-то может меня заподозрить в том, что я пытаюсь кого бы то ни было учить вычислять факториал(речь, как бы не нём была). 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума VB .NET
diadiavova
  • Прежде чем задать вопрос, воспользуйтесь поиском: возможно Ваш вопрос уже обсуждался и на него был получен ответ.
  • Если такой же вопрос не найден, не стоит задавать свой вопрос в любую тему, создайте новую.
  • Заголовок темы должен отображать ее суть.
  • Содержание поста должно описывать проблему понятно, но в то же время, по возможности, лаконично. Сначала следует описать суть вопроса, потом можно привести пример кода, не вынуждайте других участников угадывать в чем Ваша проблема - телепатов здесь нет.
  • Будьте взаимно вежливы и дружелюбны.
  • При оформлении сообщений используйте форматирование, примеры кода заключайте в теги [CODE=vbnet][/CODE].
  • Также ознакомьтесь с общими правилами, действующими на всем форуме.
  • Если вопрос решен, не забывайте помечать тему решенной(вверху темы есть ссылка). Кроме того, если Вы хотите отблагодарить участников, оказавших помощь в решении, можно повысить им репутацию, в случае, если у Вас менее 100 сообщений в форуме и функция изменения репутации Вам недоступна, можете написать сюда.
  • Общие вопросы по программированию на платформе .NET обсуждаются здесь.
  • Литература по VB .NET обсуждается здесь.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, diadiavova.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | VB .NET | Следующая тема »


 




[ Время генерации скрипта: 0.1658 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.