Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Базарная площадь
  
О разделе

Основная страница

Группы обсуждений


Тематический каталог обсуждений

Архив

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  07:26[Войти] | [Зарегистрироваться]
Обсуждение темы:
Вопросы оптимизации кода

Тема открыта по просьбе жителей Королевства и посвящена обсуждению вопросов оптимизации кода. Выставляйте свои лучшие и худшие тексты и не стесняйтесь их обсуждать. В споре рождается истина. Или, по крайней мере, оптимизация.

Количество сообщений на странице

Порядок сортировки сообщений
Новое сообщение вверху списка (сетевая хронология)
Первое сообщение вверху списка (обычная хронология)

Перейти на конкретную страницу по номеру


Всего в теме 737 сообщений

Добавить свое сообщение

Отслеживать это обсуждение


Смотрите также обсуждения:
Тестирование проекта. Отладка.
  • Подводные камни
  • Централизованная обработка ошибок
  • Бета-тестирование
  • Давайте учиться на ошибках.
  • Почему программисты допускают ошибки?
  • Автоматизированные тесты для GUI
  • О системах контроля ошибок

  • 737—688 | 687—638 | ...>>>
    Всего сообщений в теме: 737; страниц: 15; текущая страница: 1


    № 737   14-05-2012 01:53 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 736« (Санек25)
    ___________________________
    С вопросами -- на Круглый Стол
     Geo


    № 736   14-05-2012 00:48 Ответить на это сообщение Ответить на это сообщение с цитированием
    Привет всем. Есть проблемка напиал программу по обработке текстового файла. Но есть 2 проблемки.
    1. обработка файла начинается по событию botton.click. Но как форма становится не активной(напрмер я захожу в мой компьютер и т.п.) то программа сразу зависает и отказывается дальше работать.Файл с которым я работаю 37мб более 2 миллионов строк. Как этого исбежать???

    2. Очень долго исправляется файл. В нем примерно 47000 ошибок. и всеэто растягивается на часов 13... Открываю с помощью Tstinglist потом построчно делаю поиск и если нахожу ошибку то исправляю сохраняю в файл.


    № 735   24-03-2012 18:03 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 733« (Германн)
    ___________________________
    ОК, на Королевстве иногда хочется почитать не обсуждения каких-то конкретных задач, а более общих рассуждений о разных вопросах, связанных с программированием.
    Полный ответ готовлю, но сегодня уже не успею
    Да, торопиться-то особо некуда, это же не "помогите, к понедельнику курсовой сдавать надо!" ))
    Сергей О.

    Завтра, максимум послезавтра, отвечу. Точнее "продолжу обсуждение не вопроса, но темы".


    № 734   24-03-2012 00:30 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 733« (Германн)
    ___________________________
    ОК, на Королевстве иногда хочется почитать не обсуждения каких-то конкретных задач, а более общих рассуждений о разных вопросах, связанных с программированием.
    Полный ответ готовлю, но сегодня уже не успею
    Да, торопиться-то особо некуда, это же не "помогите, к понедельнику курсовой сдавать надо!" ))


    № 733   23-03-2012 18:43 Ответить на это сообщение Ответить на это сообщение с цитированием
    Прочитал.
    С очень многим соглашусь. Но не со всеми вашими утверждениями.
    Подробный ответ требует времени. Пока только скажу, что вы немного "передернули". Моё первое возражение было на ваш совет, что "по хорошему" автору следует использовать доппотоки. А вопрос о выборе асинхронного режима как предпочитаемого появился уже позже.

    P.S.
    Полный ответ готовлю, но сегодня уже не успею.


    № 732   23-03-2012 04:31 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 731« (Сергей О.)
    ___________________________
    Да, вот эти пред. 4 мои сообщения - это было продолжение разговора о COM-порте, который начался здесь:
    http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=80767


    № 731   23-03-2012 04:25 Ответить на это сообщение Ответить на это сообщение с цитированием
    Что я имею:
    -Процессор отнюдь не занят, как предполагал Alexeyslav - программа занимает около 0% процессорного времени.
    -Чтение "в штатном режиме" длится ровно столько, за сколько придут заказанное кол-во байтов в порт (пренебрегая накладными расходами).
    - Если ошибка чтения (например коммутатор не подключен к компьютеру), то функция возвратится через 200 мс. У меня например в этой задаче состояние коммутатора опрашивается раз в 1 сек. Поскольку чтение происходит в основном потоке, то в ситуации ошибок обмена (коммутатор не подключен и т.п.) примерно 200 мс из секунды программа "висит" и это заметно, например когда её перетаскиваешь по рабочему столу - небольшие скачки, но не создает реальных неудобств. Я считаю, что в нерабочем режиме это вполне допустимо. Нормальный режим программы - когда она подключена к коммутатору и обмен осуществляется нормально.
    - Код и его логика простые до неприличия.

    Не вижу причин, почему в этой ситуации я должен был бы перейти на асинхронное чтение, где вместо 1 вызова одной функции вызывать
    ReadFile, WaitCommEvent, WaitForSingleObject, читать по 1 байту 4 раза (вызывая после приема каждого байта опять функциии ожидания) и потом эти 4 байта складывать в 1 буфер.
    Повторюсь, ситуация - специфическая и конкретная, особенности я описал. Но в моей практике подавляющее число задач именно такие. В других случаях чтение вынесено в отдельный поток, но так же происходит синхронно. Но я думаю, что такого рода задач и с другими железками наверное не так уж мало.
    Я несколько раз собирался в каких-то задачах перейти на асинхронное чтение, как более идеологически правильное, как "вот если вдруг ситуация изменится и твое синхронное чтение уже не подойдет", но каждый раз в конце концов останавливался на более простом варианте, описанном здесь. Если будет какие-то другие задачи, где приведенный подход будет решать их плохо, приводить к проблемам, тогда наверное придется использовать асинхронный режим.

    Для Alexeyslav, попробуйте эксперимент: откройте порт, задайте время чтения большим, секунд 10 (ReadTotalTimeoutConstant := 10000) и вызовите синхронно ReadFile. Если ничего к порту не подключено, то естественно ничего не прочитается, и функция возвратится после конца таймаута. Программа на эти 10 сек зависнет. Но посмотрите с помощью диспетчера задач нагрузку на процессор - она будет 0%. 100% вы получаете  из-за того, что постоянно в цикле вызываете ReadFile, т.е. делаете этот самый поллинг, который Василий здесь не раз ругал. Я решаю задачу иначе, выставляя размер буфера чтения в соответствии с задачей
    и выставляя таймауты не "от балды", как написал Германн, а исходя из временных параметров протокола обмена.

    Еще раз повторю тезис.
    Насчет "синхрона". В каких-то конкретных задачах синхронное чтение вполне нормально решает задачу и решает ее простым способом.
    Насчет потоков: и при синхронном и при асинхронном чтении в общем случае стоит использовать дополнительный поток, хотя в каких-то случаях можно обойтись и без этого.


    № 730   23-03-2012 04:18 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 729« (Сергей О.)
    ___________________________
    в сообщение попал мусор. Вот этот отрывок без форматирования как код:
      then Result := True
      else EscapeCommFunction(HCom, CLRRTS);
    end;
    не нужен.


    № 729   23-03-2012 04:16 Ответить на это сообщение Ответить на это сообщение с цитированием
    Я не писал, что синхронное чтение хорошо всегда, а написал "простота такого подхода, если он решает задачу". Правильно применение синхронного чтения, по крайней мере в моем опыте, требует правильного задания как раз тех самых таймаутов. Опишу тип задач, которые часто встречаются мне, в управлении изделиями нашей фирмы. Устройство - slave, ждет запроса или команды от компьютера (программы), получив его, отвечает в заданное время (в общем-то - сразу же). Часто длина пакета в обе стороны - не более ~20 байт. Опыт показывает, что ответ (точно не помню. весь обмен туда-сюда или только время ответа, давно измерял) приходит через 60-80 мс. Иногда из-за разных виндовских штучек задержка может быть и немного больше 100 мс.
    Как я делаю? В ряде давно написанных программ, которые я поддерживаю и сейчас - один поток. Пишу в порт функцией WriteFile сразу весь пакет, например

    type
      TPacket=packed record
        Header: byte;
        Command: byte;
        Data1: byte;
        Data2: byte;
        Data3: byte;
        CtrlSum: byte;
      end;
    ...
    var
      Packet: TPacket;

    function SendCommand: Boolean;
    var WrRslt: LongBool;
    begin
      Result := False;
      BytesWritten := 0;
      if not EscapeCommFunction(HCom, SETRTS)
      then Exit;
      WrRslt := WriteFile(HCom, Packet, SizeOf(Packet), BytesWritten, nil);
      if WrRslt and (BytesWritten = SizeOf(Packet))
      then Result := True
      else EscapeCommFunction(HCom, CLRRTS);
    end;



    Для чтения задаю таймауты так:

        ReadTotalTimeoutMultiplier:=0;
        ReadTotalTimeoutConstant:=200;


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

    type
    TStateAnswer = packed array [1..4] of byte;

      then Result := True
      else EscapeCommFunction(HCom, CLRRTS);
    end;

    Для чтения задаю таймауты так:

        ReadTotalTimeoutMultiplier:=0;
        ReadTotalTimeoutConstant:=200;




    Вот пример, где читается 4 байта, в других ситуациях с этим же подходом бывает и 1, и 33 байта например (передача 33 байта на скорости 9600 порядка 30 мс).


    type
      TStateAnswer=packed array [1..4] of byte;
    ...
    var
      StateAnswer: TStateAnswer;
    ...
      ReadSuccess := ReadFile(HCom, StateAnswer, SizeOf(StateAnswer), BytesRead, nil);


    продолж. следует


    № 728   23-03-2012 04:13 Ответить на это сообщение Ответить на это сообщение с цитированием
    К вопросам оптимизации кода это имеет наверное косвенное отношение, но создавать темы на КД самому невозможно, эта мне кажется более-менее подходящей. Для удобства разобью текст на несколько сообщений.

    Тема - про синхронное чтение/запись в Com-порт. В ответ на мои слова
    В-третьих никакой причины работать синхронно с изначально асинхронным СОМ-портом нет и быть не может. - Есть причина для этого - простота такого

    подхода, если он решает задачу.

    Василий написал:
    нет ничего хуже, чем в Виндах применять  чисто ДОС-овский синхрон. Причем, этот чудик Билли развивая свое детище все больше и больше делает поблажки

    любителям синхрона.

    Германн написал:
    Вот эта простота как раз та, которая хуже воровства.
    Alexeyslav написал:
    Синхронный режим хорош своей простотой, но все достоинства тут же и заканчиваются.
    Дальше у Alexeyslav были слова про то, что такое чтение тормозит и загружает процессор на 100%, про поллинг (опрос порта каждую 1 мс) и т.д.
    Германн написал про таймауты "от балды".

    Сначала, ответ на реплику Германна про потоки: когда я написал об отдельном потоке, я не подразумевал именно синхронный режим чтения. Вы сами согласились, что функцию WaitCommEvent стоит вызывать в отдельном потоке. MSDN пишет и Василий в своей статье
    http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1126
    приводит эти слова про вызов этой функции: "при неудаче и при GetLastError=ERROR_IO_PENDING для получения маски эвентов необходимо вначале вызвать Wait-функцию (например WaitForSingleObject) на ожидание установки hEvent структуры lpOver (параметр WaitCommEvent ) в сигнальное состояние.". О чем я и написал, что используются функции WaitForxxx. Насколько я знаю нередко делают так (Василий в своей статье имено так делает): выносят в отдельный поток вообще операцию чтения вместе с функциями ожидания. Т.е. и при синхронном и при асинхронном чтении частно используют дополнительный поток (потоки).

    Теперь по поводу синхронного чтения из порта.
    Напомню, что синхронное чтение, это когда мы вызываем функцию ReadFile и ждем пока из порта не прочитается заданное в функции кол-во байт или же не выполнится заданное нами условие таймаута чтения. Асинхронное стение - когда функция возвращает результат сразу, а затем мы ожидаем оповещения о том, что что-то прочитано.

    продолж. следует.


    № 727   06-02-2012 04:09 Ответить на это сообщение Ответить на это сообщение с цитированием
    В принципе, поэкспериментировав с пересылкой данных, через eax,mm0,xmm0 пришел к выводу, что передача данных упирается в скорость шины памяти, и от выравнивания мало что зависит, т.к. при обработке массива, даже если он не выровнен, то "лишние" байты закачанные в кэш, все равно потребуются при следующей операции чтения.
    Использование mm0, кстати, дает 15-20% ускорения по сравнению с eax. Использование xmm0 уже не дает ничего, что с выравниваем, что без выравнивания, отсюда и написанный выше вывод.

    Однако, по существу вопроса - оптимизация нужна и использование MMX и SSE2.

    На Круглом столе, к сожалению, вопросов про эти наоборы команд ничтожно мало, неужели никто не оптимизирует.

    Как там с поддержкой AVX и регистров YMM в Delphi XE, никто не знает?


    № 726   03-02-2012 06:25 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 724« (fargo2)
    ___________________________

    Косвенно к вопросу оптимизации. Касается обмена данными с процессором

    Недавно опытным путем выяснил, что при включенном ALIGN=8, Delphi 7 не желает выравнивать содержимое массивов типа array of byte по границе 8.

    Интересно, появился ли в новых версиях Delphi принудительный ALIGN=16 и воздействует ли он на array of byte?


    Директива ALIGN задаёт максимальное значение выравнивания. Каждый тип (как встроенный, так и определённый программистом) имеет собственный Align. Для байтов и массивов байтов Align=1, поэтому директива ALIGN на их выравнивание влиять не должна.

    ЗЫЖ Сто лет сюда не заходил, заглянул - никого...


    № 725   27-01-2012 05:07 Ответить на это сообщение Ответить на это сообщение с цитированием
    Естественно, имеется ввиду первый элемент массива!,

    а не каждый элемент в массиве.


    № 724   24-01-2012 01:15 Ответить на это сообщение Ответить на это сообщение с цитированием
    Косвенно к вопросу оптимизации. Касается обмена данными с процессором

    Недавно опытным путем выяснил, что при включенном ALIGN=8, Delphi 7 не желает выравнивать содержимое массивов типа array of byte по границе 8.

    Интересно, появился ли в новых версиях Delphi принудительный ALIGN=16 и воздействует ли он на array of byte?


    № 723   25-11-2009 06:17 Ответить на это сообщение Ответить на это сообщение с цитированием
    всем доброго дня)Подскажите, пожалуйста, где можно прочитать про (Производительность ПО.Методики измерения производительности .Программные измерительные мониторы)..долго и упорно искал в интернете..но нашел слишком мало информации...пожалуйста помогите))


    № 722   16-06-2009 02:40 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 720« (Игорь)
    ___________________________
    Игорь, чтобы задать вопрос, перейдите по ссылке: http://delphikingdom.com/table/add.asp

    Geo - ;)


    № 721   16-06-2009 02:00 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 720« (Игорь)
    ___________________________
    Вопросы задаются на Круглом Столе, а не здесь.
     Geo


    № 720   16-06-2009 01:29 Ответить на это сообщение Ответить на это сообщение с цитированием
    Здравствутйе.
    В делфи есть иконка Timage существует ли механизм маштабирования нарисованноно изображения
    Подскажите
    Заранее благодарю


    № 719   27-05-2009 00:09 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>ПРОЦЕДУРА Оболочка;
    >>>НАЧАЛО
    >>>ВЫЗОВ ПРОЦЕДУРЫ Имя;
    >>>КОНЕЦ;
    >>>Итого имеем один вход и один выход.

    Можно и без оболочки. Обычно от альтернативных выходов можно избавиться с помощью другой формы записи условной конструкции.
    Например, "неправильную" процедуру типа:
    ПРОЦЕДУРА Имя;
    НАЧАЛО
      ЕСЛИ условие ТО ВЫХОД
    что-то...
    КОНЕЦ
    можно переписать так:
    ПРОЦЕДУРА Имя;
    НАЧАЛО
      ЕСЛИ НЕ условие ТО
      что-то...
      КОНЕЦ ЕСЛИ
    КОНЕЦ

    >>>Какое же это ветвление?
    >>>Это выполнение по условию.

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


    № 718   25-05-2009 06:27 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 717« (Как слышно? Прием!)
    ___________________________
    Это смотря какие теоретики :)
    Первый серьезный язык, моделирующий паралельные процессы, - СИМУЛа 67 имел операторы Activate, Passivate. Сохранялась точка алгоритма, из которой управление передавалось другому процессу. В нее происходил возврат при активации. Если прочертить на тексте стрелками все передачи управления между процессами, получим знакомую картину "спагетти". Activate, Passivate - аналоги GOTO для параллельных процессов.
    Достаточно очевидно, что ничего, не описываемого моделью конечного автомата все равно не реализовать при таком подходе. И моделирование параллельных процессов перешло к аналогу структурного программирования - ансамблю конечных автоматов, обменивающихся сигналами.
    Тогда речь шла о моделировании параллельных процессов на одном исполнителе, но идея управляющего списка легко модифицируется на произвольное число исполнителей.


    № 717   25-05-2009 04:01 Ответить на это сообщение Ответить на это сообщение с цитированием
    Не помню где недавно вычитал примерно следующее.
    При упоминании распределённых вычислений
    теоретики правильного программирования впадают в панику.


    № 716   25-05-2009 03:58 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 713« (S.)
    ___________________________
    ПРОЦЕДУРА Имя;
    НАЧАЛО
    ...
    Получаем управляющие данные от другого модуля (ещё один вход)
    ...
    ЕСЛИ что-то проверяем ТО выходим из процедуры
    что-то делаем
    ...
    КОНЕЦ;

    2 входа, 2 выхода.

    Оболочка только очерчивает группу переходов.


    № 715   25-05-2009 03:51 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 713« (S.)
    ___________________________
    >>> ***Точка входа в конструкцию ветвления
    >>> ЕСЛИ условие ТО алгоритм1 ИНАЧЕ алгоритм2
    >>> ***Точка выхода из конструкции ветвления

    Какое же это ветвление?
    Это выполнение по условию.
    То есть можно заменить на последовательное.
    ЕСЛИ условие ТО алгоритм1
    ЕСЛИ НЕусловие ТО алгоритм2

    Ветвление, это когда переходим на разные логические потоки
    со своими дальнейшими вариантами ветвления в том числе.

    Другое дело, что так называемое структурное программирование
    с принципом разработки "сверху вниз" действительно подразумевает
    последовательное, цепочечное выполнение программы.
    Именно от этого устойчивого заблуждения
    появилась упрощенческая формула "один вход, один выход".
    Если вспомнить про параллельное программирование,
    то подобная "структура" с очевидностью выморочна.


    № 714   25-05-2009 02:30 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 713« (S.)
    ___________________________
    >>> На этом обсуждение оптимизации кода можно заканчивать :)
    :D
    Знаете, обычно я на ассемблер перехожу, когда что-то не получается эффективно реализовать на уровне ЯВУ. В частности, я очень люблю машинные команды для обработки строк, и меня дико раздражает, что при компиляции программы на Паскале вместо этих команд используется перебор элементов массива.

    >>> Всегда?
    Да, всегда. Сделаем Вашу процедуру внутренней и для нее допишем процедуру-оболочку

    ПРОЦЕДУРА Оболочка;
    НАЧАЛО
    ВЫЗОВ ПРОЦЕДУРЫ Имя;
    КОНЕЦ;

    Итого имеем один вход и один выход.

    Я ведь сразу уточнил, что всегда относится к ситуации, "Если же речь идет о реализации" ;-)
     Geo


    № 713   24-05-2009 23:03 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>Функция достаточно эффективна. Размер -- 17 байт.
    На этом обсуждение оптимизации кода можно заканчивать :). Из двух конструкций на языке высокого уровня выбираем тот, для которого транслятор генерирует более короткий и быстродействующий код.

    >>>Ветвление не проходит под формулу "один вход, один выход".
    Если под ветвлением понимать только одно условие, то да. А если всю конструкцию, то нет.

    ***Точка входа в конструкцию ветвления
    ЕСЛИ условие ТО алгоритм1 ИНАЧЕ алгоритм2
    ***Точка выхода из конструкции ветвления

    Впрочем у меня сейчас нет под рукой работ "классиков" по этому вопросу. Что они сами имели в виду утверждать пока не могу. Надо поискать первоисточники...

    >>>Если же речь идет о реализации, то тут проблем никаких: упаковываем
    >>>реализацию алгоритма в процедуру и всегда получаем один вход и один
    >>>выход ;-)

    Всегда?
    ;-)

    ПРОЦЕДУРА Имя;
    НАЧАЛО
    что-то делаем
    ...
    ЕСЛИ что-то проверяем ТО выходим из процедуры
    что-то делаем
    ...
    выходим из процедуры
    КОНЕЦ;

    Здесь 1 вход, но 2 выхода!



    № 712   22-05-2009 07:25 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 687« (S.)
    ___________________________
    Я все же поразвлекался дома и сделал реализацию на ассемблере

    function FindPos(FindVal : Byte; BufPtr : Pointer; BufLen : Integer) : Integer; register;
    asm
      push  edi
      mov  edi,edx
      mov  edx,ecx
      repne scasb
      je    @Found
      xor  edx,edx
    @Found:
      mov  eax,edx
      sub  eax,ecx
      pop  edi
    end;


    Здесь FindVal -- значение, которое нкужно найти (тип -- Byte). BufPtr -- указатель на начало буфера данных. BufLen -- длина буфера. Возвращает позицию байта в буфере, имеющего значение равное FindVal. Нумерация начинается с единицы. Если элемент не найден, возвращается ноль.

    Функция достаточно эффективна. Размер -- 17 байт. И работать будет быстрее, чем предложенные варианты на Паскале, так как оптимизатор ни доля одного варианта не предлагает поиск через REPNE SCAS, а занимается последовательным перебором элементов массива, сравнивая каждый с искомым значеним.
     Geo


    № 711   21-05-2009 12:06 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 705« (S.)
    ___________________________
    >>> у структурного алгоритма должна быть 1 точка входа и 1 точка выхода

    У Дейкстры было последовательное выполнение, цикл и ветвление.
    Ветвление не проходит под формулу "один вход, один выход".
    Либо Вы имели в виду что-то другое.


    № 710   21-05-2009 07:49 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 700« (Александр Алексеев)
    ___________________________

    Цикл for тоже можно исключить из грамматики языка "без какого-либо ущерба".
    Ага. в Python так и сделали. Есть только for-in и while.


    № 709   21-05-2009 06:28 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 701« (S.)
    ___________________________
    >>> А моделировать for с помощью while или repeat - это неудобно
    Думаю, что программисты на Си не поймут данного утверждения. Преимущество цикла FOR в Паскале -- скорость работы. Недостаток -- ограничение на использование переменной цикла. Ну и еще к недостаткам можно отнести, что в цикле WHILE нужно инкремент переменной самростоятельно выполнять, но зато шаг цикла можно делать произвольным. Вот и все различия, которые я смог придумать. А в остальном, что вариант

    for i:=1 to N do
      begin
      // ...
      end;


    что вариант

      i:=1;
      while i <= N do
        begin
        // ...
        Inc(i);
        end;


    да хотя бы и вариант

      for(i=0;i<=N;i++) {
        // ...
      }


    все это -- вещи одного порядка, и особой сложности в переходе с одного на другой не наблюдается.


    Ответ на »сообщение 705« (S.)
    ___________________________
    >>> А какое отношение у общественности к такому принципу структурного программирования: "у структурного алгоритма должна быть 1 точка входа и 1 точка выхода"?
    Не понял, причем тут это. Ну, ладно. Про вход согласен. А вот с выходами -- не совсем. Если рассуждать на уроыне алгоритма, то иногда для полнимания удобнее остановитья на нескольких выходах (например, правильный и ошибочный). Единственно, нужно четко выделять терминальные элементы алгоритма.

    Если же речь идет о реализации, то тут проблем никаких: упаковываем реализацию алгоритма в процедуру и всегда получаем один вход и один выход ;-)
     Geo


    № 708   21-05-2009 06:14 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 707« (Александр Алексеев)
    ___________________________
    Ага. Но это -- поэзия. А сухая проза (для меня) -- это »сообщение 170« и»сообщение 175«
     Geo


    № 707   21-05-2009 05:45 Ответить на это сообщение Ответить на это сообщение с цитированием
    Там ещё Сергей Рощин метко сказал: http://delphikingdom.ru/asp/talktopic.asp?ID=356&ref=msg&msg=122#msg151 - на чём можно было бы и остановиться.


    № 706   21-05-2009 05:26 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>Ломание копий по поводу GOTO в этой теме уже было
    Проклятый склероз! :) Конечно, мы уже общались на эту тему. Причем очень конструктивно. Только тогда меня еще звали "JKJ" и я был еще не такой старый :))).


    № 705   21-05-2009 05:18 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>Так что ничего плохого в этом нет.
    А какое отношение у общественности к такому принципу структурного программирования: "у структурного алгоритма должна быть 1 точка входа и 1 точка выхода"?


    № 704   21-05-2009 05:14 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>При использовании Break и Continue мы продолжаем работать с циклом
    >>>(как структурным элементом написания программы), а не с отдельными
    >>>строками, соответственно, остаемся на уровне струкутрного
    >>>программирования. Так что ничего плохого в этом нет.

    У меня тоже нет никакого абсолютного отрицания break. Я примерно так и сказал - не люблю, но без фанатизма :))


    № 703   21-05-2009 05:07 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 700« (Александр Алексеев)
    ___________________________

    >>> goto - это атавизм, который можно исключить из грамматики языка без ущерба для качества программ
    Цикл for тоже можно исключить из грамматики языка "без какого-либо ущерба".

    goto и for - это совершенно разные вещи. goto делает листинг не читаемым, а циклы легко сворачиваются в современных текстовых редакторах, тем самым декомпозиция происходит более легко.

    Мне кажется что в основу языковых конструкций должны быть заложены основные принципы программирования: декомпозиция, объединение, иерархия и научные методы


    № 702   21-05-2009 05:02 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 699« (S.)
    ___________________________
    Ломание копий по поводу GOTO в этой теме уже было (см. начиная с »сообщение 122« ).

    Кто-то из этого спора что-то вынес, кто-то остался при своем. В общем же, смысл такой: GOTO страшен не потому, что выполняется безусловный переход. Вредность GOTO в том, что, используя его, мы начинаем работать на уровне отдельных операторов (строк). В то время как структурное программирование (начиная с которого декларируется вредность GOTO) предполагает работу с более крупными конструкциями (блоки операторов, процедуры, классы). Таким образом, с точки зрения структурного программиоования, процедуры Break и Continue для циклов (а также процедура Exit для подпрограмм) не являюится плохими: это не произвольный переход куда попало, а структурный элемент цикла (ну, или подпрограммы, если речь идет об Exit). При использовании Break и Continue мы продолжаем работать с циклом (как структурным элементом написания программы), а не с отдельными строками, соответственно, остаемся на уровне струкутрного программирования. Так что ничего плохого в этом нет.
     Geo


    № 701   21-05-2009 04:55 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>Цикл for тоже можно исключить из грамматики
    >>>языка "без какого-либо ущерба".
    Разумеется! У Вирта, если не ошибаюсь, даже была такая попытка в первых версиях Оберона. Потом вернули. Ущерб в данном случае возникает не для программы, а для программиста. Без goto можно обходиться легко. А моделировать for с помощью while или repeat - это неудобно.


    № 700   21-05-2009 04:46 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>> goto - это атавизм, который можно исключить из грамматики языка без ущерба для качества программ
    Цикл for тоже можно исключить из грамматики языка "без какого-либо ущерба".


    № 699   21-05-2009 04:22 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>А вообще-то я вреден для желудка: слишком желчный и противный. Я тоже могу
    >>>в ответ поднять бучу за использование чего-нибудь.
    Между прочим, мы затронули очень интересную тему, тесно связанную с проблемой качества и безопасности программирования.
    Что такое "Принципы программирования" и как к ним вообще следует относиться? Как к "абсолюту", который "выстрадан" теорией и практикой программирования и которому надо следовать всегда и везде? Или как к рекомендации, которой можно пожертвовать в пользу какого-то другого критерия, например, ради быстродействия загрузочного кода?
    Типичный пример такой "религиозной" войны - это отношение к оператору goto. Одни программисты вообще не используют эту конструкцию, даже при ее наличии в языке. Другие используют, но только иногда и ради повышения быстродействия кода (читаемость исходного текста в данном случае уходит на второй план). Третьи вообще считают goto обычной конструкцией, не более вредной, чем любая другая и с Дейкстрой в этом вопросе не соглашаются.
    У меня в связи с этим свой личны опыт. Примерно 5 лет мне пришлось писать на СУБД-ориентированных языках типа dBASE, FoxBase, FoxPro, Clipper. А там никакого goto не было (во всяком случае в той документации, которой я пользовался). Поэтому у меня даже не возникало такого вопроса - использовать goto или нет. Все проекты, которые у нас шли, получались без goto просто автоматически. И после того, как примерно 50 тысяч строк исходников были написаны без безусловных переходов и без каких-либо проблем с реализацией алгоритма, я поверил Дейкстре окончательно. goto - это атавизм, который можно исключить из грамматики языка без ущерба для качества программ. С тех пор - это у меня как рефлекс - писать все, что угодно без goto.
    С break ситуация сложнее. Просто это по смыслу очень напоминает goto, только с переходом без метки и только вперед, за границу тела цикла. Поэтому с этой конструкцией отношения "особые". Без особой необходимости стараюсь не употреблять, но не доводя дело до "фанатизма".


    № 698   21-05-2009 02:14 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 697« (Денис Зайцев)
    ___________________________
    >>> Ща придёт Илья Ермаков и всех вас зохавает за использование Break :)
    Даже если Вас "зохавали", у Вас все равно есть два выхода :D

    А вообще-то я вреден для желудка: слишком желчный и противный. Я тоже могу в ответ поднять бучу за использование чего-нибудь.
     Geo


    № 697   21-05-2009 02:08 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 690« (Бел Амор)
    ___________________________
    Оба варианта чётки и интуитивны. При прочих равных условиях предпочитаю цикл for...

    Ответ на »сообщение 691« (Geo)
    ___________________________
    ...Но при этом упорно не желаете пользоваться процедурой Break...

    Ща придёт Илья Ермаков и всех вас зохавает за использование Break :)


    № 696   21-05-2009 02:02 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 695« (S.)
    ___________________________
    >>> Так будет быстрее выполняться? Несмотря на обращение к функции?
    Насколько я помню, процедура Inc не является процедурой в чистом виде. Это то, что принято называть compiler magic: синтаксически мы пишем процедуру, но компилятор для этой процедуры тела не создает, подставляя в соответствующее место определенный код.
     Geo


    № 695   21-05-2009 01:57 Ответить на это сообщение Ответить на это сообщение с цитированием
    >>>Оба варианта чётки и интуитивны. При прочих равных условиях предпочитаю
    >>>цикл for как более интуитивный и более ошибкобезопасный.
    Спасибо. Я так не написал по чисто "субъективной" причине. У меня "аллергия" на две вещи: на оператор goto и на досрочный выход из цикла (break). В свое время заразился и вот до сих пор болею :)

    >>>1. Вместо i:=i+1 используйте Inc(i)
    Так будет быстрее выполняться? Несмотря на обращение к функции? Или компилятор развертывает это в один и тот же код? Если так, то почему лучше?



    № 694   21-05-2009 01:57 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 689« (Cepгей Poщин)
    ___________________________
    >>> речь о том, что в одном языке используется стиль характерный для другого, выглядит это несколько некрасиво
    Поскольку это все же больше мне, то я и отвечу. А что мне делать, если есть определенный моменты, которые плохо реализованы в Паскале, но хорошо -- в Си? Ждать, пока кто-то напишет синтезированный язык? Написать его самому? Ну его на фиг. Лучше буду писать, как пишу.
     Geo


    № 693   21-05-2009 01:54 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 688« (S.)
    ___________________________
    >>> Какой цикл будет "оптимальнее"?
    Оптимальнее будет тот цикл, в котором при проверке сравнение выполняется с нулем ;-) Оптимальность не зависит от того, в каком направлении выполняется перебор. Например, такие циклы будут по оптимальности одинаковы

      for i:=1 to n do
      // и
      for i:=n downto 1 do


    А с другой стороны, вот такой цикл

      for i:=-10 to 0 do


    будет эффективнее, чем

      for i:=0 downto -10 do

     Geo


    № 692   21-05-2009 01:50 Ответить на это сообщение Ответить на это сообщение с цитированием
    Добавлю от себя.

    Мне если честно, все эти новые конструкции языка появляющиеся год от года, даются если честно с трудом, наверно потому, что могу спокойно обходится без них. Возьмем тот же for in... Но кому то это нравится и он во всю пользуется. Другое дело оптимизация кода, стоит сказать что есть решения языка, есть решения алгоритмичесткие. В С больше вывертов с оптимизацией записи кода, но и проблем согласитесь всетаки тоже поболее, да и разбирать код написанный так, особено чужой тяжело. В Delphi тоже в год от года вносятся модные нововведения, например Operator Overloading или анонимные методы, которые по моему мнению сделаны как то не совсем прозрачно и читабельно, особенно для программиста иследующего код. Есть полезные Class Helper. Есть не очень полезные Nested Clases - по моему мнению лучше делать два класса отдельно, да и читать такую конструкцию тяжело


    type        TOuterClass = class       
      strict private         
        myField: Integer;           
      public           
          type             
          TInnerClass = class             
            public                  myInnerField: Integer;                 
            procedure innerProc;             
          end;           
            procedure outerProc;       
      end;   

    procedure TOuterClass.TInnerClass.innerProc;     
    begin    ... 
    end;



    пока немного кода еще ничего, а если он разрастется. Потом мы забываем, что оптимизация кода вещь двоякая, часть оптимизации может взять на себя компилятор, часть программист. Если оптимизируем для компа - это одно, а если оптимизируем код для передачи например заказчику - это другое. Второе подразумевает наверно более структурный и системообразующий подход, включающий написание документации, внесения комментарий и т.п. Поэтому оптимизация оптимизации рознь. Или вспомнив поговорку лучшее-враг хорошего нужно искать золотую середину.

    Вот так сумбурно как то...



    № 691   21-05-2009 01:47 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 687« (S.)
    ___________________________
    Метод 1 вовсе не дурацкий. Ну, разве что нет смысла выполнять цикл до конца, если искомый элемент найден. Ах, да... Вам же нужно вхождение первого элемента, а не последнего, так что цикл нужно выполнять в прямом направлении, а не в обратном. То есть лучше сделать rfr-nj так:

      с:=0;
      for i:=1 to n do
        if a[i]=0
        then
          begin
          с:=i;
          Break;
          end;


    Метод 2.
    >>> Неплохо, но при отсутствии нулей проверка второго условия за границами массива будет исключена только при условии сокращенного вычисления булевых выражений, т.е. корректность написанного текста зависит от настроек компилятора. Насколько это грамотно?
    Если Вы пишете текст, который может компилироваться неизвестно кем, то вставьте в текст опцию компилятора {$B-}.

    Метод 3 хуже, потому что от него никаким опциями компиляитора не защитишься.

    В методе 4 вы постепенно доходите до того, что я озвучил в модификации метода 1. Но при этом упорно не желаете пользоваться процедурой Break.

      while i <= n do
        if a[i] = 0 then Break else Inc(i);
      if i > n
      then
        // элемент отсутствует
      else
        // нулевой элемент имеет индекс i


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

    Ну, а если, говоря про оптимальность, подразумевать скорость, то последовательный перебор элементов массива не является опитмальным. Правильнее будет использовать специальные команды процессора, обрабатывающие строки. Либо функции языка программирования, использующие эти команды. Например, если речь идет о поиске символа в строке, то разуимнее использовать функцию Pos, которая окажется быстрее, чем последовательны перебор символов. Если нужно для массивов, то можно и на асме функцию накатать, используя REP SCAS. Пример без проверки писать не хочу, так как могу допустить ошибку (плохо помню особенность работы этой команды, а писать надежно, но неэффективно на асме не хочется).
     Geo


    № 690   21-05-2009 01:41 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 687« (S.)
    ___________________________

    Метод 1 (самый "дурацкий")
    с:=0;
    for i:=n downto 1 do
    if a[i]=0 then с:=i


    Действительно дурацкий, поскольку:
    1. Перебирается весь массив без необходимости.
    2. Происходит многократное присвоение целевой переменной.
    3. Цикл развёрнут, что скрывает смысл.

    Метод 2.
    i:=1;
    while (i<=n) and (a[i]<>0) do i:=i+1
    Неплохо, но при отсутствии нулей проверка второго условия за границами массива будет исключена только при условии сокращенного вычисления булевых выражений, т.е. корректность написанного текста зависит от настроек компилятора. Насколько это грамотно?


    Есть любители применения быстрой оценки. Лично я избегаю таких моментов всеми силами и второе условие всегда оформляю через then if
    Лично я так не написал бы никогда.

    Метод 3.
    i:=1;
    while (a[i]<>0) and (i<=n) do i:=i+1
    Это уже не грамотно по указанной выше причине. При отсутствии нулей проверка первого условия будет некорректна после выхода i за границу массива.


    Сами всё сказали...

    Метод 4.
    c:=0; i:=1;
    while (c=0) and (i<=n) do
    begin
    if a[i]=0 then c:=i;
    i:=i+1
    end
    Самый "длинный", но похоже самый "умный" из четырех.


    Завязка на конкретное начальное значение и последующее сравнение на неравенство ему выглядит крайне некрасиво. Кроме того, крайне неинтуитивно...

    Самое интересное в этих примерах то, что все они "работают". Но что будет "оптимальным"? Особенно с точки зрения обучения "правильному и эффективному программированию"?

    В таких случаях я вспоминаю загадку:
    Вопрос: Чем отличаются программа и самолёт?
    Ответ: Некрасивый самолёт не полетит...

    Я бы предложил два других варианта:

      c := 1;
      while c <= n do
        if a[c] = 0 then
          Break
        else
          Inc(c);


      for i := 1 to n do
        if a[i] = 0 then
        begin
          c := i;
          Break;
        end;

    Оба варианта чётки и интуитивны. При прочих равных условиях предпочитаю цикл for как более интуитивный и более ошибкобезопасный. Только нужно хорошо запомнить, что за пределами цикла переменную цикла использовать нельзя.

    P.S.
    1. Вместо i:=i+1 используйте Inc(i)
    2. Используйте кнопку CODE для подсветки синтаксиса (здесь).
    3. Форматируйте код (вообще).


    № 689   21-05-2009 01:06 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 684« (S.)
    ___________________________
    Вас S, похоже за живое задело :)
    В самой идее "смешивания" языков в рамках одного проекта нет ничего страшного. Речь не о том, что часть программы написана на одном языке, часть на другом. Давайте из мира идей вернемся к теме обсуждения »сообщение 673«, мой наезд на C был конечно шуткой, но если серьёзно, то речь о том, что в одном языке используется стиль характерный для другого, выглядит это несколько некрасиво, как разговор с сильным акцентом. И главное не надо делать из этого глубоких выводов, а то опять во флейме потоним.
     Cep


    № 688   21-05-2009 00:14 Ответить на это сообщение Ответить на это сообщение с цитированием
    И еще один "детский" вопрос "в догонку".

    Какой цикл будет "оптимальнее"?
    for i:=0 to n do
    или
    for i:=n downto 0 do


    737—688 | 687—638 | ...>>>
    Всего сообщений в теме: 737; страниц: 15; текущая страница: 1


    Добавить свое сообщение

    Отслеживать это обсуждение

    Дополнительная навигация:
    Количество сообщений на странице

    Порядок сортировки сообщений
    Новое сообщение вверху списка (сетевая хронология)
    Первое сообщение вверху списка (обычная хронология)

    Перейти на конкретную страницу по номеру
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования