- •1. Структура (состав) языка
- •2. Алфавит
- •3. Лексическая структура языка
- •4. Структура программной единицы
- •5. Стиль записи программ на языке Паскаль
- •6. Типы данных в Паскале
- •6.3 Классификация типов данных в Турбо Паскале
- •6.4 Порядковые типы
- •6.4.2 Булевский (логический) тип
- •Repeat тело_цикла until (логическое_выражение);
- •6.4.3 Целые типы Выделяют целые типы ------------- со знаком – shortint, integer, longint)
- •1 Группа функций:
- •2 Группа функций:
- •3 Группа функций:
- •6.4.4 Перечисляемый тип.
- •6.4.6 Символьный тип
- •6.5 Вещественные типы.
- •7. Выражения в языке Паскаль.
- •10. Вычисление по формулам.
- •10.1 Оператор присваивания .
- •10.2 Характер использования переменных в математике и в программах.
- •10.3 Бесконечности
- •10.4 Нестандартные операции
- •6.6 Строки
- •1) Операции присваивания и сравнения.
- •3) Заполнение строки одним символом
- •4) Стандартные функции и процедуры для работы со строками:
- •5) Подпрограммы преобразования из строкового представления в числовое и наоборот:
- •8. Совместимость и преобразование типов.
- •Совместимость типов
- •8.2 Тип результата арифметических выражений.
- •8.3 Преобразование (приведение) типов и значений.
- •8.3.1 Явное преобразование (приведение) типов.
- •8.3.2 Неявное преобразование или приведение типов.
- •9. Простейший ввод-вывод на Паскале
- •Стандартные файлы Input и Output
- •9.2 Процедуры ввода информации (с клавиатуры.
- •9.3 Процедуры вывода в тр.
- •10. Вычисление по формулам (продолжение)
- •10.6. Уточнение многоместных (n - арных) операций
- •11. Средства языка Паскаль для циклов с известным числом повторений.
- •12. Табулирование функций
- •13. Разветвляющиеся алгоритмы
- •13.1 Таблица ситуаций и команда выбора.
- •13.2 Средства языка Паскаль для программирования разветствляющихся алгоритмов
- •13.4 Описание ситуаций
- •13.5 Запись команды выбора (case) (уточнение таблицы ситуаций) с помощью набора команд ветвления
- •13.6 Запись последовательных команд ветвления в случае, когда соседние зависимые ситуации имеют общие признаки.
- •13.6.1 Восходящий подход
- •13.6.2 Нисходящий подход
- •14. Циклы с неизвестным числом повторений
- •15. Структурированные типы данных. Массивы
- •15.1 Классификация (особенности) структурированных типов данных
- •15. 2. Определение массива
- •15.3 Объявление массива на Турбо Паскале
- •15.4 Хранение элементов массива. Доступ к элементам и частям массива
- •15.5 Уточнение команд обработки массива
- •16. Правила разработки цикла
- •15. 6 Действия над массивами
- •17. Множества.
- •17.1 Множества в Паскале и в математике. Сходства и различия между ними.
- •17.2 Объявление множества на Паскале
- •17.3 Присваивание значений множествам. Конструктор множества
- •17.4 Операции над множествами.
- •17.5 Сравнение множеств.
- •17.6 Применение множеств.
- •18. Вспомогательные алгоритмы (подпрограммы).
- •18.1 Три способа записи повторяющихся команд
- •18.2 Понятие блока
- •18.3 Объекты подпрограммы (то, над чем выполняются действия).
- •18.4 Свойства локальных и глобальных объектов
- •Свойства глобальных объектов:
- •18.5 Выделение памяти под локальные и глобальные переменные
- •18.6 Передача параметров в подпрограммы.
- •Фактические параметры
- •18.7 Подпрограммы, возвращающие значение (функции)
- •18.8 Особенности использования процедур и функций в Турбо Паскале
- •18.9. Побочный эффект (side effect)
- •18.10 Опережающее определение процедур и функций.
- •18.11 Рекурсия и итерация.
- •18.12 Процедуры и функции как параметры.
- •18.13 Директивы подпрограмм
- •Директива forward
- •Директивы far и near
- •Директива external
- •Директива assembler
- •Директива inline
- •Директива interrupt
- •Отладка и тестирование программ, содержащих подпрограммы
- •18.14.1 Нисходящее тестирование и подпрограммы-заглушки
- •18.14.2 Восходящее тестирование и программы-тестеры
- •18.14.3 Рекомендации по отладке программ, содержащих подпрограммы
- •18.14.4 Использование отладчика для трассировки процедур
- •18.14.5 Область действия идентификаторов и переменные в окне Watch
- •18.15. Получение доступа а параметрам командной строки, запуск внешних программ.
- •19. Записи.
- •19.1 Понятие записи. Объявление записи в программе.
- •19.2 Доступ к полям записи.
- •19.3 Оператор with
- •19.4 Действия над записями
- •19.5 Записи с вариантами
- •Замечание1:Порядок частей – именно такой, как показано: фиксированная часть всегда первая (или единственная)
- •19.6 Типизированные константы - записи
- •20. Модули (Unit)
- •20.1 Что такое модуль?
- •20.2 Зачем нужны модули и какие есть средства, аналогтчные (в какой-то мере) модулям
- •Интерфейсная секция
- •Секция реализации
- •Секция инициализации
- •Подключение других модулей к данному (модулю)
- •20.4 Ссылки на описания модуля
- •Пример создания модуля
- •Использование модулей. Режимы Compile, Build и Make при компиляции модулей
- •Косвенные и перекрестные ссылки на модули
- •Пример модуля (стек)
- •Модули и большие программы
10. Вычисление по формулам (продолжение)
10.6. Уточнение многоместных (n - арных) операций
S =
=x1+x2+x3+...+xn
S
=U1
* U2
* U3
* ... * Un S
=
=
x1∙x2∙x3∙...∙xn
обобщенный
вид
S = XN=
x∙x∙x∙...∙x
n – арной операции N раз
S = X!=1∙2∙3∙4∙...∙X
*
- так обозначается обобщенная
бинарная (двухместная) операция
("+","-",".",":","возведение
в степень"). Исполнитель алгоритма,
на которого ориентирована программа,
к сожалению многоместные операции
выполнять не может (имеет только одно
вычислительное устройство) и поэтому
вычисление многоместных операций
нужно заменять на последовательность
бинарных операций.
Для решения поставленной задачи (замены многоместной операции последовательностью 2-местных) составим соответствующий линейный алгоритм:
S1=U1 Можно заметить, что строки, начиная со второй, можно записать
S2=S1 * U2 в следующей обобщенной форме (на Псевдокоде):
S3=S2 * U3 для i от 2 до n повторить
S4=S3 * U4 Si=Si-1 * Ui - рекуррентная формула (от слова рекурсия)
. . . . . .
Sn=Sn-1 * Un
В этой последовательности начиная со второй строки хорошо видна однотипность вычислений. Поэтому, заметив эту однотипность, попытаемся найти обобщенную запись. Обобщенная запись последовательности шагов, на каждом из которых последующее значение результата получается с использованием предыдущего, называется рекуррентной формулой (от слова рекурсия). Рекурсия в общем случае - это выражение (определение) какого-то понятия самого через себя. В данном случае осуществляется вычисление нового значения переменной S через ее старое значение (i-е промежуточное значение S вычисляется через (i-1)-ое). Если удалось получить такую обобщенную формулу, то это означает, что можно свернуть группу действий (для которой удалось найти обобщенную запись) в цикл (с заранее известным числом повторений). В общем случае цикл будет состоять из трех частей (порядок их важен):
Подготовка
Заголовок
Тело
В тело цикла включается то, что удалось записать в виде рекуррентной формулы, т.е. тело цикла - это те действия, которые надо многократно повторять. Заголовок цикла задает закон изменения т.н. параметра цикла, из которого определяется количество повторения цикла (из приведенного выше заголовка цикла видно, что цикл будет выполняться n-1 раз для i от 2 до n). В подготовку цикла включаются те действия, которые не удалось подвести под рекуррентную формулу. Подготовка цикла настраивает цикл на первое правильное выполнение. На Псевдокоде цикл для выполнения рассмотренной выше последовательности действий имеет вид:
подготовка S1=U1
заголовок Для i от 2 до n повторить
тело цикла Si=Si-1 * Ui
Согласно «Правил разработки циклов» (чуть позже рассмотрим) мы имеем дело с циклом с известным числом повторений, которые разрабатываются в данном случае методом «снизу вверх».
Согласно Правил после получения записи цикла необходимо попытаться выполнить упрощение подготовки цикла. Подготовка бывает простой, если в правой части оператора присваивания используется константа или переменная без индекса.
В данном случае подготовка простой не является, потому что в правой части используется переменная U1 - с индексом. Для упрощения подготовки составляется система уравнений:
- в 1-е уравнение переписывается сам оператор присваивания из подготовки цикла;
- 2-е уравнение получается из рекуррентной (обобщенной) формулы путем подстановки в нее (в левую и правую часть оператора присваивания) нужных значений (тех, которые используются в подготовке) индексов (в данном случае i=1):
S1=U1
S1=S0 * U1
Частные случаи:
- если обобщенная операция "+", то S0=0 ;
- если обобщенная операция "*", то S0=1.
В общем случае присваивание для простой подготовки цикла должно иметь вид: S0=const.
Если попытка упрощения подготовки цикла удалась, то необходимо скорректировать заголовок цикла таким образом, чтобы число повторения цикла увеличилось на единицу. Это нужно сделать потому что в результате упрощения подготовки цикла действия которые ранее выполнялись при подготовке (т.е. вне цикла), теперь включаются в тело цикла и нужно еще один проход тела цикла выполнить, что бы эти действия выполнялись.
В данном случае цикл примет следующий вид:
S0:=const;
Для i от 1 до n повторить
Si:=Si-1 * Ui
Далее согласно теории (См п. «Использование индексов в математике и программах») необходимо исключить лишние индексы. В результате получится следующий вид цикла.
S = const
Для i от 1 до n повторить
S=S * Ui
Часто бывают такие ситуации, когда компоненты многоместных операций представляют из себя не простые выражения (как в рассмотренном выше случае), а достаточно сложные.
Например:
n
S= xi
i=1
В данном случае нужно привести сложную запись каждого операнда многоместной операции к более простой форме , которая была до этого.
n n
S= xi = ui , где ui = xi
i=1 i=1
более простая запись
Далее в дополнение к поиску обобщенной формулы для самой многоместной операции необходимо попытаться найти обобщенную запись для вычисления каждой сложной компоненты многоместной операции вида: Ui = f(Ui-1) . При этом самый простой способ для нахождения нужной формулы – это деление типа
Z=Ui/Ui-1.
Тогда при известном Z можно вычислить Ui через Ui-1:
Ui=Z*Ui-1
Для данного примера такая формула имеет следующий вид: Ui=Ui-1∙x
Замечание: вместо деления аналогичным образом можно выполнить вычитание.
Если попытка нахождения обобщенной записи каждой сложной компоненты многоместной операции удалось, то дальше можно выполнять те же действия, что и для более простого предыдущего случая за одним только исключением: При записи линейного алгоритма (и при записи тела цикла) вместо одного действия у нас на каждом этапе (на каждой итерации) будет два:
вычислить U1=X для шагов, начиная со 2-го можно записать
принять S1=U1 для i от 2 до n повторить
вычислить U2=U1*X нач
принять S2=S1+U2 Ui=Ui-1*X
вычислить U3=U2*X Si=Si-1+Ui
принять S3=S3+U2 кон
............
В подготовке теперь тоже будет не одно действие, а два:
1) Вычислить U1=X
2) Принять S1 = U1
Упростим эту подготовку:
S0 = 0
упрощенная подготовка цикла
U0 = 1
В итоге получим следующий цикл.
S0=0; U0=1
Для i от 1 до n повторить
нач
Ui=Ui-1*X
Si=Si-1+Ui
кон
10.7 Подведение выражения под n-арную операцию (нахождение компактной записи).
Часто встречаются такие случаи, когда необходимо длинную последовательность действий подвести под цикл:
S=1+3/4+4/6+5/8+...=
1 +
Подходов к решения этой задачи много. Самыми простейшими из них являются следующие:
а) поделить все следующие элементы последовательности на предыдущие и попробовать получить геометрическую прогрессию
Например:
S = 1 + ½ + ¼ + 1/8 ++ ...
Возможны два варианта нахождения решения: 1) решение вида ai = f(i), т.е. нахождение формулы для прямого вычисления элементов ряда 2) решение вида ai = f(ai-1), т.е. нахождение формулы для вычисления Текущего значения элемента ряда из предыдущего значения.
Для нахождения обоих видов решения надо составить таблицу:
ai |
½ |
1/4 |
1/8 |
1/16 |
i |
1 |
2 |
3 |
4 |
Из таблицы видно, что обобщенные формулы для двух видов решения имеют вид:
S
= 1 +
или S = 1 +
,
где ai
= ai-1
*(1/2)
обобщенная запись вида ai = f(ai-1)
ai (здесь нужна подготовка цикла: S0 := 1;
a0 := 1)
обобщенная запись вида ai = f(i)
(здесь подготовка цикла не нужна)
б) вычесть из последующих значений ряда предыдущие и попробовать получить арифметическую прогрессию, т.е. представить все последующие элементы как предыдущий плюс некоторую разность
Например:
S
= 1 + 3 + 5 + 7+ 9 + 11 =
Для нахождения обобщенной формулы, как уже говорилось выше, есть 2 пути:
1 путь: угадать обобщенную формулу для прямого (без рекурсии) вычисления каждого элемента последовательности
ui |
1 |
3 |
5 |
7 |
9 |
11 |
i |
1 |
2 |
3 |
4 |
5 |
6 |
Из таблицы видно, что ui = 2*i – 1 (здесь подготовка цикла не нужна)
В итоге получим цикл:
S :=0;
For i:=1 to 6 do
S := S + 2*i – 1
2 путь: угадать рекуррентную формулу для вычисления ui вида: ui = f(ui-1)
ui |
1 |
3 |
5 |
7 |
9 |
11 |
i |
1 |
2 |
3 |
4 |
5 |
6 |
Из таблицы видно, что ui = ui-1 + 2 (для i от 2 до 6)
(здесь подготовка цикла нужна:
u1 = 1; упрощенная подготовка
u1 = u0 +2;
В итоге получим цикл:
S :=0; u :=-1;
for i:=1 to 6 do
begin
u := u + 2;
S := S + u;
end;
в) попытаться подвести под цикл не всю последовательность, а ее часть, например, выкинув (исключив) из анализа первый элемент (мысленно)
Например:
s
= 1+3+5+7+9+11=
= 1+
Выше (в пункте б) мы рассмотрели ситуацию, когда эта последовательность подводилась под цикл с первого элемента. Теперь рассмотрим ситуацию, когда ту же последовательность будем подводить под цикл, начиная со второго элемента (первый уйдет в подготовку цикла):
ui |
3 |
5 |
7 |
9 |
11 |
i |
1 |
2 |
3 |
4 |
5 |
Из таблицы видно, что при прямом вычислении ui = 2i+1 (для i от 1 до 5)
Здесь подготовка цикла нужна только для S (s0 = 1):
В итоге получим цикл:
S :=1;
For i:=1 to 5 do
S := S + 2i+1;
Из той же таблицы видно, что при рекурсивном вычислении ui имеем:
ui = ui-1+2 (для i от 1 до 5)
Здесь подготовка цикла нужна и для S (s0 = 1) и для u:
u1 = 3;
u1 = u0 +2;
В итоге получим цикл:
S :=1; u:=1;
for i:=1 to 5 do
begin
u := u+2;
S := S + u;
end;
г) Если не удается найти обобщенную запись для дробного выражения в целом, надо представить дробь в виде следующей общей записи:
n
S= ai/bi
i=1
После этого отдельно для числителя и знаменателя расписывается последовательность значений. Так для случая
S=1+3/4+4/6+5/8+...
получим:
-
ai
2
3
4
5
6
i
1
2
3
4
5
-
bi
2
4
6
8
10
i
1
2
3
4
5
a1 /b1 = 1
Замечание:
Часто ряд значений бывает знакопеременным, например
S=1
- 3/4+4/6 - 5/8+6/10...=
В этом случае в программе категорически не надо возводить (-1) в степень. Вместо этого надо завести дополнительную переменную a и делать так:
{Подготовка}
a:=1; {Знак a специально подбирается исходя из того, перед каким элементом ряда – четным
или нечетным стоит знак минус}
s:=0;
{Тело цикла}
.....
a := a * (-1); {инвертируем - переключаем знак a при каждом повторении тела}
S := S +((i+1)/(2*i))*a; { меняем знак у слагаемого путем умножения на a}
.....
