Программирование. Оптимизация по времени и памяти
Теория к заданию 27 из ЕГЭ по информатике
Технология программирования
Чтение короткой (30±50 строк) простой программы на алгоритмическом языке (языке программирования)
Запись алгоритма в словесной форме, в виде блок-схемы или на псевдокоде должна быть точна настолько, чтобы позволить исполнителю правильно выполнить алгоритм, при этом изображение команд произвольное. При решении любой задачи на компьютере предполагается, что некоторая информация подвергается обработке по предварительно составленной инструкции, называемой программой. Язык, на котором записывается алгоритм для исполнения компьютером, называется языком программирования. Языки программирования принадлежат к формальным языкам. При записи алгоритма на языке программирования все правила языка должны строго выполняться. Программа — это алгоритм, записанный на языке программирования.
Для записи программ используется конечный набор символов, составляющих алфавит языка программирования. В отличие от привычных алфавитов (например, русского) алфавит языка программирования включает в себя, кроме букв, цифры, знаки препинания, знаки арифметических действий и некоторые другие дополнительные символы. Программа записывается в виде последовательности символов из алфавита своего языка программирования. Естественно, что не любой текст, составленный из символов алфавита, будет правильной программой. Как и в естественных языках, правильность построения программы из символов алфавита можно проверить, используя синтаксис языка программирования.
Синтаксис языка программирования — это набор правил, которые определяют способы построения правильных программ из символов алфавита. Зная синтаксис языка, можно построить алгоритм, который определяет, является ли данный текст правильной программой или нет. Этот алгоритм позволяет компьютеру проверять синтаксическую правильность вводимых в него программ.
Должна быть определена и семантика языка программирования. Семантика языка программирования — это набор правил, по которым исполнитель выполняет программы на этом языке. Пользуясь семантикой языка, можно однозначно определить результат выполнения программы с заданными входными данными.
При чтении программы необходимо сначала определить, к какому виду она относится. Условно программы можно разделить на два вида: простая программа без использования подпрограмм (кроме стандартных процедур ввода\вывода) и программа, использующая подпрограммы (подалгоритмы). Такая программа может включать в свою структуру как стандартные подпрограммы, так и подпрограммы, написанные пользователем.
Для чтения простой программы необходимо выяснить:
- что является входными данными и как они вводятся в программу;
- какие действия последовательно выполняются с помощью каждого функционального узла программы (операторов), т. е. рассмотреть пошаговое выполнение операторов, при этом обратить внимание на роль вспомогательных переменных, массивов и т.д.;
- что является результаты работы программы;
- каковы ограничения по работе алгоритма.
При чтении программы, использующей подпрограммы, необходимо сначала проанализировать, что и как выполняют подпрограммы, каковы их входные и выходные параметры. Затем в основной программе вызовы каждой из подпрограмм рассматривать уже как результат работы соответствующего подалгоритма.
Существенно облегчает чтение программ наличие комментариев — поясняющего текста. Комментарии можно добавлять в любое место программы. Наличие комментариев — обязательное условие хорошо и грамотно написанной программы.
Примеры чтения программ на языках Pascal, QBASIC
Примечание. В приведенных примерах программа приводится для двух языков программирования. В зависимости от того, какой язык программирования изучается, и следует рассматривать ее вариант записи и соответствующие пояснения.
Пример 1. Дана программа на двух языках программирования. Определить, какую задачу она решает.
Решение. Проанализируем тексты программы:
- формируется тело программы и описываются переменные;
- вводятся натуральные числа М и N, причем проверяется условие корректности ввода: числа должны быть положительные. Если введенные значения не удовлетворяют условию, то ввод повторяют, пока условие не будет выполнено;
- выбирается наименьшее значение из М и N, результат записывается в K;
- NOD присваивается значение 1;
- в цикле от двух до K генерируется число I;
- тело цикла — в условном операторе проверяется, является ли значение переменной I одновременно делителем М и N. Если условие выполняется, то текущее значение I сохраняется в переменной NOD; если условие не выполняется, NOD не изменит своего значения;
- после перебора всех значений I в NOD или запишется наибольший делитель двух чисел М и N, или останется значение 1;
- последний оператор программы служит для вывода результата работы программы — значения переменной NOD.
Переменные, используемые в программе:
N, М — исследуемые числа;
I — переменная цикла;
NOD — наибольший общий делитель;
К — наименьшее из М и N.
Ответ: данная программа позволяет определить для двух чисел М и N их наибольший общий делитель NOD.
Примечание. Эту же задачу можно решить, используя алгоритм Евклида.
Пример 2. Дана программа на двух языках программирования. Определить, какую задачу она решает.
Решение. Проанализируем тексты программы:
- формируется тело программы, описываются переменные и одномерный массив MAS целого типа (для Pascal целый массив длиной 100);
- вводится фактическая длина массива N с проверкой на положительное значение N;
- вводится значение первого элемента массива MAS;
- устанавливается начальное значение МАХ по первому элементу массива;
- переменной К присваивается значение 1;
- последовательно, в цикле, просматриваются вводимые элементы массива, и если очередной элемент MAS(I) больше или равен МАХ, то переписывается значение MAS(I) в МАХ и в переменной К запоминается I;
- выводятся результаты: МАХ — значение максимального элемента массива и К — номер максимального элемента в исходном массиве (если таких элементов несколько, выведется номер самого правого максимума).
Переменные, используемые в программе:
MAS — массив чисел;
N — размер массива;
I — переменная цикла;
МАХ — значение наибольшего элемента;
К — номер наибольшего элемента.
Ответ: программа написана для поиска значения максимального элемента массива и его номера (если таких элементов несколько, то будет найден номер самого правого максимума).
Пример 3. Дана программа на двух языках программирования. Определить, какую задачу она решает.
Решение. Проанализируем тексты программы:
- формируется тело программы и описываются переменные;
- вводится строка символов S;
- определяется длина строки, значение которой заносится в переменную L;
- в цикле осуществляется замена '!' на '.' в исходной строке;
- выводится преобразованная строка.
Переменные, используемые в программе:
I — переменная цикла;
L — длина строки;
S — строка текста.
В программе на языке Pascal используется встроенная функция языка:
Length(STR) — она определяет фактическую длину строки STR (длина строки не более 256 символов).
В программе на языке QBASIC используются встроенные функции:
Len(X) — определяет фактическую длину строки X (длина строки не более 256 символов);
M1D$(X$, N, M) — выделяет M символов, начиная с N-го символа в символьном выражении X$ (M можно опустить).
Ответ: данная программа позволяет заменить во введенной строке символов все восклицательные знаки на точки.
Пример 4. Дана программа на двух языках программирования. Определить, какую задачу она решает.
Решение. Проанализируем текст программы на языке Pascal:
- формируется тело программы и описываются переменные;
- вводится строка STR и дублируется во вспомогательной переменной S1;
- определяется местоположение первой точки в тексте; если точка есть, то из S1 вырезается текст до нее;
- ищется вторая точка; если она есть, то из S1 вырезается текст после нее;
- в зависимости от присутствия точек результат выводится на экран.
Используемые переменные:
I — номер позиции, которая соответствует точке;
STR — строка текста;
S1 — вспомогательная переменная.
В данной программе используются встроенные функции языка Pascal:
Pos(S1, S2) — поиск подстроки S1 в строке S2 ;
Delete(S, N, M) — удаление из строки S M символов, начиная с позиции N;
Copy(S, N, M) — выделение подстроки из M символов, которые располагаются в строке S начиная с позиции N.
Проанализируем текст программы на языке QBASIC:
- формируется тело программы, и описываются переменные;
- вводится строка символов S;
- определяется местоположение первой точки в тексте — М1;
- ищется вторая точка в строке (поиск начинается с символа М1 + 1); если в строке есть две точки, то на экран выводится текст, находящийся между двумя точками, если нет — сообщение "В тексте нет двух точек".
Используемые переменные:
S — строка текста;
Ml, M2 — номера позиций двух точек; если точек нет, то значения Ml и М2 равны нулю.
В данной программе используются встроенные функции языка:
INSTR(N, X$, Y$) — поиск подстроки Y в строке X, начиная с N-го символа (N можно опустить);
MID$(X$, N, M) — выделение M символов, начиная с N-го символа в символьном выражении X$ (M можно опустить).
Ответ: данная программа из заданной строки символов выделяет подстроку между первой и второй точкой.
Пример 5. Проанализировать тексты программы.
Решение.
- Формируется тело программы и описываются переменные и двумерный массив MАS;
- вводится фактический размер массива MAS и значения его элементов;
- просматриваются строки массива справа налево, находиться минимальный элемент в строке и запоминаются значения индексов (номер столбца) этого элемента;
- для каждой строки выводится значение и местоположение самого правого минимального элемента.
Используемые переменные:
MAS — двумерный массив;
N, M — количество строк и столбцов массива;
I, J — переменные цикла;
JM — столбец минимального элемента для данной строки;
MIN — текущий минимум.
Ответ: программа решает задачу поиска в каждой строке двумерной матрицы минимального элемента и его координат. Если таких элементов в строке несколько, то выводится значение и координаты самого правого элемента.
Поиск и исправление ошибок в небольшом фрагменте программы (10±20 строк)
Существует три аспекта проверки программы:
- на правильность;
- на эффективность реализации;
- на вычислительную сложность.
Эти проверки, вместе взятые, направлены на получение экспериментального ответа на вопросы: работает ли алгоритм и насколько хорошо он работает? Предполагается, что проверка правильности удостоверяет, что программа делает в точности то, для чего она была предназначена. Проверка эффективности реализации направлена на поиск способов «заставить» правильную программу работать быстрее или расходовать меньше памяти. Чтобы улучшить программу, пересматриваются результаты этапа реализации в процессе построения алгоритма.
Проверка вычислительной сложности сводится к экспериментальному анализу сложности алгоритма или к экспериментальному сравнению двух или более алгоритмов, решающих одну и ту же задачу.
Наличие ошибок в только что разработанной программе — вполне нормальное, закономерное явление. Составить реальную (достаточно сложную) программу без ошибок практически невозможно. Нельзя делать вывод, что программа правильна, лишь на том основании, что она считает и выдает результаты.
Текст программы можно проконтролировать за столом с помощью просмотра, проверки и прокрутки.
Просмотр. Текст программы просматривается на предмет обнаружения явных ошибок и расхождений с алгоритмом. Нужно просмотреть организацию всех циклов, чтобы убедиться в правильности операторов, задающих кратности циклов. Полезно просмотреть еще раз условия в условных операторах, аргументы в обращениях к подпрограммам и т. п.
Проверка. При проверке программы программист по тексту программы мысленно старается восстановить тот вычислительный процесс, который определяет программа, после чего сверяет его с требуемым алгоритмом.
Прокрутка. Основой прокрутки является имитация программистом за столом выполнения программы на машине. Для выполнения прокрутки приходится задаваться какими-то исходными данными и производить над ними необходимые вычисления.
Прокрутка — трудоемкий процесс, поэтому ее следует применять только для контроля логически сложных участков программы.
После просмотра программы вручную ее необходимо отладить и протестировать на компьютере.
Отладка — это процесс поиска и устранения ошибок в программе, производимый по результатам ее прогона на компьютере.
Тестирование — это испытание, проверка правильности работы программы в целом или ее составных частей.
Отладка и тестирование — два разных этапа:
- при отладке происходит локализация и устранение синтаксических ошибок и явных ошибок кодирования;
- в процессе тестирования проверяется работоспособность программы, не содержащей явных ошибок. Тестирование устанавливает факт наличия ошибок, а отладка выясняет их причину.
Как бы тщательно ни была отлажена программа, решающим этапом, устанавливающим ее пригодность для работы, является контроль программы по результатам ее выполнения на системе тестов. Программу условно можно считать правильной, если ее запуск для выбранной системы тестовых исходных данных во всех случаях дает правильные результаты.
Тестовые данные должны обеспечить проверку всех возможных условий возникновения ошибок. Процесс тестирования можно разделить на три этапа:
- Проверка в нормальных условиях. Предполагает тестирование на основе данных, которые характерны для реальных условий функционирования программы.
- Проверка в экстремальных условиях. Тестовые данные включают граничные значения области изменения входных переменных, которые должны восприниматься программой как правильные данные. Типичными примерами таких значений являются очень маленькие или очень большие числа и отсутствие данных. Еще один тип экстремальных условий — граничные объемы данных. Например, когда массивы состоят из слишком малого или слишком большого количества элементов.
- Проверка в исключительных ситуациях. Проводится с использованием данных, значения которых лежат за пределами допустимой области изменений.
Ошибки могут быть допущены на всех этапах решения задачи. Разновидности характерных ошибок:
- Неправильная постановка задачи — верное решение неверно сформулированной задачи.
- Неверный алгоритм — выбор алгоритма, приводящего к неточному, неэффективному решению задачи.
- Ошибки анализа — неполный учет ситуаций, которые могут возникнуть; логические ошибки.
- Семантические ошибки — неправильный порядок выполнения операций.
- Синтаксические ошибки — нарушение правил, определяемых языком программирования.
- Ошибки при выполнении операций — слишком большое число (переполнение), деление на нуль, извлечение квадратного корня из отрицательного числа и т. п.
- Ошибки в данных — неправильное определение возможного диапазона изменения данных.
- Опечатки — перепутаны близкие по написанию символы, например цифра 1 и буква I.
- Ошибки ввода/вывода — неверное считывание входных данных, неверное задание форматов, отсутствие некоторых данных.
В качестве примера рассмотрим программу, в которой вычисляется значение функции по приведенным формулам в зависимости от значения параметра K, который является номером режима.
$y(x)=\{\table\√{a_1x^2+b_1x+c_1}, \text"если"\ K=1; \√{a_2x^2+c_2}, \text"если"\ K=2; \√{b_3x+c_3}, \text"если"\ K=3;$
Программа имеет вид
Ошибки, допущенные при написании программы:
- Пропущен ввод исходных данных А1, B1, C1, A2, C2, B3, C3; пропущено описание переменной Y (для языка Pascal).
- В приведенной программе не предусмотрена обработка ситуации, когда под корнем получается отрицательное значение. Необходимо использовать условный оператор для определения положительности подкоренного выражения.
- Отсутствует анализ ситуации, когда вместо цифр 1, 2, 3 для переменной К считана другая цифра. В этом случае, можно выдавать, например, сообщение: «Номер режима неверен». Для выдачи такого сообщения в программе в саsе-операторе после строки с меткой 3 нужно добавить строку вида else <Печать сообщения> (вариант 1). Можно также организовать ввод параметра K с проверкой введенного значения, и при ошибочном вводе требовать повторения ввода значения для переменной K (вариант 2).
Пример откорректированной программы (вариант 1).
Пример откорректированной программы (вариант 2).
Создание собственной программы (30±50 строк) для решения простых задач
Процесс создания компьютерной модели можно представить как путь от постановки задачи до реализации модели на компьютере. При разработке компьютерной модели очень важен выбор программного обеспечения (ПО), с помощью которого будет реализована модель. Возможны два основных варианта выбора — это, во-первых, прикладное ПО и, во-вторых, среда программирования. Если в качестве ПО была выбрана среда программирования, то построение компьютерной модели завершается созданием программы.
При написании программы прежде всего следует четко уяснить задачу, которую должна решать программа. Затем предварительно разработанный алгоритм решения задачи записывается в виде упорядоченной последовательности команд (инструкций), т. е. составляется программа, ориентированная на определенную среду программирования.
При написании программы обязательно следует проверять, насколько она соответствует намеченной цели, т. е. делает ли программа для всех наборов данных то, что от нее требуется, не выполняет ли она каких-либо лишних действий. Основное внимание следует сосредоточить на предотвращении логических ошибок. Для этого рекомендуется перед написанием программы построить блок-схему алгоритма решения или словесный алгоритм, что позволит абстрагироваться от конкретного языка программирования и сосредоточиться на анализе алгоритма.
Примеры разработки программ
Пример 1. Составить словесный алгоритм, разработать блок-схему и написать программу проверки принадлежности введенного числа данной арифметической прогрессии. Прогрессия задается двумя последовательными членами.
Решение. Словесный алгоритм.
Начало алгоритма
- Ввести два последовательных члена арифметической прогрессии: A1, A2.
- Ввести произвольное целое число C.
- Найти разность (D) арифметической прогрессии.
- Найти разность между введенным числом C и членом арифметической прогрессии, например A1.
- Найти остаток от деления нацело найденной разности на D.
- Если остаток от деления равен 0, то это значит, что число C принадлежит рассматриваемой арифметической прогрессии»; иначе получаем, что число C не принадлежит рассматриваемой арифметической прогрессии.
Конец алгоритма.
Блок-схема алгоритма:
Программа:
Примечание. Mod — операция, результатом которой является остаток от целочисленного деления.
Пример 2. Составить словесный алгоритм, алгоритм в виде блок-схемы и написать программу поиска в строковом массиве, содержащем фамилии 10 учеников, заданной фамилии, обеспечить запоминание ее порядкового номера (массив фамилий может быть неупорядочен).
Решение.
Словесный алгоритм
Начало алгоритма
- Ввести все десять фамилий (строковый массив из 10 элементов).
- Ввести фамилию, которую нужно найти.
- Сравнивать ее с очередным элементом строкового массива, пока не будет найдена такая же фамилия или пока не закончится список (массив).
- Если фамилия найдена, вывести ее номер в списке (массиве), если нет — сообщить о том, что фамилия не найдена.
Конец алгоритма.
Блок-схема алгоритма
Программа: