crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в Реализация анализатора (парсера) формул времени выполнения
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
BRE Дата 11.3.2009, 23:17
 
Цитата(AntonTatu @ 11.3.2009, 21:52) *
ЗЫ: что то попробовал открыть под Visual Studio, QT проект не подцепился, ошибку при открытии выдает, под Qt Creator ом, проект открылся только все что по русски написано не читается (кракозябы), пробовал FAR ом открыть он то же кодировку не понял (win, dos), под Linux-ом написано ?

UTF8
В QtCreator: Edit -> Select encoding... -> UTF-8
AntonTatu Дата 11.3.2009, 21:52
 
Цитата(BRE @ 11.3.2009, 21:44) *
Добавил контексты.
Разбил по файлам.
Кратко документировал.
Проект в архиве.


ПАСИБА завтра буду вникать ! :)

ЗЫ: что то попробовал открыть под Visual Studio, QT проект не подцепился, ошибку при открытии выдает, под Qt Creator ом, проект открылся только все что по русски написано не читается (кракозябы), пробовал FAR ом открыть он то же кодировку не понял (win, dos), под Linux-ом написано ?
BRE Дата 11.3.2009, 21:44
  Добавил контексты.
Разбил по файлам.
Кратко документировал.
Проект в архиве.
BRE Дата 11.3.2009, 11:31
 
Цитата(AntonTatu @ 11.3.2009, 11:09) *
//Очищаем стэк перед новым расчетом
//хотя заметил что перед новым расчетом стэк всегда пуст, даже если предыдущий выход из цикла был по брэйку....,
//наверно и очищать его не нужно.... и функция лишняя... ?

Вот смотри формула:
100 200 300 400 0 / * + +

происходит ошибка: Деление на 0, в стеке:
100 200 300 400

Тут от формулы зависит.

Цитата(AntonTatu @ 11.3.2009, 11:09) *
вот это очень интересно, т.к. скорости мне все равно хочется больше... (если компилировать dll ку с массивом получается намного быстре, только компилятор таскать за собой не получится...)

С нативом даже не сравнивай, не расстраивай себя. Такой производительности не будет. ;)

Контексты набросаю чуть позже...
AntonTatu Дата 11.3.2009, 11:09
 
Цитата(BRE @ 11.3.2009, 6:12) *
Мне кажется, что логичней, если сам метод run() будет сообщать нужно ли продолжать вычисления.

Так и знал что можно было огород не городить......с флажком... :(
Цитата
Еще желательно ввести методы для очистки стека, т.к. при таком прерывании операции возможны случаи, когда в стеке останутся данные.

сделал так:
вот

void MathStack::clear()
{
   while (!m_stack.empty()){
       m_stack.pop(); //удаляем верхний элемент в стэке, который формально является последним элементом в контэйнере
     }

}

//и сюда добавил

double Formula::calc() const
{
    //Очищаем стэк перед новым расчетом
    Operation::m_stack.clear(); //хотя заметил что перед новым расчетом стэк всегда пуст, даже если предыдущий выход из цикла был по брэйку....,
                                             //наверно и очищать его не нужно.... и функция лишняя... ?

    // Выполнить все операции
    for( ListOp::ConstIterator iOp = m_ops.begin(); iOp != m_ops.end(); ++iOp ){
        (*iOp)->run();
        if (!(*iOp)->exit()) {
            break;

     //после выполнения на вершине арифметического стэка результат
     return Operation::m_stack.pop();


Если выход из цикла будет по break, то в стэке будет какой то результат, но в этом случае очищать его мне ненужно, т.к., я его в дальнейшем использую... (мне его наооборот получать нужно :) )
Цитата
Можно ввести такое понятие как контекст, в котором хранить арифметический стек, состояние (ошибка), исходные данные, локальные переменные.
Тогда мы бы избавились от статического стека и получили возможность пихать расчет формул по разным потокам.
Если будут еще вопросы задавай, мне самому интересен этот вопрос. :)

вот это очень интересно, т.к. скорости мне все равно хочется больше... (если компилировать dll ку с массивом получается намного быстре, только компилятор таскать за собой не получится...)
BRE Дата 11.3.2009, 6:12
  Мне кажется, что логичней, если сам метод run() будет сообщать нужно ли продолжать вычисления.

вот


class Operation
{
public:
    virtual bool  run() = 0;    //выполнить операцию, вернуть false - если необходимо прервать операцию
};

class VarOp : public Operation
{
public:
    VarOp( int *var  );

    bool    run();
};

class AddOp : public Operation
{
public:
    bool    run();
};

class DivOp : public Operation
{
public:
    bool    run();
};

//...............................................
void AddOp::run()
{
    int v1 = m_stack.pop();
    int v2 = m_stack.pop();
    m_stack.push( v1 + v2 );
    if (v1 >= 1) return false;

        return true;
}

// В операции деления проверяем, а не делим ли мы на 0!!!
void DivOp::run()
{
    int v1 = m_stack.pop();
        // Проверяем деление на 0!!!
        if( v1 == 0 )
                 return false;

    int v2 = m_stack.pop();
    m_stack.push( v2 / v1 );
    return true;
}

//изменил этот класс так
double Formula::calc() const
{
    // Выполнить все операции
    for( ListOp::ConstIterator iOp = m_ops.begin(); iOp != m_ops.end(); ++iOp )
        if( !(*iOp)->run() )
            break;
}


Еще желательно ввести методы для очистки стека, т.к. при таком прерывании операции возможны случаи, когда в стеке останутся данные.

Можно ввести такое понятие как контекст, в котором хранить арифметический стек, состояние (ошибка), исходные данные, локальные переменные.
Тогда мы бы избавились от статического стека и получили возможность пихать расчет формул по разным потокам.

Если будут еще вопросы задавай, мне самому интересен этот вопрос. :)
AntonTatu Дата 10.3.2009, 23:38
 
Цитата(BRE @ 10.3.2009, 20:46) *
Ну барин ты задачки задаешь. (с) :)
.............................................
.............................................
Таким образом можно наделать разных необходимых операций, ввести переменные и т.д.
Например, если у всех переменных необходимо изменять j, можно сделать такую операцию, которая это будет делать вызовом одной функции.
Думай пробуй. :)


