Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "switch" vs "if/else", выбор? 
V
    Опции темы
mes
Дата 25.4.2008, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(SABROG @  25.4.2008,  10:45 Найти цитируемый пост)
И до сих пор меня терзают смутные сомнения, все время задаю себе вопрос: "На машинном уровне это jmp/loop + dec eax + cmp eax,N. Т.е. 3 долгих операции вместо одного jmp'a... Нафига мне оно надо было ? Из-за шаблонного мышления! 


1. Никогда не думай, что ты лучше компилятора знаешь какие машинные комманды нужны - если все же лучше то пиши на асме
2. выход из "goto" все равно будет по проверке значения - так что от проверки ты не избавишься
3.  в твоем примере  воoбше не понятен смысл - но скорей всего ты неправильную конструкцию подобрал раз тебя терзают сомнения ))

Добавлено @ 11:05
Цитата(MAKCim @  25.4.2008,  10:16 Найти цитируемый пост)
в каждом из stateX state изменяется по определенному алгоритму
перепишите ка этот пример без goto   
число переходов недетерминировано (т. е мы не знаем сколько раз будет выполняться goto *jumps[state])

Так ?
Код

namespace A
{
void do_state (size_t index);

void state1 () { int x=2; do_state (x); };
void state2 () { int x=3; do_state (x); };
void state3 () {  };

void do_state (size_t index)
{
     static   void (*states[3])() = { state1 , state2, state3 };
     states[index]();
};
};


Это сообщение отредактировал(а) mes - 25.4.2008, 11:09


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 25.4.2008, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Цитата(mes @ 25.4.2008,  10:52)
Цитата(SABROG @  25.4.2008,  10:45 Найти цитируемый пост)
И до сих пор меня терзают смутные сомнения, все время задаю себе вопрос: "На машинном уровне это jmp/loop + dec eax + cmp eax,N. Т.е. 3 долгих операции вместо одного jmp'a... Нафига мне оно надо было ? Из-за шаблонного мышления! 


1. Никогда не думай, что ты лучше компилятора знаешь какие машинные комманды нужны - если все же лучше то пиши на асме
2. выход из "goto" все равно будет по проверке значения - так что от проверки ты не избавишься
3.  в твоем примере  воoбше не понятен смысл - но скорей всего ты неправильную конструкцию подобрал раз тебя терзают сомнения ))

Попробую объяснить по памяти. Есть ряд чисел:

1,2,3,2,4,5,1,4

Задача: сгруппировать одинаковые цифры таким образом, чтобы получилось:

1,1
2,2
3
4,4
5

Т.е. объединить одинаковые цифры.

Внутри цикла for который выполняется 8 раз на каждую цифру приходится неизвестное количество проходов, неизвестное потому, что мы заранее не знаем какое количество совпадений будет в массиве.

Т.е. берем цифру 1 и в цикле goto проходим дальше по всему массиву начиная с 2 до тех пор пока не встретится 1 (предпоследняя).


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
bsa
Дата 25.4.2008, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(SABROG @ 25.4.2008,  10:45)
А мне из-за шаблонного мышления пришлось отказаться от такого варианта:

Код

for(int i=0; i < N; i++)
{
    label:
    ...
    goto label;
}


Я бы тоже отказался, заменив на:
Код
for(int i=0; i < N; i++)
{
    while(1) {
    ...
    }
}
И не потому, что у меня шаблонное мышление, а потому что это наглядней.
И вообще, я против goto ничего не имею, у меня самого есть код:
Код
static const void* ops[] = { op0, op1, ... op255};
do {
  unsigned char c;
  ...
  goto *ops[c];
  ...
  op0:
      operation0(param1, param2);  //Все operationX - встраиваемые функции (иначе тормоза дикие).
      continue;
  op1:
      operation1(param3, param4);
      continue;
...
  op255:
      operation255(paramX, paramY);
      continue;
} while(<условие>);


PM   Вверх
Mayk
Дата 25.4.2008, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

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



Цитата(MAKCim @  25.4.2008,  14:35 Найти цитируемый пост)

нет
это просто динамический конечный автомат

что нет? покажи полностью небольшой пример когда контструкцию с goto *[] нельзя свести к switch/case.

Цитата(MAKCim @  25.4.2008,  14:35 Найти цитируемый пост)

Mayk, 
в твоем коде каждая итерация влечет за собой большое число проверок условий (число растет пропорционально числу состояний)

зависит от оптимизатора компилятора. Некоторые вполне за О(1) перепрыгнут куда надо.

Добавлено через 1 минуту и 43 секунды
Цитата(SABROG @  25.4.2008,  15:09 Найти цитируемый пост)

Задача: сгруппировать одинаковые цифры таким образом, чтобы получилось:
.,,

Т.е. объединить одинаковые цифры.

причем тут goto? это  простейшя задача для std::map'а или аналоигчной контсрукции
Код

//pseudo code
while(in>>n)
 map[n]++;

foreach(entry : map)
{
 out << entry->key << "встречаеццо" << entry->value << "раз"
}




--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
SABROG
Дата 25.4.2008, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



