"Информатика (базовый и углублённый уровень)", Гейн А.Г., Сенокосов А.И.
Исследование алгоритма и программы помогает выяснить, верно ли решение задачи и насколько оно эффективно. Для этого сначала уточняют входные данные, ожидаемый результат и ограничения, затем прослеживают выполнение команд и проверяют программу на специально подобранных тестах. Один удачный запуск ещё не доказывает правильность: нужны обычные, граничные и специальные случаи. Сравнивая решения на одинаковых данных, можно оценить их скорость и расход памяти.
Текст подготовлен нейронной сетью по теме параграфа и не заменяет учебник — важные факты и формулировки сверяйте с ним.
Алгоритм — точное конечное описание действий, которое преобразует исходные данные в результат. Иначе говоря, это план решения, в котором определены шаги и порядок их выполнения. Понятное описание нужно, чтобы проверить, решает ли план задачу и можно ли выполнить его без догадок.
Программа — запись алгоритма на языке программирования, предназначенная для выполнения компьютером. В ней идея решения выражена командами, синтаксис которых должен соответствовать правилам языка. Это определение помогает отличать замысел решения от его конкретной реализации и искать источник ошибки.
Трассировка программы — последовательная фиксация значений переменных и выполняемых команд. При трассировке выполнение как будто замедляют: после каждого шага записывают, что изменилось и какое условие проверено. Она нужна, чтобы объяснить появление результата и заметить место, где ход вычислений пошёл не так.
Тестовый набор — специально подобранные входные данные для проверки алгоритма или программы. Тесты должны представлять разные ситуации, а не только удобный типичный пример. Такой набор позволяет обнаружить ошибки и понять, при каких условиях решение работает корректно.
Исследование начинают с формулировки входных данных, результата и ограничений, потому что иначе нельзя определить, что считать правильным решением. Например, важно знать, могут ли числа быть отрицательными и каков максимальный размер массива. Эти условия влияют на выбор алгоритма и задают область, для которой требуется проверка. Точное описание задачи также предотвращает ситуацию, когда программа верно решает не ту задачу.
Трассировка позволяет установить порядок выполнения команд и увидеть изменения переменных, потому что программа в каждый момент хранит промежуточное состояние вычислений. Для каждого шага записывают текущие значения, проверяемое условие и следующую команду. Так можно объяснить, почему цикл повторился или завершился и откуда взялся ответ. Если результат неожиданен, таблица состояний помогает локализовать ошибку.
Одних типичных примеров недостаточно: ошибки часто проявляются только на границах допустимых значений или в особых ситуациях. Поэтому проверяют обычные данные, граничные случаи и ошибочный ввод, если программа должна его обрабатывать. Например, поиск максимума стоит проверить на одном элементе и на последовательности одинаковых значений. Разнообразие тестов увеличивает шанс обнаружить неверное условие или пропущенный случай.
Алгоритмы сравнивают по правильности результата, числу действий, времени работы и используемой памяти, потому что одного критерия для выбора может быть мало. Быстрое решение бесполезно, если оно иногда даёт неверный ответ; зато при верных ответах экономия времени может иметь значение на больших данных. Чтобы сравнение было честным, алгоритмы запускают на одинаковых входах. Несколько размеров и порядков данных помогают понять, в каких условиях преимущество сохраняется.
Один удачный пример не доказывает правильность программы, потому что он подтверждает её поведение только на одном входе. Программа может пройти по одной ветви и не проверить другие условия. Обратная ситуация сильнее: найденный контрпример — конкретные данные, на которых утверждение о правильности не выполняется. Такой тест опровергает универсальное утверждение и помогает уточнить причину сбоя.
| Этап исследования | Что проверяется | Какие данные или действия используются | Какой вывод фиксируется |
|---|---|---|---|
| Формулировка задачи | Входные данные и требуемый результат | Описание ограничений и условий применимости | Понятно, что именно должна делать программа |
| Трассировка | Порядок команд и изменение переменных | Пошаговое выполнение на выбранном примере | Объяснено получение результата |
| Тестирование | Корректность на разных типах входных данных | Обычные, граничные и ошибочные тесты | Зафиксированы пройденные и непройденные проверки |
| Сравнение алгоритмов | Количество операций и ресурсы | Одинаковые входные данные для нескольких программ | Выбран более подходящий алгоритм |
| Формулировка вывода | Соответствие результата условию | Сопоставление ожидаемого и фактического результата | Указаны область применимости и обнаруженные ограничения |
Используйте таблицу как последовательный план: сначала зафиксируйте условие задачи, затем изучите выполнение и проведите проверки. Для каждого этапа записывайте не только действия, но и полученный вывод. Так исследование можно повторить и понять, на чём основано итоговое решение.
Задача 1. Для алгоритма поиска максимального элемента выполнить трассировку на последовательности 7, 3, 9, 9, 2 и записать изменения переменной максимума. Предположим, что сначала максимумом объявляют первый элемент, затем сравнивают с ним остальные. Нужно проследить каждое сравнение и убедиться, что итоговое значение действительно наибольшее.
Ответ: значения переменной максимума после обработки элементов — 7, 7, 9, 9, 9. Равный текущему максимуму элемент не меняет значение переменной, а проверка всех элементов подтверждает итог.
Задача 2. Проверить программу, которая определяет, является ли число простым, на единице, нуле, отрицательном числе, простых и составных числах; найти возможный сбой. Число простое, если оно больше 1 и имеет ровно два натуральных делителя. Это определение сразу подсказывает, что проверять только делимость на несколько чисел недостаточно: нужно отдельно обработать значения меньше 2.
Ответ: единица — подходящий контрпример для реализации без отдельной проверки условия n < 2. Правильная программа должна сообщать, что числа меньше 2 не являются простыми.
Задача 3. Сравнить два алгоритма сортировки на массивах разных размеров и с разным порядком элементов. Цель — не просто определить победителя на одном запуске, а выяснить, как меняется работа алгоритмов в разных условиях. Для честности подают одинаковые копии массива, а результат каждого измерения записывают.
Ответ: более подходящим будет алгоритм, который корректно сортирует все проверенные массивы и лучше отвечает выбранным требованиям по скорости и памяти. Вывод о преимуществе ограничивают условиями проведённых испытаний.
Проверка на одном удобном примере не охватывает все варианты входа, поэтому программа может пройти тест и ошибиться на границе. Так происходит, когда тест выбирают лишь потому, что ответ легко посчитать. Проверьте себя: включите минимальные, максимальные и специальные значения, а также разные ветви условий.
Смешивание ошибки алгоритма и ошибки реализации мешает исправить причину сбоя: неверна может быть как идея, так и конкретная команда. Часто замечают только неправильный итог и сразу переписывают код целиком. Проследите трассировку: если неверен ожидаемый ход решения — пересмотрите алгоритм, если ошибка возникает на отдельном шаге — проверьте реализацию.
При трассировке можно забыть начальное значение переменной или неверно определить завершение цикла. Из-за этого меняется число обработанных элементов и итоговый результат. Перед расчётом выпишите начальное состояние, условие продолжения и момент проверки условия.
Сравнение программ на разных данных или по одному измерению не даёт надёжного вывода: сложность входов может отличаться, а время — колебаться. Причина ошибки обычно в стремлении упростить эксперимент. Используйте одинаковые входы, несколько размеров и повторные измерения, заранее выбрав критерий сравнения.
Для исследования нужны знания о свойствах алгоритмов и основных конструкциях программирования: переменных, ветвлениях, циклах и массивах. Без понимания этих элементов трудно проследить выполнение команд или выбрать содержательные тесты. Сами приёмы исследования становятся основой отладки и доказательства корректности алгоритмов. Позже они помогают оценивать сложность и выбирать эффективное решение для ограничений конкретной задачи.
Чем исследование алгоритма отличается от обычного запуска программы?
Обычный запуск показывает результат для одного входа. Исследование включает формулировку условий задачи, трассировку, серию тестов и оценку ресурсов. Оно помогает объяснить, почему программа работает именно так и где могут быть ограничения.
Почему нельзя проверить правильность программы одним примером?
Один пример проверяет только один путь выполнения и может не затронуть граничные случаи или отдельные ветви условий. Программа может случайно дать правильный ответ на этом входе, но ошибиться на другом. Поэтому используют наборы разных тестов.
Как выбрать граничные тестовые данные?
Нужно найти минимальные и максимальные допустимые значения, а также случаи рядом с границами ограничений. Полезно проверить пустой или минимальный ввод, одинаковые элементы, ноль и особые значения, если они допустимы по условию. Отдельно проверяют вход за пределами допустимой области.
Что делать, если программа выдаёт неверный результат?
Сначала повторите запуск на том же входе и запишите ожидаемый и фактический результаты. Затем выполните трассировку и найдите команду, после которой значения расходятся с ожидаемыми. Определите, ошибочна ли идея алгоритма или её реализация в коде, и проверьте исправление на других тестах.
Как корректно сравнить быстродействие двух алгоритмов?
Запустите обе программы на одинаковых входных данных и в одинаковых условиях. Используйте несколько размеров и порядков элементов, а не одно измерение; сравнивайте число операций или время работы. При необходимости отдельно учитывайте объём памяти.
Лабораторная работа № 20 (к § 48) Исследование алгоритмов и программ