Да у самого голова уже пухнет :(, залез в такие дебри в которых мало что понимаю
Последний вопрос связанный вот с этим , и все....
вот эта часть

void AddOp::run()
{
    int v1 = m_stack.pop();
    int v2 = m_stack.pop();
    m_stack.push( v1 + v2 );
}

double Formula::calc() const
{
    // Выполнить все операции
    for( ListOp::ConstIterator iOp = m_ops.begin(); iOp != m_ops.end(); ++iOp ){
        (*iOp)->run();
    }
    // После выполнения на вершине арифметического стека результат
    return Operation::m_stack.pop();


как сделать так что бы при сложении если на стеке ( m_stack.push( v1 + v2 );) число больше ну к примеру 100 (или любого какое нравится) остановить подсчет Formula::calc() и вывести результат ?
я сделал так....
вот


//изменил этот класс так 
class Operation
{
public:
    virtual void  run() = 0;    //выполнить операцию
    virtual bool  exit() = 0;   //добавил проверку на выход

//изменил этот класс так
class VarOp : public Operation
{
public:
    VarOp( int *var  );

    void    run();
    bool    exit();

//изменил этот класс так
class AddOp : public Operation
{
public:
    void    run();
    bool    exit();
    bool flag;

//...............................................
void AddOp::run()
{
    int v1 = m_stack.pop();
    int v2 = m_stack.pop();
    m_stack.push( v1 + v2 );
    if (v1 >= 1) flag = false;
}


bool AddOp::exit()
{
   if (flag == false)
   {
       return false;
   }else
   {
    return true;
   }
}

//изменил этот класс так
double Formula::calc() const
{
    // Выполнить все операции
    for( ListOp::ConstIterator iOp = m_ops.begin(); iOp != m_ops.end(); ++iOp ){
        (*iOp)->run();
        if (!(*iOp)->exit()) {
            break;


все работает как надо, но мне кажется что можно было както проще сделать ?
BRE Дата 10.3.2009, 20:46
 
Цитата(AntonTatu @ 10.3.2009, 12:49) *
т.е. что бы появилась возможность "сдвигать" формулу и, не перестраивая формулу заново и не генерируя новый массив ?

Ну барин ты задачки задаешь. (с) :)

Переделать операцию VarOp или сделать еще одну операцию (это набросок).
class VectorVarOp : public Oparation
{
public:
    VectorVarOp( const Vector &vec );

    void    run();
    void    setIndex( int i, int j );

private:
    Vector    &m_vector;
    int         m_i;
    int         m_j;
};

VectorVarOp::VectorVarOp( const Vector &vec )
    : m_vector( vec ), m_i( 0 ), m_j( 0 )
{
}

void VectorVarOp::run()
{
    m_stack.push( m_vector[ m_i ][ m_j ] );
}

void VectorVarOp::setIndex( int i, int j )
{
    m_i = i;
    m_j = j;
}

Таким образом можно наделать разных необходимых операций, ввести переменные и т.д.
Например, если у всех переменных необходимо изменять j, можно сделать такую операцию, которая это будет делать вызовом одной функции.
Думай пробуй. :)
SABROG Дата 10.3.2009, 20:29
 
Цитата(Litkevich Yuriy @ 10.3.2009, 20:24) *
Цитата(SABROG @ 10.3.2009, 23:21) *
Хорошо бы троллям спидтест запостить, а то не хорошо получается.
отпишись, и тестовый примерчик приложи, как я понял у тебя он уже есть

Мопед не мой я просто разместил объяву :)
Litkevich Yuriy Дата 10.3.2009, 20:24
 
Цитата(SABROG @ 10.3.2009, 23:21) *
Хорошо бы троллям спидтест запостить, а то не хорошо получается.
отпишись, и тестовый примерчик приложи, как я понял у тебя он уже есть
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 28.4.2024, 14:43