У меня в коде используются continue и break. Я точно не могу сказать что именно произойдет в этой ситуации, если с помощью continue/break я должен управлять циклом for, а не while: 

Код

for(int i=0; i < N; i++)
{
    while(1
    {
        if()
        {
            continue; // продолжит выполняться с начала while или for ?
        }
        else
        {
            break; // прервется while или for ?
        }
    }
}


Цитата(Mayk @  25.4.2008,  11:20 Найти цитируемый пост)
причем тут goto? это  простейшя задача для std::map'а или аналоигчной контсрукции


Я логику сократил, чтобы было яснее. На самом деле там массив из неизвестного количества столбцов, если все цифры во всех столбцах совпадают со всеми цифрами в других строках, то эти строки надо объединять. При этом есть еще ряд условий, которые не позволяют объединить цифры в строках, т.к. строки имеют разные ключи. В общем тут ничем кроме как многоэтажными for'aми и if'aми не обойтись.

Код

2 | 3 | 1 2 3 4 5 6 7 8 9 10 ... n
1 | 3 | 1 2 3 4 5 6 7 8 9 10 ... n
2 | 3 | 2 3 4 5 6 7 8 9 10 11... n
2 | 3 | 1 2 3 4 5 6 7 8 9 10 ... n
3 | 4 | 5 6 7 3 4 5 6 7 3 2  ... n
2 | 3 | 1 2 3 4 5 6 7 8 9 10 ... n


Соотв строки 1, 4, 6 объединяются.

Это сообщение отредактировал(а) SABROG - 25.4.2008, 11:34


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 25.4.2008, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Код

for(int i=0; i < N; i++)
{
    while(1)
    {
        if()
        {
            continue; // продолжит выполняться с начала while
        }
        else
        {
            break; // прервется while
        }
    }
   if () break; // прервется for
  else continue; // продолжит выполняться с начала for
}



--------------------
PM MAIL WWW   Вверх
SABROG
Дата 25.4.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Ну вот в том то и дело. Если нет чего-то типа ::continue и ::break, то получается нужен goto вместо while.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Lazin
Дата 25.4.2008, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(MAKCim @  25.4.2008,  10:35 Найти цитируемый пост)
в твоем коде каждая итерация влечет за собой большое число проверок условий (число растет пропорционально числу состояний) 

иногда возможна оптимизация, при которой адреса переходов будут вычисляться сразу
PM MAIL Skype GTalk   Вверх
mes
Дата 25.4.2008, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  25.4.2008,  11:48 Найти цитируемый пост)
иногда возможна оптимизация, при которой адреса переходов будут вычисляться сразу 

 в том случае если состояние является константой на момент компиляции. 
в приведенных примерах с goto  состояние определяется в рантайме

Цитата(SABROG @  25.4.2008,  11:42 Найти цитируемый пост)
Ну вот в том то и дело. Если нет чего-то типа ::continue и ::break, то получается нужен goto вместо while. 

если тебе такое требуется, значит алгоритм выбран не подходяший для задачи,
а вообше сложные условия решаются через состояния конечным автоматом. 


Это сообщение отредактировал(а) mes - 25.4.2008, 11:57


--------------------
PM MAIL WWW   Вверх
baldina
Дата 25.4.2008, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата

Ведь он, по сути пострен на goto принципе.
 Если так рассуждать, все конструкции изменения хода выполнения в принципе построены на goto. goto - основополагающий принцип и остро отточенный инструмент. есть ситуации, когда более высокоуровневые конструкции менее кратки, удобны и понятны. но их совсем немного, как правило - наоборот.
по теме: больше 2х if/else наводят на мысль о switch. Кстати, switch может быть построен более эффективно, чем набор if: массив адресов перехода плюс всего одно сравнение и собственно переход. Т.е. фактически тот же jumps, что у MAKCim, только метки не изменяются.

Rickert, 
Цитата

Все вот говорят, что 
попробуй понять, почему так говорят. А выводы делай самостоятельно.
PM MAIL   Вверх
vinter
Дата 25.4.2008, 12:16 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



пипец вы развели, лучше пусть будет жрать больше времени CPU чем времени программиста, разбирающегося в этом коде. 
Насчет примера выше, то что написано у Майка просматривается за 3 секунды и приходит понимание. То что написано у Максима,я не понял до сих пор. goto ухудшает восприятие кода. А уж отказываться от свитча, это по моему маразм. Если у переменной много состояний то свитч, если мало то if'ы, я так считаю.


--------------------
Мой блог
PM MAIL WWW   Вверх
Lazin
Дата 25.4.2008, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(mes @  25.4.2008,  11:55 Найти цитируемый пост)
в том случае если состояние является константой на момент компиляции. 
в приведенных примерах с goto  состояние определяется в рантайме

неа, если например case-ы - целые значения идущие по порядку, то смещение может быть вычислено вместо проверки всех условий, либо смещение берется из таблицы, либо просто вычисляется.
Недаром в синтаксисе языка такие ограничения на аргумент конструкции swtch
PM MAIL Skype GTalk   Вверх
SABROG
Дата 25.4.2008, 12:23 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


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

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



Цитата(baldina @  25.4.2008,  11:58 Найти цитируемый пост)
по теме: больше 2х if/else наводят на мысль о switch.


А меня не наводит из-за ограничения в том, что значение которое сравниваешь должно быть константной:

Код

            if (!pBase->record().isNull(QLatin1String("name")))
            {
                row->name = pBase->record().value(QLatin1String("name")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("note")))
            {
                row->note = pBase->record().value(QLatin1String("note")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("sposnote")))
            {
                row->sposnote = pBase->record().value(QLatin1String("sposnote")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("spognote")))
            {
                row->spognote = pBase->record().value(QLatin1String("spognote")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("catnote")))
            {
                row->catnote = pBase->record().value(QLatin1String("catnote")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("postfix")))
            {
                row->postfix = pBase->record().value(QLatin1String("postfix")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("comission")))
            {
                row->Com = pBase->record().value(QLatin1String("comission")).toDouble();
            }
            if (!pBase->record().isNull(QLatin1String("opcomission")))
            {
                row->OpCom = pBase->record().value(QLatin1String("opcomission")).toDouble();
            }
            if (!pBase->record().isNull(QLatin1String("xmlengine")))
            {
                row->xmlEngine = pBase->record().value(QLatin1String("xmlengine")).toInt();
            }
            if (!pBase->record().isNull(QLatin1String("type")))
            {
                row->SpoType = pBase->record().value(QLatin1String("type")).toInt();
            }
            if (!pBase->record().isNull(QLatin1String("sposort")))
            {
                row->SpoSort = pBase->record().value(QLatin1String("sposort")).toInt();
            }
            if (!pBase->record().isNull(QLatin1String("tour")))
            {
                row->Tour = tour->value(pBase->record().value(QLatin1String("tour")).toUInt());
            }
            if (!pBase->record().isNull(QLatin1String("country")))
            {
                row->Country = state->value(pBase->record().value(QLatin1String("country")).toUInt());
            }
            if (!pBase->record().isNull(QLatin1String("Operator")))
            {
                row->Operator = partner->value(pBase->record().value(QLatin1String("operator")).toUInt());
            }
            if (!pBase->record().isNull(QLatin1String("Owner")))
            {
                row->Owner = partner->value(pBase->record().value(QLatin1String("owner")).toUInt());
            }
            if (!pBase->record().isNull(QLatin1String("currency")))
            {
                row->Currency = currency->value(pBase->record().value(QLatin1String("currency")).toUInt());
            }



Да и goto - got'e рознь. В ассемблере мне известны следующие механизмы для перехода по адресам:

int'ы - прерывание
retn'ы - возврат, при желании можно изменить значения в стеке, чтобы ретурны использовались вместо callов
call'ы - тут все понятно, адрес возврата пихается в стек и происходит переход
jmp'ы/ja/jz/jb и т.д. - аналогично call'у, разве что one way.
loop'ы - условный переход, где условие - значение в регистре cx/ecx.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 25.4.2008, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vinter @  25.4.2008,  12:16 Найти цитируемый пост)
пипец вы развели, лучше пусть будет жрать больше времени CPU чем времени программиста, разбирающегося в этом коде. 


Никто не советует разбазаривать время CPU, но экономить пару тактов ради того чтоб запутать код определено не стоит.

В программирование как в реале не стоит экономить время на не экономном.
Что лучше обойти большую лужу или сэкономить две секунды и пройти насквозь?
Все зависит от нескольких факторов:
1 критичность времени на данной момент
2. периметр против  глубины и "чистоты" лужи 
3. наличие подходящей обуви.
4 ...
И если все таки решились пройти сквозь лужу надо не забывать о том что она скрываетоткрытый люк - выбраться из которого далеко не просто. ))




Это сообщение отредактировал(а) mes - 25.4.2008, 12:27


--------------------
PM MAIL WWW   Вверх
mes
Дата 25.4.2008, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(SABROG @  25.4.2008,  12:23 Найти цитируемый пост)
           
           if (!pBase->record().isNull(QLatin1String("note")))
            {
                row->note = pBase->record().value(QLatin1String("note")).toString();
            }
            if (!pBase->record().isNull(QLatin1String("sposnote")))
            {
                row->sposnote = pBase->record().value(QLatin1String("sposnote")).toString();
            }...


а не проще разгрузить такое большое кол-во однотипных операций - самому же дышать легче будет.

к примеру так
Код

TBase::SetValue (string& s, const string& key_name, const string& default_value) 
{
    s = (record().isNull(QLatin1String(key_name))) ? default_value
                                                                                          : record().value(QLatin1String(key_name).toString();
}

тогда код выглядить будет примерно так
Код

          pBase->SetValue (row->name, "name", "");
          pBase->SetValue (row->note,    "note",   "");
          pBase->SetValue (row->sposnote,    "sposnote",   "");
          pBase->SetValue (row->spognote,    "spognote",   "");
          pBase->SetValue (row->catnote,    "catnote",   "");
     ....
    
            }



--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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