НовыеЛекции ОАиП

184
Министерство образования Республики Беларусь Учреждение образования «Белорусский государственный университет информатики и радиоэлек- троники» Кафедра «Вычислительные методы и программирование» Шестакович В. П. Электронный учебно-методический комплекс по дисциплине «ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ» Для студентов специальностей 36 04 01 «Электронно-оптические системы и технологии», 39 02 02 «Проектирование и производство радиоэлектронных средств», 39 02 03 «Медицинская электроника», 39 02 01 «Моделирование и компьютерное проектирование радиоэлек- тронных средств», 39 03 01 «Электронное обеспечение безопасности». Курс лекций Минск 2011

Upload: uladzislau93

Post on 29-Jul-2015

380 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: НовыеЛекции ОАиП

Министерство образования Республики Беларусь

Учреждение образования

«Белорусский государственный университет информатики и радиоэлек-

троники»

Кафедра «Вычислительные методы и программирование»

Шестакович В. П.

Электронный учебно-методический комплекс

по дисциплине

«ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ»

Для студентов специальностей

36 04 01 «Электронно-оптические системы и технологии»,

39 02 02 «Проектирование и производство радиоэлектронных средств»,

39 02 03 «Медицинская электроника»,

39 02 01 «Моделирование и компьютерное проектирование радиоэлек-

тронных средств»,

39 03 01 «Электронное обеспечение безопасности».

Курс лекций

Минск 2011

Page 2: НовыеЛекции ОАиП

2

СОДЕРЖАНИЕ

ТЕМА 1. ОСНОВЫ АЛГОРИТМИЗАЦИИ ................................................... 7

1.1. Понятие алгоритма и способы его записи ...................................... 7

1.2. Программировие в среде Delphi....................................................... 9

1.3. Структура программ Delphi ............................................................11

1.4. Линейные алгоритмы ......................................................................12

1.5. Пример создания программы в среде Delphi ................................14

1.5.1. Настройка формы ...................................................................14

1.5.2. Изменение заголовка формы ...................................................14

1.5.3. Размещение строки ввода (Edit) .............................................14

1.5.4. Размещение надписей (Label) ..................................................15

1.5.5. Размещение многострочного окна вывода (Memo) ..............15

1.5.6. Размещение кнопки Close ........................................................15

1.5.7. Подпрограмма обработки события создания формы .........16

(FormCreate) ........................................................................................16

1.5.8. Подпрограмма обработки события нажатия кнопки

(ButtonClick) ........................................................................................16

1.5.9. Запуск и работа с программой ...............................................16

ТЕМА 2. БАЗОВЫЕ ЭЛЕМЕНТЫ ЯЗЫКА OBJECT PASCAL ...............20

2.1. Алфавит языка Object Pascal ..........................................................20

2.2. Типы данных ....................................................................................20

2.3. Операторы языка Object Pascal ......................................................24

2.3.1. Оператор присваивания ..........................................................24

2.3.2. Составной оператор ...............................................................24

2.4. Операции над переменными и константами ................................24

ТЕМА 3. ПРОГРАМИРОВАНИЕ РАЗВЕТВЛЯЮЩИХСЯ

АЛГОРИТМОВ ...............................................................................................27

3.1. Определение разветвляющегося алгоритма .................................27

3.2. Оператор безусловной передачи управления goto .......................28

3.3. Оператор условного выбора if ........................................................28

3.4. Оператор выбора Case ....................................................................30

3.5. Возможности, предоставляемые средой Delphi для организации

разветвлений ...........................................................................................30

ТЕМА 4. ПРОГРАММИРОВАНИЕ ЦИКЛИЧЕСКИХ АЛГОРИТМОВ .32

4.1. Понятие циклического алгоритма .................................................32

4.2. Оператор цикла с последующей проверкой условия repeat .......32

4.3. Оператор цикла с предварительной проверкой условия while ...33

4.4. Оператор цикла с явно заданныи числом повторений for .........33

4.5. Вложенные циклы ...........................................................................34

4.6. Примеры циклических алгоритмов ...............................................35

ТЕМА 5. ОТЛАДКА ПРОГРАММ И ОБРАБОТКА

ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ ...........................................................37

5.1. Ошибки на этапе компиляции ........................................................37

Page 3: НовыеЛекции ОАиП

3

5.2. Понятие исключительной ситуации ..............................................37

5.3. Защищенные блоки .........................................................................38

5.4. Некоторые стандартные типы исключительных ситуаций.........39

5.5. Инициирование собственных исключительных ситуаций .........40

5.6. Использование функций ShowMessage и MessageDlg ................40

5.7. Пример программы с обработкой исключительных ситуаций ...41

ТЕМА 6. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

МАССИВОВ ...................................................................................................45

6.1. Понятие массива ..............................................................................45

6.2. Некоторые возможности ввода и вывода массивов в Delphi ......46

6.3. Примеры алгоритмов работы с массивами ...................................47

ТЕМА 7. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

УКАЗАТЕЛЕЙ ................................................................................................49

7.1. Статическое и динамическое распределение оперативной

памяти ......................................................................................................49

7.2. Понятие указателя ...........................................................................49

7.3. Динамическое распределение памяти ...........................................50

7.4. Организация динамических массивов ...........................................50

ТЕМА 8. ПОДПРОГРАММЫ И БИБЛИОТЕКИ ........................................53

8.1. Понятие подпрограммы ..................................................................53

8.2. Обмен данными между подпрограммой и программой ..............54

8.3. Оформление подпрограмм в библиотечный модуль ...................55

8.4. Пример создания библиотечного модуля ....................................56

ТЕМА 9. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

МНОЖЕСТВ ...................................................................................................58

9.1. Понятие множества .........................................................................58

9.2. Операции над множествами ...........................................................58

9.3. Пример программы с использованием множеств ........................59

ТЕМА 10. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ СТРОК ..63

10.1. Описание переменных строкового типа .....................................63

10.2. Основные операции над переменными строкового типа ..........63

10.3. Некоторые процедуры и функции обработки строк ..................64

10.4. Примеры алгоритмов обработки строк .......................................65

ТЕМА 11. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ЗАПИСЕЙ

..........................................................................................................................66

11.1. Понятие записи ..............................................................................66

11.2. Операции над записями ................................................................66

ТЕМА 12. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ФАЙЛОВ

..........................................................................................................................68

12.1. Понятие файла ...............................................................................68

12.2. Операции над файлами .................................................................69

12.2.1. Типизированные файлы ..........................................................69

12.2.2. Текстовые файлы ...................................................................70

12.2.3. Нетипизированные файлы ....................................................70

Page 4: НовыеЛекции ОАиП

4

12.3. Подпрограммы работы с файлами ...............................................71

12.4. Компоненты OpenDialog и SaveDialog .......................................71

12.5. Пример программы работы с файлами .......................................72

ТЕМА 13. ПРОГРАММИРОВАНИЕ С ОТОБРАЖЕНИЕМ

ГРАФИЧЕСКОЙ ИНФОРМАЦИИ ..............................................................80

13.1. Как рисуются изображения ..........................................................80

13.2. Построение графиков с помощью компонента Chart ................81

ТЕМА 14. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

РЕКУРСИИ .....................................................................................................86

14.1. Понятие рекурсии ..........................................................................86

15.2. Примеры рекурсивных вычислений ............................................87

ТЕМА 15. ПОИСК И СОРТИРОВКА МАССИВОВ ..................................89

15.1. Организация работы с базами данных ........................................89

15.2. Поиск в массиве записей ..............................................................89

15.3. Сортировка массивов ....................................................................90

15.3.1. Метод пузырька .....................................................................91

15.3.2. Метод прямого выбора .........................................................92

15.3.3. Метод Шелла ..........................................................................92

15.3.4. Метод Хоара (Hoare) .............................................................94

ТЕМА 16. РАБОТА СО СПИСКАМИ НА ОСНОВЕ ДИНАМИЧЕСКИХ

МАССИВОВ ...................................................................................................95

16.1. Работа со списками .......................................................................95

16.2. Добавление элемента в список на заданную позицию ..............95

16.3. Удаления элемента с заданным номером ..................................96

16.4. Пример программы .......................................................................96

ТЕМА 17. СВЯЗАННЫЕ СПИСКИ НА ОСНОВЕ РЕКУРСИВНЫХ

ДАННЫХ .......................................................................................................101

17.1. Определение стека и очереди ....................................................101

17.2. Понятие рекурсивных данных и односвязных списков ..........101

17.3. Процедуры для работы со стеками ............................................104

17.4. Процедуры для работы с односвязными очередями ...............107

17.5. Пример программы по созданию стека .....................................110

17.6. Работа с двухсвязными очередями ............................................114

17.7. Процедуры для работы с двусвязными очередями ..................116

17.8. Пример пограммы по работе с двухсвязным списком ............120

ТЕМА 18. АЛГОРИТМЫ РЕШЕНИЯ СИСТЕМ ЛИНЕЙНЫХ

АЛГЕБРАИЧЕСКИХ РЕШЕНИЙ ..............................................................125

18.1. Основные понятия и определения .............................................125

18.2. Прямые методы решения СЛАУ ................................................127

18.2.1. Метод Гаусса .......................................................................127

18.2.2. Метод прогонки....................................................................128

18.2.3. Метод квадратного корня ..................................................129

18.3. Итерационные методы решения СЛАУ ....................................130

18.3.1. Метод простой итерации...................................................130

Page 5: НовыеЛекции ОАиП

5

18.3.2. Метод Зейделя ......................................................................130

18.3.3. Понятие релаксации ............................................................131

18.4. Нахождение обратных матриц ...................................................131

ТЕМА 19. СОБСТВЕННЫЕ ЗНАЧЕНИЯ И СОБСТВЕННЫЕ ВЕКТОРЫ

МАТРИЦЫ ....................................................................................................133

19.1. Интерполяционный метод ..........................................................133

19.2. Метод вращений Якоби ..............................................................134

19.3. Итерационный метод ..................................................................135

ТЕМА 20. АППРОКСИМАЦИЯ ФУНКЦИЙ ............................................136

20.1. Определение аппроксимации .....................................................136

20.2. Интерполяция ..............................................................................137

20.3. Многочлены и способы интерполяции .....................................139

20.3.1. Интерполяционный многочлен Ньютона ..........................139

20.3.2. Линейная и квадратичная интерполяции ..........................139

20.3.3. Интерполяционный многочлен Лагранжа ........................140

20.3.4. Интерполяция общего вида .................................................140

20.4. Среднеквадратичная аппроксимация ........................................140

20.4.1. Метод наименьших квадратов ...........................................141

ТЕМА 21. ВЫЧИСЛЕНИЕ ПРОИЗВОДНЫХ ИНТЕГРАЛОВ ...............143

21.1. Формулы численного дифференцирования ..............................143

21.2. Формулы численного интегрирования......................................144

21.2.1. Формула средних ..................................................................144

21.2.2. Формула трапеций ...............................................................145

21.2.3. Формула Симпсона ...............................................................145

21.2.4. Формулы Гаусса ...................................................................145

ТЕМА 22. МЕТОДЫ РЕШЕНИЯ НЕЛИНЕЙНЫХ УРАВНЕНИЙ ........147

22.1. Как решаются нелинейные уравнения ......................................147

22.2. Итерационные методы уточнения корней ................................148

22.2.1. Метод простой итерации...................................................148

22.2.2. Метод Ньютона ...................................................................148

22.2.3. Метод секущих .....................................................................149

22.2.4. Метод Вегстейна .................................................................150

22.2.5. Метод парабол .....................................................................150

22.2.6. Метод деления отрезка пополам .......................................150

ТЕМА 23. РЕШЕНИЕ ОБЫКНОВЕННЫХ ДИФФЕРЕНЦИАЛЬНЫХ

УРАВНЕНИЙ ................................................................................................152

23.1. Задачи для обыкновенных дифференциальных уравнений ....152

23.2. Основные положения метода сеток для решения задачи Коши

................................................................................................................153

23.2.1. Явная схема 1-го порядка (метод Эйлера) ........................154

23.2.2. Неявная схема 1-го порядка ................................................154

23.2.3. Неявная схема 2-го порядка ................................................155

23.2.4. Схема Рунге – Кутта 2-го порядка ....................................155

23.2.5. Схема Рунге – Кутта 4-го порядка ....................................155

Page 6: НовыеЛекции ОАиП

6

23.3. Многошаговые схемы Адамса ...................................................156

23.3.1. Явная экстраполяционная схема Адамса 2-го порядка ...157

23.3.2. Явная экстраполяционная схема Адамса 3-го порядка ...157

23.3.3. Неявная схема Адамса 3-го порядка ..................................158

23.4. Краевая (граничная) задача ........................................................158

23.5. Численные методы решения краевых задач .............................159

23.5.1. Метод стрельбы ..................................................................159

23.5.2. Метод конечных разностей ................................................160

ТЕМА 24. МЕТОДЫ ОПТИМИЗАЦИИ ....................................................162

24.1. Постановка задач оптимизации, их классификация ................162

24.2. Методы нахождения минимума функции одной переменной 163

24.2.1. Метод деления отрезка пополам .......................................164

24.2.2. Метод золотого сечения .....................................................164

24.2.3. Метод Фибоначчи ................................................................165

24.2.4. Метод последовательного перебора .................................166

24.2.5. Метод квадратичной параболы .........................................167

24.2.6. Метод кубической параболы ..............................................168

24.3. Методы нахождения безусловного минимума функции

нескольких переменных .......................................................................169

24.3.1. Классификация методов .....................................................169

24.4. Методы нулевого порядка ..........................................................170

24.4.1. Метод покоординатного спуска ........................................170

24.4.2. Метод Хука – Дживса .........................................................171

24.4.3. Метод Нелдера – Мида .......................................................171

24.5. Методы первого порядка ............................................................174

24.5.1. Метод наискорейшего спуска .............................................174

24.5.2. Метод сопряженных градиентов Флетчера – Ривса ......174

24.6. Методы второго порядка ............................................................175

24.6.1. Обобщенный метод Ньютона – Рафсона .........................175

24.7. Методы переменной метрики ....................................................176

24.7.1. Метод Дэвидона – Флэтчера – Пауэлла ...........................176

24.8. Методы условной минимизации функций ................................177

24.8.1. Метод штрафных функций ................................................177

ПРИЛОЖЕНИЕ 1. Процедуры и функции для преобразования

строкового представления чисел ................................................................179

ПРИЛОЖЕНИЕ 2. Математические формулы ..........................................181

ПРИЛОЖЕНИЕ 3. Таблицы символов ASCII ...........................................182

ЛИТЕРАТУРА ..............................................................................................184

Page 7: НовыеЛекции ОАиП

7

ТЕМА 1. ОСНОВЫ АЛГОРИТМИЗАЦИИ

1.1. Понятие алгоритма и способы его записи

Программирование – это процесс создания программы, состоящий из

следующих этапов:

1. Формулирование требований к программе.

2. Разработка алгоритма.

3. Запись алгоритма на языке программирования.

4. Отладка программы.

5. Тестирование программы.

Алгоритмом называется последовательность действий, приводящая к

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

блок-схема или словесное описание алгоритма. При изображении блок-схемы

могут использоваться следующие основные графические элементы:

Page 8: НовыеЛекции ОАиП

8

Начало «Оконечная фигура» (начало и конец алгоритма)

Ввод

x,y«Данные» (Ввод и вывод информации)

«Процесс» (Линейный блок)w=x+sin(y)

x>2

Да

Нет

«Решение» (Разветвление алгоритма)

k=1,n

Тело цикла

Выход

«Подготовка» (Организация цикла)

Уточнение

корня

«Заранее определенный процесс» (Отдельно описанный

алгоритм)

Рис. 1.1. Графические элементы алгоритма

Отладка – это процесс поиска и исправления ошибок. Ошибки в про-

грамме разделяются на синтаксические (ошибки в тексте программы) и алго-

ритмические. Синтаксические ошибки выявляет транслятор программы на

этапе компиляции (преобразовании операторов программы в набор машин-

ных команд). Алгоритмические ошибки выявляются на этапе тестирования

(прогонке программы при наборе входных данных с заведомо известным ре-

зультатом).

Page 9: НовыеЛекции ОАиП

9

1.2. Программирование в среде Delphi

Выполняемая компьютером программа является набором команд над

содержимым ячеек памяти. Составление программы в машинных командах

является крайне неудобным и сложным процессом. Поэтому часть работы по

составлению программы была предоставлена компьютеру. Были созданы

языки программирования, которые сейчас принято называть языками высо-

кого уровня, при использовании которых алгоритм записывается с помощью

небольшого числа операторов соответствующего языка, после чего програм-

ма проходит процесс так называемой компиляции, при которой компьютер

проверяет правильность записи каждого оператора, а затем преобразует опе-

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

обходимых стандартных библиотек (компоновка) и создание выполняемого

файла (файл с расширением *.exe). Полученная программа в машинных кодах

может быть записана на диск и при ее многократном выполнении уже не тре-

буются этапы компиляции и компоновки.

Delphi – это среда визуального программирования на основе языка Ob-

ject Pascal. Этот язык программирования был создан Никлаусом Виртом, ди-

ректором института информатики Швейцарской высшей политехнической

школы в 1970 году специально как язык обучения программированию. Его

отличает строгость в определении переменных и констант, модульность про-

граммирования, широкие возможности в создании собственных структур

данных, использование объектно-ориентированного программирования. Кор-

порация Borland сделавшая ставку на визуальное объектно-ориентированное

программирование с предоставлением возможности работы с любыми базами

данных создала среду программирования Delphi по своим возможностям не

уступающую таким средам программирования как С++, Visual C++, C–

Builder, Visual Basic и др., а по удобству языка и простоте обучения Delphi

значительно привлекательнее. Система Delphi реализует технологию объ-

ектно-ориентированного визуального программирования (ООП). В ООП

главным элементом является объект. Объектно-ориентированная программа –

это совокупность объектов и способов их взаимодействия. Пользователь про-

граммы является главным (управляющим) объектом. Обмен между объектами

происходит посредством сообщений. Пользователь посылает свои сообщения

посредством определенных действий на панели программы. Когда сообщение

поступило некоторому объекту (произошло определенное событие), он начи-

нает выполнять свои определенные действия и сообщает результаты пользо-

вателю визуально через окна на панели программы. Объект представляет со-

бой объединение под одним именем (именем объекта) данных и методов ра-

боты с ними. Данные обьекта, определяющие вид, положение и поведение

обьекта называются свойствами обьекта. Процедуры и функции обьекта

предназначенные для работы с этими данными называются методами. Вы-

зов метода производится указанием имени объекта и через точку имени мето-

да, например, Memo.Clear.

Page 10: НовыеЛекции ОАиП

10

Программная среда разработки Delphi состоит из нескольких одновре-

менно открытых окон – главного окна, окна инспектора объектов, окна фор-

мы, окна текста программы и окна списка обьектов. На рис. 1.2 представлена

среда разработки Borland Delphi 7.0.

Рис. 1.2. — Программная среда Borland Delphi 7.0

1 – главное окно; 2 – основное меню; 3 – пиктограммы основного меню;

4 – окно списка обьектов; 5 - окно инспектора объектов; 6 – меню обьектов;

7 – окно редактора текста программ; 8 - окно формы;

Главное окно необходимо для управления процессом создания про-

граммы. Основное меню содержит все необходимые средства для управления

проектом. Пиктограммы облегчают доступ к наиболее часто применяемым

командам основного меню. Через меню объектов (компонентов) осуществля-

ется доступ к набору стандартных сервисных программ среды Delphi, кото-

рые описывают некоторый визуальный элемент (компонент), помещаемый

разработчиком программы в окно формы. Каждый компонент имеет опреде-

ленный набор свойств (параметров), которые разработчик может задавать,

например цвет, заголовок окна, надпись на кнопке, размер и тип шрифта и др.

Окно инспектора объектов (вызывается c помощью клавиши F11)

предназначено для изменения свойств выбранных компонентов и содержит

две вкладки. Вкладка Properties (Свойства) предназначена для изменения

свойств компонента, на вкладке Events (События) перечислены события, на

Page 11: НовыеЛекции ОАиП

11

которые может реагировать обьект (например, нажатие определенной клави-

ши или щелчок «мышью» по кнопке).

Окно формы представляет собой визуальную оболочку программы. В

это окно в процессе разработки программы помещаются визуальные и неви-

димые компоненты.

Окно текста программы предназначено для просмотра, написания и

редактирования текста программы. При создании программы первоначально

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

рования пустого проекта Windows-окна. При размещении компонента в окно

формы, текст программы автоматически дополняется описанием необходи-

мых для его работы библиотек стандартных программ (раздел uses) и типов

переменных (раздел type) (см. Листинг 1.1).

Программа в среде Delphi является набором алгоритмов, которые будут

выполняться при возникновении того или иного события (например, щелчок

мыши на кнопке – событие OnClick, создание формы – OnCreate). Для каждо-

го обрабатываемого события, с помощью вкладки Events инспектора объектов

в тексте программы организуется процедура (procedure), между ключевыми

словами begin и end которой разработчик записывает на языке Object Pascal

требуемый алгоритм.

Переключение между окном формы и окном текста программы осуще-

ствляется с помощью клавиши F12.

1.3. Структура программ Delphi

Приложение в среде Delphi состоит из файлов с исходным текстом

программы (*.pas), файла формы (*.dfm) содержащем описание формы и ее

компанентов, файла проекта (*.dpr), который связывает вместе все файлы

проекта, ресурсного файла (*.res), содержашего значки, картинки, меню, ко-

торые будут помещаться в форму, файла настроек проекта (*.dof), файла

(*.dcu), содержащего результат компиляции файла с расширением (*.pas) и

файла, содержащего единый исполняемый файл (*.exe).

В файле проекта находится информация о модулях, составляющих

данный проект. Файл проекта автоматически создается и редактируется сре-

дой Delphi и не предназначен для редактирования.

Файл исходного текста – программный модуль (Unit) предназначен

для размещения текстов программ. В этом файле разработчик размещает

текст программы, написанный на языке Object Pascal.

Модуль имеет следующую структуру:

unit Unit1;

interface

// Раздел объявлений

implementation

// Раздел реализации

begin

Page 12: НовыеЛекции ОАиП

12

// Раздел инициализации

end.

В разделе объявлений описываются типы, константы, переменные, заго-

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

лями после подключения библиотек (Uses). В разделе реализации располагают-

ся тела процедур и функций, описанных в разделе объявлений, а также типы,

константы, переменные, процедуры и функции, которые будут функциониро-

вать только в пределах данного модуля. Раздел инициализации используется

редко и его описание можно пропустить.

При компиляции программы Delphi создает файл с расширением dcu,

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

с расширениями pas и dfm. Компоновщик преобразует файлы с расширением

dcu в единый исполняемый файл с расширением exe. В файлах, имеющих

расширения ~df, ~dp, ~pa, хранятся резервные копии файлов формы, проекта

и исходного текста соответственно.

При сохранении проекта необходимо создать отдельную папку с име-

нем проекта в которую следует поместить файлы проекта (достаточно сохра-

нять только файлы с расширениями *.dpr, *.pas, *.dfm, *.res. Остальные фай-

лы являются рабочими и их можно не сохранять).

1.4. Линейные алгоритмы

Линейными называются алгоритмы, в которых независимо от входных

данных и результатов промежуточных расчетов всегда выполняется одна и та

же последовательность действий.

Например требуется организовать расчет некоторого арифметического

выражения при различных исходных данных. 3 2

2 | |( ) *

( ) ln( )

ye xu tg x y

arctg z x, где x, y, z – действительные числа.

Разработка алгоритма обычно начинается с построения блок-схемы. Проду-

мывается оптимальная стратегия вычислений, при которой, например, отсут-

ствуют повторения. При написании алгоритма рекомендуется также перемен-

ным присваивать по возможности те же имена, которые фигурируют в задан-

ном арифметическом выражении. Для того, чтобы не было «длинных» опера-

торов исходное выражение полезно разбить на ряд более простых. В нашем

случае предлагается схема вычислений, представленная на рис. 1.3.

Page 13: НовыеЛекции ОАиП

13

Начало

Ввод

x,y,z

a=tg2(x+y)

b=|e3y

-x2|

s=a*b/c

Вывод

x,y,z,s

Конец

( ) ln( )c arctg z x

Рис. 1.3. Схема линейного алгоритма

Она содержит ввод исходных данных, линейный вычислительный про-

цесс и вывод полученного результата и исходных данных. Введя переменные

a,b,c мы разбили сложное выражение на ряд простых. В Delphi чаще всего

ввод или вывод небольшого количества данных производят из так называе-

мых окон однострочных редакторов (компонент Edit) или табличных строч-

ных редакторов (компонент StringGrid). Вывод большого числа данных

обычно осуществляется в окно многострочного редактора (компонент Memo).

Окна этих редакторов и пояснения к ним размещаются на форме по усмотре-

нию программиста. В окна строчных редакторов может помещаться любой

набор символов, в частности запись чисел, которые необходимо ввести или

вывести. Для того, чтобы, например, в окне редактора Edit1 было помещено

число 28.64 в программе достаточно написать оператор Edit1.Text:=’28,64’.

Для вывода результатов можно поместить на форму окно многострочного ре-

дактора Memo1. Окно многострочного редактора в данном случае предназна-

чено для вывода результатов и представляет собой отображение в окне по-

следовательности строк. Новая строка добавляется в окно с помощью опера-

тора Memo1.Lines.Add(’новая строка’). Если нужно вывести содержимое

вещественных или целых переменных их необходимо предварительно преоб-

разовать в строковое представление. Для этого используются функции Float-

ToStrF(х,fffixed,6,2) – преобразование вещественного числа x в строку из 6

Page 14: НовыеЛекции ОАиП

14

символов с двумя цифрами после запятой и IntToStr(m) – преобразование це-

лого числа m в строку.

1.5. Пример создания программы в среде Delphi

Задание: составить программу вычисления для заданных значений x, y,

z арифметического выражения 3 2

2 | |( ) *

( ) ln( )

ye xu tg x y

arctg z x.

Панель диалога программы организовать в виде, представленном на рис. 1.4.

1.5.1. Настройка формы

Для создания нового проекта в основном меню выбирается пункт

File–>New–>Application. Пустая форма в правом верхнем углу имеет кнопки

управления, которые предназначены: для сворачивания окна , для развора-

чивания окна на весь экран , возвращения к исходному размеру и для за-

крытия окна . С помощью мыши, «захватывая» одну из кромок формы или

выделенную строку заголовка регулируются нужные размеры формы и ее по-

ложение на экране.

1.5.2. Изменение заголовка формы

Новая форма имеет одинаковое имя (свойство Name) и заголовок (свойст-

во Caption) – Form1. Для изменения заголовка активируется форма щелчком

мыши на форме и на вкладке Properties инспектора объектов в правой ячейке от

свойства Caption вводится новый заголовок окна, например «Моя первая про-

грамма».

1.5.3. Размещение строки ввода (Edit)

Для ввода данных, а так же вывода информации, которая вмещается в

одну строку, используется компонент Edit. Доступ к отображаемой в окне

информации в виде строки символов (тип данных String) осуществляется с

помощью свойства Text. В составляемой ниже программе с помощью компо-

нентов Edit будут вводиться значения переменных x, y, z (см. рис. 1.4). Для

этого необходимо сначало щелкнуть мышью по пиктограмме в меню

компонентов Standard а затем в том месте формы, где необходимо размес-

тить компонент. После рамещения на форме трех компонентов Edit, в тексте

программы (см. Листинг 1.1) появится три новых переменных – Edit1, Edit2,

Edit3. Последовательно выделяя компоненты, можно регулировать их разме-

ры и положение. С помощью инспектора объектов устанавливаются шрифт,

размер и цвет символов отражаемых в окне Edit (свойство Font). В свойстве

Text инспектора объектов можно задать начальные значения переменных x, y,

z.

Page 15: НовыеЛекции ОАиП

15

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

численные значения переменных x, y, z имеют действительный тип, а компо-

нент Edit в свойстве Text содержит отображаемую в окне строку символов.

Для преобразования строковой записи числа, находящегося в свойстве

Edit.Text, в действительное его представление, используется стандартная

функция StrToFloat, например x:=StrToFloat(Edit1.Text). Для перевода строки

в целочисленный тип данных используется функция StrToInt. При этом в за-

писи числа не должно быть пробелов, а целая и дробная часть действительно-

го числа разделяется символом, заданным в разделе «Языки и стандарты» па-

нели управления Windows (по умолчанию – запятой). Некоторые процедуры и

функции для преобразования строк приведены в Приложении 1 и в теме 7.

1.5.4. Размещение надписей (Label)

На рис. 1.4 на форме имеются четыре пояснительные надписи. Для на-

несения таких надписей на форму используется компонент Label. (пикто-

грамма в меню компонентов Standard). Отображаемая информация дан-

ного компонента содержится в свойстве Caption (заголовок).

1.5.5. Размещение многострочного окна вывода (Memo)

Для вывода нескольких строк на экран можно использовать компонент

Memo (пиктограмма в меню компонентов Standard). Для отображения

вертикальной и горизонтальной полос прокрутки в данном компоненте, во

вкладке Properties инспектора объектов необходимо установить свойство

ScrollBars в положение SSBoth. Информация, которая отображается построч-

но в окне Memo, находится в свойстве Memo.Lines. Новая строка добавляется

методом Memo.Lines.Add(). Для очистки окна во время выполнения програм-

мы используется метод Memo.Clear. Если в окно Memo выводятся данные,

находящееся в переменных действительного или целого типа, то их необхо-

димо предварительно преобразовать к типу String: для действительных чисел

– FloatToStr() или FloatToStrF(), для целых – IntToStr(). Например, для пере-

менной целого типа n:=100 – Memo1.Lines.Add(‘Значение n=’+IntToStr(n)),

для переменной действительного типа x:=-256,38666 –

Memo1.Lines.Add(‘Значение x=’+FloatToStrF(x,fffixed,8,2)). В данном случае

параметр fffixed отвечает за вывод числа с фиксированной точкой, 8 – за об-

щее количество выводимых цифр, 2 – количество цифр после запятой (дроб-

ная часть).

1.5.6. Размещение кнопки Close

Для окончания работы программы лучше использовать не стандартную

кнопку для закрытия окна , а компонент TBitBtn расположенный в меню

компонентов Additional и представляющий собой разновидность стандартной

кнопки TButton. Его отличительная особенность – наличие растрового изо-

Page 16: НовыеЛекции ОАиП

16

бражения на поверхности кнопки, которое определяется свойством Clyph.

Кроме того, имеется свойство Kind, которое задает одну из 11 стандартных

разновидностей кнопок. Кнопка bkClose закрывает главное окно и завершает

работу программы.

1.5.7. Подпрограмма обработки события создания формы

(FormCreate)

После запуска программы, на этапе ее выполнения, происходит соз-

дание спроектированной формы (событие OnCreate). Создадим подпро-

грамму – обработчик этого события (TForm1.FormCreate). После запуска

программы она будет очищать окно Memo1. Для этого необходимо дваж-

ды щелкнуть мышью на любом свободном месте формы. На экране поя-

вится текст, в котором автоматически внесен заголовок процедуры – об-

работчика события создания формы: Procedure

TForm1.FormCreate(Sender:TObject). Между begin … end вставляется

текст программы (смотрите пример, расположенный ниже).

1.5.8. Подпрограмма обработки события нажатия кнопки (ButtonClick)

Поместить на форму кнопку (компонент Button), для чего необходимо

выбрать в меню компонентов Standart пиктограмму . Для изменения над-

писи на кнопке можно использовать свойство Caption. После этого два раза

щелкнуть мышью по кнопке. В тексте программы появится текст процедуры

обработчика события «щелчок мышью на кнопке»

Procedure TForm1.ButtonClick(Sender:TObject);

Begin

End;

Набрать текст этой процедуры (см. Листинг 1).

Внимание! Заголовки процедур ButtonClick и FormCreate создаются средой

Delphi автоматически (если набрать их вручную – программа работать не

будет). При запуске программы на выполнение все процедуры обработки со-

бытий, у которых между begin и еnd ничего не было удаляются автомати-

чески по соответствующему запросу среды Delphi. Поэтому нет необходи-

мости вручную удалять ошибочно созданные обработчики.

Разместить на форме собственную кнопку для окончания работы, по-

местив из меню компонентов Additional компанент BitBtn. Выбрать в инспек-

торе объектов для этого компонента в свойстве Kind значение Close.

1.5.9. Запуск и работа с программой

Запустить программу можно, выбрав в главном меню пункт Run – >Run

или нажав клавишу F9, или щелкнув мышью по пиктограмме . При этом

Page 17: НовыеЛекции ОАиП

17

происходит компиляция программы и, если нет ошибок, компоновка про-

граммы и создание исполняемого файла с расширением exe. На экране появ-

ляется активная форма программы (рис. 1.4).

Рис. 1.4. Изображение формы выполняемой программы

Дальнейшая работа с программой осуществляется следующим образом. В со-

ответствующих окнах задаются значения переменных x, y, z. Производится

щелчок мышью по кнопке «Вычислить». В окне Memo1 появляется резуль-

тат. При изменении значений x, y, z в окнах и вторичных нажатиях кнопки

«Вычислить» в окно Memo1 будут добавляться новые результаты. Завершить

работу программы можно или нажав кнопку на форме или кнопку «Close»

или, выбрав в главном меню Delphi пункт Run –> Program Reset. Последний

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

В Листинге 1.1 представлен текст программы. Для наглядности, опера-

торы, которые следует набрать разработчику выделены полужирным курсив-

ным шрифтом, остальные операторы вставляются средой Delphi автоматиче-

ски.

Листинг 1.1. unit Unit1;

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,

Controls,Forms,Dialogs,Buttons,StdCtrls;

type

Page 18: НовыеЛекции ОАиП

18

TForm1 = class(TForm)

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Memo1: TMemo;

Button1: TButton;

BitBtn1: TBitBtn;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

Memo1.Clear; // Очистка окна

end;

procedure TForm1.Button1Click(Sender: TObject);

var x,y,z,a,b,c,s:extended;

begin

x:=StrToFloat(Edit1.text);

y:=StrToFloat(Edit2.text);

z:=StrToFloat(Edit3.text);

a:=sqr(sin(x+y)/cos(x+y));

b:=abs(exp(3*y)-x*x);

c:=sqrt(arctan(z)+ln(x));

s:=a*b/c;

// Вывод исходных данных и результата в окно memo1

Memo1.Lines.Add('x='+Edit1.Text+

' y='+Edit2.Text+' z='+Edit3.Text+

Page 19: НовыеЛекции ОАиП

19

' Результат = '+FloatToStrF(s,fffixed,9,4));

end;

end.

Page 20: НовыеЛекции ОАиП

20

ТЕМА 2. БАЗОВЫЕ ЭЛЕМЕНТЫ ЯЗЫКА OBJECT PASCAL

2.1. Алфавит языка Object Pascal

Алфавит языка Object Pascal оперирует следующим набором симво-

лов:

1) прописные и строчные буквы латинского алфавита

A, B, C, D,...,U, V, W, X, Y, Z;

a, b, c, d,...,u, v, w, x, y, z;

2) десятичные арабские цифры от 0 до 9;

3) _ – символ «подчеркивание»,

4) специальные символы

+ плюс {} фиг. скобки : двоеточие

- минус [ ] кв. скобки ; точка с запятой

* звездочка ( ) круг. скобки ' апостроф

/ дробная черта # номер @ коммерческое а

= равно пробел $ знак ден.единицы

> больше . точка ^ каре

< меньше , запятая

Комбинации специальных символов могут образовывать составные

символы:

:= – присваивание

.. – диапазон значений

<= – меньше или равно

>= – больше или равно

< > – не равно

(. .) – альтернатива квадратных скобок

(* *) – альтернатива фигурных скобок

5) ключевые (зарезервированные) слова. Например, Begin, End;

6) стандартные идентификаторы. Например, Sin, Cos;

7) идентификаторы пользователя.

2.2. Типы данных

Величины, с которыми должна работать программа принято называть

данными. Все данные при работе программы размещаются в различные ячей-

ки памяти, им присваиваются оригинальные имена (идентификаторы) и ука-

зываются их типы. Идентификаторы образуются из латинских букв, симво-

ла _ и арабских цифр и могут иметь произвольную длину до 127 символов, но

значимыми будут только первые 63 символа. Первым символом должна быть

буква или символ _. Пробелы, точки и другие специальные символы не могут

Page 21: НовыеЛекции ОАиП

21

входить в имя. Данные могут быть константами и переменными. Кон-

станты – это те данные, значения которых известны заранее и в процессе

выполнения программы не изменяются. В качестве констант в Object Pascal

могут использоваться целые, вещественные и шестнадцатеричные числа, ло-

гические константы, символы, строки символов, конструкторы множеств и

признак неопределенного указателя nil. Целые константы – это целые числа

со знаком или без в диапазоне от –263

до 263

-1.

Например, 286; -17; +1995

Можно использовать целую константу в шестнадцатеричном виде.

Шестнадцатеричное число состоит из шестнадцатеричных символов ( 0, 1, 2,

3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F ), которым предшествует знак доллара $ ( код

символа 36 )

Например, $3A4F; $100A

Вещественные константы могут быть представлены в двух видах: с

фиксированной и плавающей точкой. Константа с фиксированной точкой –

это число, содержащее точку, разделяющую целую и дробную часть (наличие

целой и дробной части обязательно).

Например, -39.013; 0.256

Константа с плавающей точкой – это число, представленное с десятичным

порядком: в виде mEp, где m – мантисса (как целые, так и вещественные

числа с фиксированной точкой), E или e – признак записи числа с десятичным

порядком, p – порядок числа (только целые числа).

Например, -7.78Е-3; -13e6; 4.9e5

Логические константы могут принимать только одно из двух значений: True

(истина) и False (ложь). Символьная константа – это любой символ,

заключенный в апострофы. Допускается использование записи символа путем

указания его внутреннего кода, которому предшествует символ #.

Например, ‘w’; ‘ф’; #53

Строковые константы – это последовательность символов, заключенная в

апострофы.

Например, 'БГУИР'; #75#58#93

Конструктор множества – это список элементов множества, обрамленный

квадратными скобками.

Например, [ 43, 76, 12, 90 ]; [ red, blue, green ]

Константы могут иметь свои собственные имена. Этот вариант

предпочтительней при многократном использовании константы. Форма

описания констант:

Const <идентификатор> = <значение константы>;

Например Const Min = 1; // Описание констант

Max = 150;

A=’Таблица’;

Page 22: НовыеЛекции ОАиП

22

Переменная – это именованный участок оперативной памяти, который в

процессе выполнения программы может принимать различные значения.

Форма описания переменных:

Var <идентификатор 1, ... > : тип;

Например, Var a, b: integer:

sum, min :extended;

c: Char;

Тип переменных определяет, какие значения они могут иметь, какая структу-

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

выполнять. В Object Pascal имеется развитая система типов данных. Их мож-

но разделить на две группы: скалярные (простые) и структурированные (со-

ставные). К скалярному типу относятся данные, представляемые одним зна-

чением (числом, символом) и размещаемые в одной ячейке из нескольких

байтов. Структурированные типы определяются пользователем через ска-

лярные и описанные ранее структурированные с помощью оператора Type

следующим образом

Type <Тип> = <определение типа>;

В языке Object Pascal имеется 7 скалярных типов (целочисленные, вещест-

венные, логические (булевские), символьные, перечисляемые, интервальные,

дата-время) и 10 основных структурированных типов (строки, массивы, мно-

жества, записи, файлы, указатели, процедуры, объекты, варианты, классы). В

Object Pascal предусмотрено создания программистом новых типов данных,

поэтому общее количество типов, использующихся в программе, может быть

сколь угодно большим. Характеристики двух основных скалярных типов

представлены в следующих таблицах.

Целые типы. Табл. 2.1.

Unsigned (Беззнаковые) Signed (Знаковые)

Тип J Объем Диапазон Тип Объем Диапазон

Byte 1 0 .. 255 ShortInt 1 -128 .. 127

Word 2 0 .. 65 535 SmallInt 2 -32 768 .. 32 767

Long,

Cardinal

4 0 .. 4 294 967 295 Integer,

LongInt

4 -2 147 483 648 ..

2 147 483 647

Int64 8 -263

.. 263

-1

Вещественные типы Табл. 2.2.

Тип Размер Значащих цифр Диапазон

Single 4 7..8 1,5*10-45

.. 3,4*1038

Real, Double 8 15 .. 16 5*10-324

.. 1,7*10308

Extended 10 19 .. 20 3,4*10-4951

.. 1,1*104932

Comp 8 19 .. 20 -263

.. 263

-1

Currency 8 19 .. 20 ±922 337 203 685 477, 5807

Page 23: НовыеЛекции ОАиП

23

Для экономии памяти следует пользоваться более «короткими» типами, a для

повышения точности более «длинными». Следует помнить, что арифметиче-

ский сопроцессор всегда обрабатывает числа в формате Extended, а три дру-

гих вещественных типа (Double, Real, Single) получаются простым усечением

результата до нужных размеров и применяются, как правило, для экономии

памяти. Следует так же учесть что тип Real оптимизирован для работы без

сопроцессоров, однако его использование на ПК с сопроцессором приводит к

дополнительным затратам (в 2 – 5 раз) времени на преобразование формата.

Если ваш компьютер оснащен сопроцессором, то не рекомендуется использо-

вать тип Real. Из логических типов наиболее часто используется тип Boolean

(1 байт), другие логические типы ByteBool (1 байт), Bool (2 байта), WordBool

(2 байта) и LongBool (4 байта) введены для совместимости с Windows.

Пользовательские типы переменных

К ним относятся переменные перечисляемого и интервального типов.

Переменная типа перечисление задается перечислением значений, которые

она может принимать. Форма описания этих переменных:

Type <имя типа> = (список значений);

Var <идентификатор 1,...> : <имя типа>;

или Var <идентификатор 1,...>: (список значений);

Например Type elem = (Fe, Cu, Na, Zn, Be);

Var a, b : elem;

или Var a, b : (Fe, Cu, Na, Zn, Be);

Здесь a, b – переменные типа перечисление, которые могут принимать любое

из заданных значений. Следует отметить, что описание типа перечисляемой

переменной одновременно вводит упорядочение ее значений. Так, для

данного примера Fe < Cu < Na < Zn < Be (в операциях сравнения). Для

переменных интервального типа указывается некоторое подмножество

значений, которые они могут принимать. Форма описания этих переменных:

Type <имя типа> = <константа 1>..<константа 2>;

Var <идентификатор 1, ... > : <имя типа>;

или Var <идентификатор 1, ... > : <константа 1> .. <константа 2>;

где <константа 1>, <константа 2> – соответственно константы,

определяющие нижнюю и верхнюю границы значений, которые может

принимать интервальная переменная. Значение первой константы должно

быть обязательно меньше значения второй. Эти константы могут быть

целого, символьного или перечисляемого типов.

Например Type Dni = 1..31;

Var x, y : Dni;

В этом примере переменные x и y имеют тип Dni и могут принимать любые

значения из диапазона 1..31. Выход из диапазона вызывает программное

прерывание. Можно определять интервальный тип и более универсальным

способом, задав границы диапазона не значениями констант, а их именами.

Page 24: НовыеЛекции ОАиП

24

Например Const Min=1; Max=31;

Type Dni = Min..Max;

Var x, y : Dni;

2.3. Операторы языка Object Pascal

Во всех языках фундаментальным понятием является оператор, кото-

рый представляет описание определенного набора действий компьютера.

Программа, написанная на языке программирования, состоит из последова-

тельности операторов.

2.3.1. Оператор присваивания

Одним из самых распространенных операторов является оператор при-

сваивания форма записи которого имеет вид:

<имя переменной>:=<выражение>;

где составной символ := (записывается без пробелов) означает «присвоить».

Результатом выполнения оператора является присваивание переменной, имя

которой записано слева результата вычисления <выражения>. Оператор за-

канчивается точкой с запятой.

2.3.2. Составной оператор

Группа операторов взятая в операторные скобки begin и end воспринима-

ется компьютером как один оператор (составной оператор).

2.4. Операции над переменными и константами

Арифметические выражения

Арифметические выражения строятся из числовых констант,

переменных, стандартных функций и операций над ними. Для обозначения

операций используются символы: + (сложение), - (вычитание), * (умножение)

и / (деление). С операндами целого типа могут использоваться операции div

(целочисленное деление) и mod (остаток целочисленного деления). В

арифметическом выражении принят следующий приоритет операций:

1. Вычисление значений стандартных функций;

2. Умножение, деление, div, mod;

3. Сложение и вычитание.

Порядок выполнения операций изменяется с помощью скобок.

Стандартные функции

Таблица 2.3.

Вызов

функции

Тип аргумента Тип резуль-

тата

Назначение функции

Abs(x)

Pi

Sin(x)

Целый/веществ

Целый/веществ

Тип аргум.

Веществ.

Веществ.

Абсолютное значение x

Значение числа π

Синус x

Page 25: НовыеЛекции ОАиП

25

Cos(x)

Arctan(x)

Sqrt(x)

Sqr(x)

Exp(x)

Ln(x)

Trunc(x)

Frac(x)

Int(x)

Round(x)

Random

Random(x)

Odd(x)

Succ(x)

Pred(x)

Chr(x)

Ord(x)

Inc(x)

Dec(x)

Inc(x, n)

Dec(x, n)

Целый/веществ

Целый/веществ

Целый/веществ

Целый/веществ

Целый/веществ

Целый/веществ

Вещественный

Вещественный

Вещественный

Вещественный

Word

Целый

Целый

Целый

Целый(Byte)

Символьный

Целый

Целый

Целый

Целый

Веществ.

Веществ.

Веществ.

Тип аргум.

Веществ.

Веществ.

LongInt

Веществ.

Веществ.

LongInt

Веществ.

Word

Логический

Целый

Целый

Символьный

Целый(Byte)

Целый

Целый

Целый

Целый

Косинус x

Арктангенс x

Квадрат. корень из x, x>0

Значение квадрата x

Значение показ. функ e x

Натур. логарифм x, x>0

Целая часть значения x

Дробная часть значения x

Целая часть значения x

«Правильное» округление x

до ближайшего целого

Сл. число из диап.0<=…<1

Сл. число из диап.0<=…<x

Возвращает True, если

x нечет. (x целое)

Возвр. след. за x значение

в перечисляемом типе

Возвр. предыдущее знач. x

в перечисляемом типе

Возвр. симв. ASCII кода x

Возвр.ASCII код символа x

Увеличивает знач. x на 1

Уменьшает знач. x на 1

Увеличивает знач. x на n

Уменьшает знач x на n

A Div B

A Mod B

Целочисленное деление A на B. Возвращает целую часть

частного, дробная часть отбрасывается

Восстанавливает целый остаток, полученный при выполнении

целочисленного деления.

Отметим, что в тригонометрических функциях аргумент должен быть задан

только в радианах. Как видно из таблицы 2.3 в Object Pascal имеются

стандартные функции для вычисления только трех тригонометрических

функций. Для вычисления остальных необходимо использовать известные

математические соотношения:

)cos(/)()( xxsiпxtg ;

21/(()( xxarctgхarcsiп )) ;

)(2/)arccos( хarcsiпx ;

)(2/)( xarctgxarcctg ;

Для вычисления логарифма с основанием а используется соотношение

alog )(/)()( аlпxlпx ;

Page 26: НовыеЛекции ОАиП

26

Так как в Object Pascal отсутствует операция возведения в степень, то для вы-

числения выражения yx используется известное математическое соотноше-

ние: yx = xye ln = ))(( xlпyexр ;

Но таким образом нельзя возвести в целую степень отрицательное число. Это

можно сделать с использованием операторов цикла. При выполнении дейст-

вий с целыми числами, если операнды имеют различные целые типы, то тип

результата будет соответствовать типу, который включает в себя оба операн-

да. Например, при действиях с ShortInt и Word общим будет тип Integer.

Логические выражения

Логические выражения строятся из логических констант и

переменных, операций отношения и логических операций. В операциях

отношения могут участвовать арифметические и логические выражения, а

также символьные данные. Результатом логического выражения является

значение True (истина) или False (ложь). Операции отношения : < (меньше),

> (больше), = (равно), <= (меньше или равно), >= (больше или равно), < > (не

равно). Логические операции:

Not – > НЕ – логическое отрицание;

And – > И – логическое умножение;

Or – > ИЛИ – логическое сложение.

Xor – > исключительное ИЛИ.

В логических выражениях операции выполняются слева направо с

соблюдением следующего приоритета:

1. Not;

2. *, /, Div, Mod, And, Shr, Shl ;

3. +, -, Or, Xor;

4. =, <>, <, >, <=, >=, in.

К переменным символьного типа, кроме операции присваивания, применима

функция Ord(сh), которая возвращает порядковый номер символа ch в кодо-

вой таблице. Обратная к ней функция Chr(<порядковый номер символа >)

возвращает символ по его порядковому номеру. Для кодировки используется

ANSI - кодировка (American National Standart Institute). Функция Pred(сh) воз-

вращает символ, предшествующий символу ch в кодовой таблице. Функция

Succ(ch) возвращает символ, следующий за символом ch в кодовой таблице. В

виду упорядоченности над символами допустимы логические операции от-

ношения, например ch > ’a’ , ‘ф’ <> ch, ‘+’ <= ch.

Page 27: НовыеЛекции ОАиП

27

ТЕМА 3. ПРОГРАМИРОВАНИЕ РАЗВЕТВЛЯЮЩИХСЯ

АЛГОРИТМОВ

3.1. Определение разветвляющегося алгоритма

Алгоритм называется разветвляющимся, если он содержит две или бо-

лее ветвей отличающихся друг от друга содержанием вычислений. Выход

вычислительного процесса на ту или иную ветвь алгоритма определяется ис-

ходными данными задачи или результатами промежуточных расчетов. На

рис. 3.1 приведена схема разветвляющегося алгоритма решения квадратного

уравнения ax2+bx+c=0:

2

1,2

4

2

b b acx

a

Начало

Ввод

a,b,c

d=b2-4ac

x1=(-b+d)/(2a)

Вывод

x1,x2

Конец

d>0

d d

x2=(-b-d)/(2a)

d=0

x=-b/(2a)

Вывод

x

Нет

решения

ДаНет

Нет

Да

Рис. 3.1. Схема разветвляющегося алгоритма

Page 28: НовыеЛекции ОАиП

28

Для организации разветвлений в языке Object Pascal используются операторы

goto, if и case.

3.2. Оператор безусловной передачи управления goto

Форма записи оператора безусловной передачи управления имеет вид:

goto <метка>;

где <метка> – это идентификатор или целое положительное число без знака,

описанные в разделе описаний меток label.

Например: labe1 8;

goto 8;

8: w:=exp(x);

Оператор goto передает управление оператору с указанной меткой. Оператор,

следующий за goto, обязательно должен иметь метку, иначе он никогда не

получит управление. По возможности следует избегать использования опера-

тора goto так как это приводит к созданию неэффективных программ.

3.3. Оператор условного выбора if

Этот оператор служит для разделения естественного порядка выполне-

ния операторов программы на две ветви. Он может иметь одну из следующих

форм записи:

if <условие> then <оператор1>

else < оператор2>;

Допускается усеченный вариант (без else-ветви)

if <условие> then <оператор>;

где <условие> – выражение логического типа. Если условие выполняется,

тогда выполняется оператор оператор1, иначе, в первом варианте, выполня-

ется оператор оператор2, во втором – выполняется оператор, следующий за

оператором if. Перед ключевым словом else точка с запятой не ставится (см.

рис. 3.2 – 3.3).

Условие

Оператор 1 Оператор 2

Да Нет

Рис. 3.2. Схема действия оператора if

Page 29: НовыеЛекции ОАиП

29

Условие

Оператор

Да Нет

Рис. 3.3. Схема действия усеченного оператора if

При вложенности операторов if каждое else соответствует тому then, которое

непосредственно ему предшествует, например (см. рис. 3.4):

if <условие1> then if <условие2> then оператор1

else оператор2

else оператор3;

Условие 1

Оператор 1 Оператор 3

Да Нет

Условие 2

Оператор 2

Да Нет

Рис. 3.4. Схема действия при вложенности операторов if

В условном операторе после then и else можно размещать только один опера-

тор. Однако, часто необходимо в какой-либо ветви выполнить группу опера-

торов. В Object Pascal имеется возможность объединить группу операторов в

один составной оператор с помощью ключевых слов begin ... end (оператор-

ные скобки). Такой составной оператор может быть размещен после then или

else.

Page 30: НовыеЛекции ОАиП

30

3.4. Оператор выбора Case

Этот оператор служит для разделения естественного порядка выполне-

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

которое принимает выражение порядкового типа – селектор. Напомним, что

к порядковым типам относятся целые, символьные, логические, перечисляе-

мые, интервальные. Оператор Case имеет следующую форму записи:

case <селектор> of

Список констант 1: оператор 1;

Список констант 1: оператор 1;

else оператор 0;

end;

где <список констант к> представляет перечисление тех значений перемен-

ной <селектор> при которых выполняется оператор оператор к. Если значе-

ние переменной <селектор> не попала ни в один <список констант к>, вы-

полняется оператор 0. Допускается усеченный вариант оператора case, когда

else-ветвь может отсутствовать. С помощью оператора case удобно програм-

мировать алгоритмы, имеющие возможность выбора из нескольких вариан-

тов.

3.5. Возможности, предоставляемые средой Delphi для организации раз-

ветвлений

При создании программ в среде Delphi для организации разветвлений

часто используются компоненты в виде переключателей. Состояние таких пе-

реключателей (включен – выключен) визуально отражается на форме. Компо-

нент типа TCheckBox представляет собой один независимый переключатель, с

помощью которого пользователь может указать свое решение типа «да – нет».

В программе состояние переключателя связано со значением булевого свой-

ства CheckBox.Checked (true – false). Компонент CheckBox, помещенный на

форму, позволяет пользователю с помощью щелчка мыши изменить значение

CheckBox.Checked, что может быть использовано в операторе if внутри про-

граммы, например:

if CheckBox.Checked then оператор1

else оператор2;

Компонент типа TRadiogroup представляет собой группу зависимых пере-

ключателей. При включении одного из этой группы все остальные переклю-

чатели отключаются. В программу номер включенного переключателя (0, 1,

2, ...) передается значением свойства Radiogroup.itemindex. Компонент

RadioGroup, помещенный на форму, позволяет пользователю организовать

селектор, передающий в программу через переменную целого типа

RadioGroup.ItemIndex номер включенного переключателя, который анализи-

руется с помощью оператора case внутри программы, например:

Page 31: НовыеЛекции ОАиП

31

case radiogroup.itemindex of

0: w:=sin(x);

1:w:=ln(x);

2:w:=sqrt(x);

end;

Page 32: НовыеЛекции ОАиП

32

ТЕМА 4. ПРОГРАММИРОВАНИЕ ЦИКЛИЧЕСКИХ

АЛГОРИТМОВ

4.1. Понятие циклического алгоритма

Под циклом понимается многократное (итерационное) выполнение неко-

торой последовательности одних и тех же операторов при различных значе-

ниях промежуточных данных. Число повторений может быть задано в явной

или неявной форме. Практически все алгоритмы решения задач содержат

циклически повторяемые участки. Цикл – это одно из фундаментальных по-

нятий программирования. Реализовать его в можно с помощью операторов if

и goto следующим образом:

label m1;

……

m1: <1-й оператор тела цикла>;

……

<Последний оператор тела цикла>;

if <условие продолжения цикла> then goto m1;

<1-й оператор вне цикла>;

где m1 – метка, которая описывается в разделе объявлений меток label. Цикл

продолжается, пока выполняется <условие продолжения цикла>. В этом слу-

чае управление передается оператору с меткой m1 (<1-й оператор тела цик-

ла>). При первом нарушении <условие продолжения цикла> происходит вы-

ход из цикла – передача управления на <1-й оператор вне цикла>. Такая тех-

нология организации циклов была характерна для первых алгоритмических

языков. Однако, очень скоро были выявлены ее недостатки. Особенно не-

удобно оказалось составлять программы автоматизированной отладки и тес-

тирования. Поэтому при разработке новых алгоритмических языков были

введены специальные операторы, позволяющие организовать циклы без ис-

пользования меток. В языке Object Pascal имеется три оператора цикла:

repeat, while, for. Все эти операторы организуют цикл и проверку условия вы-

хода из него.

4.2. Оператор цикла с последующей проверкой условия repeat

Этот оператор имеет следующую форму записи:

repeat

<тело цикла (список операторов)>

until <условие окончания цикла>;

и организует повторение операторов, помещенных между ключевыми слова-

ми repeat и until (тело цикла), до тех пор, пока не выполнится <условие окон-

чания цикла>, после чего управление передается следующему за циклом опе-

ратору.

Page 33: НовыеЛекции ОАиП

33

Например, необходимо вывести таблицу значений функции y=f(x) на интер-

вале [a,b] с шагом h.

x:=a;

repeat

y:=f(x);

<Вывод x, y>

x:=x+h;

until x>b;

4.3. Оператор цикла с предварительной проверкой условия while

Этот оператор имеет следующую форму записи:

while <условие продолжения цикла> do

begin

<тело цикла (список операторов>

end;

и организует повторение операторов, помещенных между begin и end, до тех

пор, пока выполняется <условие продолжения цикла>. Заметим, что если <ус-

ловие продолжения цикла> не выполнится при входе в цикл, то тело цикла не

выполнится ни разу, в отличие от оператора repeat, в котором оно хотя бы

один раз выполнится. Например, последняя задача может быть реализована с

помощью оператора while следующим образом

x:=a;

while x<=b do

begin

y:=f(x);

<Вывод x, y>

x:=x+h;

end;

4.4. Оператор цикла с явно заданныи числом повторений for

Этот оператор имеет следующую форму записи:

for k:=m to n do

begin

<тело цикла (список операторов>

end;

и организует повторение операторов при нарастающем изменении перемен-

ной цикла k от начального значения m до конечного n с шагом единица. Заме-

тим, что если m>n, то тело цикла не выполнится ни разу. Модификация опе-

ратора

for k:=m downto n do

begin

<тело цикла (список операторов>

end ;

Page 34: НовыеЛекции ОАиП

34

организует повторения при убывающем на единицу изменении k. Если m<n,

то тело цикла не выполнится ни разу. Примечание: Переменная цикла k мо-

жет иметь любой порядковый тип (целочисленный, тип char, интервальный,

перечисление). Внимание! Внутри цикла нельзя принудительно изменять пе-

ременную цикла. После окончания цикла переменная цикла становится неоп-

ределенной и ее значение нельзя использовать. Пример использования этого

оператора в случае, когда переменная цикла имеет тип char: Вывести все

символы латинского алфавита в обратном порядке в компанент Memo1:

var c: char;

. . .

For c:=’z’ downto ‘a’ do

Memo1.lines.add(c);

Для досрочного прекращения выполнения цикла используется процедура

Break, которая прерывает выполнение тела любого цикла и передает управле-

ние следующему за циклом оператору. Для прерывания текущей итерации

цикла и передачи управления следующей итерации используется процедура

Continue.

Общие правила при работе с операторами цикла

1. Циклы можно вкладывать друг в друга, но не пересекать.

2. Можно передавать управление из цикла вовне его (выходить из цикла),

но извне передавать управление во внутрь цикла нельзя.

3. Можно досрочно прерывать цикл с помощью процедуры break.

4. Можно досрочно прерывать текущую итерацию с переходом на начало

следующей итерации с помощью процедуры continue.

4.5. Вложенные циклы

Вложенность циклов имеет место тогда, когда внутри повторяемой час-

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

лицы значений функции S(х,n), представляющую собой сумму ряда n

i i

xnxS

1

1),( на интервале [a, b] с шагом h=(b-a)/m. Задаются a, b, количест-

во членов ряда n и количество разбиений интервала m.

h:=(b-a)/m;

x:=a;

repeat

s:=0;

for i:=1 to n do

s:=s+(x+1)/i;

< Вывод x, s>

until x>b+0.0000001;

Следует отметить, что при каждом приращении переменной х накапливается

погрешность, связанная с тем, что величина h из-за округлений вычислена не-

Page 35: НовыеЛекции ОАиП

35

точно. Поэтому возможна ситуация, когда после m+1 шага значение х не рав-

но b и превышает b на некоторую незначительную величину, имеющую поря-

док погрешности округлений. В результате, если условие выхода из цикла за-

писано как x>b, то значение функции в точке b не вычисляется и не выводит-

ся. Для того, чтобы в точке b функция всегда вычислялась в приведенном ал-

горитме используется условие x>b+0.0000001.

4.6. Примеры циклических алгоритмов

Вычисление заданного члена рекуррентной последовательности

Последовательность чисел а0,а1,а2...аn называется одношаговой рекур-

рентной, если каждый следующий член выражается через один предыдущий

по определенному правилу ak=φ(ak-1). Поэтому для того, чтобы найти все чле-

ны последовательности достаточно задать начальный a0. Фрагмент програм-

мы вычислений члена с номером n, при заданном а0 , имеют вид:

a:=a0; for k:=1 to n do a:=f(a);

Заметим, что для реализации алгоритма понадобилось не n, а только две пе-

ременных а0 и а. Последовательность ак сходится к некоторому пределу а,

если при 0, aak k . При увеличении k так же стремится к нулю

разность между соседними членами последовательности 01kk aa . По-

этому для нахождения предела последовательности а с заданной точностью

используется следующий алгоритм:

a:=a0; it:=0;

repeat

it:=it+1;

w:=a;

a:=f(a);

until (abs(a-w)<eps) or (it>100);

где it – счетчик количества повторений, который служит как для их подсчета,

так и для предотвращения зацикливания алгоритма, если последовательность

не сходится к конечному пределу.

Вычисления сумм с использованием рекуррентной последовательности

В практике вычислений часто приходится находить всевозможные

суммы. Использование рекуррентности позволяет значительно упростить вы-

числения. Представим задачу суммирования в общем виде как n

kkaS

0

, где

а0, а1,...ак...аn, последовательность, каждый член которой представляет неко-

торую функцию от k. Предположим, что из последовательности ак удается

выделить рекуррентную последовательность ск: ck=φ(ck-1), представив

ак=ск bk, где bk функция от номера k: bk=f(k). В этом случае программа вычис-

ления суммы имеет вид:

Page 36: НовыеЛекции ОАиП

36

c:=c0 s:=c*f(0);

for k:=1 to n do

begin

c:=φ(c);

s:=s+c*f(k);

end;

Page 37: НовыеЛекции ОАиП

37

ТЕМА 5. ОТЛАДКА ПРОГРАММ И ОБРАБОТКА

ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ

Мастерство программиста определяется умением составить правильный

алгоритм, быстро отладить и протестировать программу его реализующую, т.

е.:

1. выявить и исправить все ошибки;

2. убедиться в правильности алгоритма.

5.1. Ошибки на этапе компиляции

Эти самые простые, их находит компилятор, который останавливается в

том месте, где обнаружена ошибка и внизу окна текста выдает сообщение о ее

характере. Например:

– «Несоответствие типа i:=2.5;»

– «Переменная нигде не используется»

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

строку, но обычно это результат ошибки в предыдущей строке. Постарайтесь

исправить все замечания компилятора, даже если они несущественны.

5.2. Понятие исключительной ситуации

Под исключительной ситуацией понимается такое состояние, возни-

кающее при выполнении некоторых действий программы (например: деление

на нуль, попытка открыть несуществующий файл, выход индекса за допусти-

мые пределы массива и т. п.), при котором требуется выполнить определен-

ные действия для продолжения ее работы или корректного завершения. При

работе в среде Delphi возникновение одной из вышеназванных или других

подобных ситуаций, которых насчитывается более 50, обычно приводит к

полной остановке выполнения программы с указанием причины, что не все-

гда удобно. Каждая такая ситуация имеет свое имя и тип. Для повышения на-

дежности программы и защиты ее от преждевременного завершения в Delphi

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

ров «перехватить» различные исключительные ситуации и организовать вы-

полнение определенных операций при их возникновении. При отладке про-

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

необходимо отменить стандартную реакцию среды Delphi на эти ситуации.

Для этого надо в главном меню Delphi отключить опцию Stop on Delphi Ex-

ceptions находящуюся в Tools Debbuger Options на закладке Language Excep-

tions. В этом случае отключается стандартная реакция среды Delphi на все ис-

ключительные ситуации. С помощью директив можно отключать реакцию на

отдельные исключительные ситуации на определенном этапе работы про-

граммы. Например:

Page 38: НовыеЛекции ОАиП

38

{$I-}

<список операторов>

{$I+}

Директива {$I-} отключает реакцию среды на исключительные ситуации свя-

занные с ошибками ввода – вывода при выполнении <список операторов>.

Директива {$I+} – включает ее снова.

5.3. Защищенные блоки

Для перехвата исключительных ситуаций и описания реакций на их

возникновение в Object Pascal предусмотрены операторы организации защи-

щенного блока try...end; двух видов (except и finally):

1-й вид:

try // попытаться выполнить

<последовательность защищенных операторов>

except // обработчики исключительных ситуаций:

on <тип искл. ситуации 1> do <оператор–обработчик 1>;

...

on <тип искл. ситуации k> do <оператор–обработчик k>;

else // эта ветвь может отсутствовать

<операторы выполняемые если перехваченная ситуация не обнаружена

среди типов ситуаций 1 k >

end;

<следующий оператор>;

Здесь между except и else приводится список нескольких стандартных типов

ситуаций между ключевыми словами on, do и соответствующих каждому из

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

2-й вид:

try

<последовательность защищенных операторов>

finally

<последовательность операторов, которые выполняются всегда,

независимо от того перехвачена ситуация или нет>

end;

<следующий оператор>

Эти блоки отличаются лишь способом обработки перехваченной в <последо-

вательности защищенных операторов> исключительной ситуации. Если все

операторы в этой последовательности выполнялись без возникновения ис-

ключительной ситуации, то в блоке except управление передается на <сле-

дующий оператор>, в блоке finally на оператор, следующий за словом finally.

Если при выполнении одного из защищенных операторов возникла исключи-

тельная ситуация, то следующие за ним защищенные операторы пропускают-

ся, причем в блоке finally управление передается опять на оператор, следую-

щий за словом finally. В блоке же exception управление передается тому опе-

ратору-обработчику, <тип искл. ситуации> которого соответствует возник-

Page 39: НовыеЛекции ОАиП

39

шей ситуации, и после его выполнения – <следующему оператору>. Если в

списке операторов-обработчиков не обнаружен тип возникшей ситуации, то

управление передается операторам, стоящим между else и end. Если при этом

ветвь else отсутствует, то выполняется стандартная обработка ситуации, пре-

дусмотренная в среде Delphi. Следует помнить, что поиск нужного обработ-

чика осуществляется с начала списка вниз до первого, соответствующего. По-

этому, если в списке имеется несколько типов ситуаций, соответствующих

возникшей, то выполняется обработчик встретившийся первый. Если для со-

ставителя программы важен лишь сам факт возникновения исключительной

ситуации, то возможна следующая конструкция:

try

<последовательность защищенных операторов>

except

<операторы, которые выполняются при возникновении

исключительной ситуации>

end;

которая отличается от блока finally тем, что область <операторы…> здесь

выполняется только в случае возникновения исключительной ситуации. За-

щищенные блоки могут вкладываться друг в друга на любую глубину, при-

чем в любой области, где возможно вставить оператор try...end.

5.4. Некоторые стандартные типы исключительных ситуаций

Табл. 5.1

Тип исключи-

тельной ситуации

Причина

EAbort Намеренное прерывания программы, генерируемое про-

цедурой Abort

EArrayError Ошибка при операциях с массивами: использование

ошибочного индекса массива, добавление слишком

большого числа элементов в массив фиксированной дли-

ны (для использования требует подключения модуля

mxarrays)

EConvertError Ошибка преобразования строки в другие типы данных

EDivByZero Попытка целочисленного деления на нуль

ERangeError Целочисленное значение или индекс вне допустимого

диапазона (при включенной директиве проверки границ

массива {$R+})

EIntOverflow Переполнение при операции с целыми числами (при

включенной директиве {$Q+})

EInvalidArgument Недопустимое значение параметра при обращении к ма-

тематической функции

EZeroDivide Деление на нуль числа с плавающей точкой

EOutOfMemory Недостаточное количество памяти

Page 40: НовыеЛекции ОАиП

40

EInvalidOp Неправильная операция с плавающей точкой

EOverFlow Переполнение при выполнении операции с плавающей

точкой

EAssertionFailed Возникает при намеренной генерации исключительной

ситуации с помощью процедуры Assert (при включенной

директиве { $С+ })

5.5. Инициирование собственных исключительных ситуаций

Возникновение исключительной ситуации может быть инициировано

самим разработчиком программы для обработки некоторых «своих» ситуа-

ций. Для этого имеется три оператора:

Во-первых, процедура Abort вставленная в нужном месте раздела try ге-

нерирует ситуацию типа EAbort. В отличие от Break и Exit, она позволяет, на-

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

Во-вторых, процедура Assert (B:Boolean; [const st:String]), генерирует

исключительную ситуацию типа EAssertionFailed, если результат логического

выражения B=false, при этом возможна выдача в диалоговое окно сообщения,

помещенного в St (этот аргумент может отсутствовать).

В-третьих, ключевое слово

raise <тип исключительной ситуации>. create (‘текст сообщения’),

генерирует исключительную ситуацию указанного типа и выдает сообщение.

5.6. Использование функций ShowMessage и MessageDlg

Для вывода сообщений полезно использовать функции ShowMessage и

MessageDlg, Функция ShowMessage(Msg: string) отображает диалоговое окно

с заданным сообщением и кнопкой OK для закрытия окна. В заголовке окна

отображается имя выполняемой программы. Функция MessageDlg(const Msg:

WideString; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx:

Longint): Word отображает диалоговое окно с заданными кнопками и возвра-

щает значение выбранной пользователем кнопки (mrYes, mrOK, mrHelp и

т.д.), папример, MessageDlg('Error', mtError, [mbOK, mbNo], 0);. Параметр

Msg содержит текст сообщения, DlgType определяет вид отображаемого окна

(табл. 5.2).

Табл. 5.2

mtWarning Предупреждающее сообщение

mtError Сообщение о какой-либо ошибке

mtInformation

Информационное сообщение

mtConfirmation

Сообщение с вопросом

Page 41: НовыеЛекции ОАиП

41

mtCustom Пользовательское сообщение, не имеющее значка

и типа

Параметр Buttons указывает, какие кнопки будут находиться в окне

(табл. 5.3). Список необходимых кнопок заключается в квадратные скобки.

Табл. 5.3

mbYes mbCancel mbAbort mbNoToAll

mbNo mbRetry mbHelp mbYesToAll

mbOK mbIgnore mbAll

Параметр HelpCtx определяет номер контекстной справки для данного окна (в

случае отсутствия справки указывается 0). Результатом выполнения функции

является значение, соответствующее нажатой кнопке. Возвращаемое значе-

ние имеет имя, состоящее из букв mr и имени кнопки, например: mrYes,

mrOK, mr Help.

5.7. Пример программы с обработкой исключительных ситуаций

Простейший калькулятор:

Рис. 5.1. Вид формы программы

unit Unit1; Листинг 5.1

interface

uses Windows, Messages, SysUtils, Variants, Classes,

Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;

Page 42: НовыеЛекции ОАиП

42

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

Button3: TButton;

Button4: TButton;

BitBtn1: TBitBtn;

Edit1: TEdit;

Edit2: TEdit;

Label1: TLabel;

Label2: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var Form1: TForm1;

implementation

{$R *.dfm}

{$R+}

procedure TForm1.Button1Click(Sender: TObject);

var a,b,c:extended; // /

begin

try

a:=StrToFloat(Edit1.text);

b:=StrToFloat(Edit2.text);

c:=a/b;

label2.Caption:=FloatToStrf(c,fffixed,8,2);

except

on EZeroDivide do MessageDlg('Нельзя делить на нуль',

mtError,[mbOk],0);

on Econverterror do MessageDlg('Проверьте'+

' значения в edit',mtError,[mbOk],0);

end;

end;

procedure TForm1.Button4Click(Sender: TObject);

var a,b,c:byte; // +

Page 43: НовыеЛекции ОАиП

43

begin

try

a:=StrToInt(Edit1.text);

b:=StrToInt(Edit2.text);

c:=a+b;

label2.Caption:=IntToStr(c);

except

on Erangeerror do MessageDlg('Результат выходит за'+

' пределы диапазона допустимых значений',

mtError,[mbOk],0);

on Econverterror do MessageDlg('Проверьте'+

' значения в edit',mtError,[mbOk],0);

end;

end;

procedure TForm1.Button2Click(Sender: TObject);

var a,b,c:byte; // -

begin

try

a:=StrToInt(Edit1.text);

b:=StrToInt(Edit2.text);

c:=a-b;

label2.Caption:=IntToStr(c);

except

on Erangeerror do MessageDlg('Результат выходит за'+

' пределы диапазона допустимых значений',

mtError,[mbOk],0);

on Econverterror do MessageDlg('Проверьте'+

' значения в edit',mtError,[mbOk],0);

end;

end;

procedure TForm1.Button3Click(Sender: TObject);

var a,b,c:byte; // *

begin

try

a:=StrToInt(Edit1.text);

b:=StrToInt(Edit2.text);

c:=a*b;

label2.Caption:=IntToStr(c);

except

on ERangeerror do MessageDlg('Результат выходит за'+

' пределы диапазона допустимых значений',

mtError,[mbOk],0);

Page 44: НовыеЛекции ОАиП

44

on EConverterror do MessageDlg('Проверьте'+

' значения в edit',mtError,[mbOk],0);

end;

end;

end.

Page 45: НовыеЛекции ОАиП

45

ТЕМА 6. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

МАССИВОВ

6.1. Понятие массива

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

зуют индексированные переменные: векторы, матрицы, тензоры. Так, вектор

c

представляется набором чисел (c1, c2,…, cn), называемых его компонентами,

причем каждая компонента имеет свой номер, который принято обозначать в

виде индекса. Матрица А – это таблица чисел (аij, i=1,..,n, j=1,..,m), где i –

номер строки, j – номер столбца. Операции над матрицами и векторами

обычно имеют короткую запись, которая обозначает определенные порой

сложные действия над их индексными компонентами. Например, произведе-

ния двух векторов записывается как

i

n

i

i bcbc1

Произведение матрицы на вектор

j

n

j

iji cabcAb1

,

;

Произведение двух матриц

kj

n

k

ikij qadGAD1

, ;

Введение индексированных переменных в языках программирования также

позволяет значительно облегчить реализацию многих сложных алгоритмов,

связанных с обработкой массивов однотипных данных. В языке Object Pascal

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

– это упорядоченный набор данных одного типа. Переменные типа массив

вводятся с помощью ключевого слова array следующим образом:

Type <имя типа>=array[список описаний индексов] of <тип элементов>;

Var a, b, c:<имя типа>;

Количество индексов не ограничено, но на практике используются, как пра-

вило, одномерные и двумерные массивы. Индексы могут иметь любой поряд-

ковый тип. Чаще всего используется тип диапазон. В программе доступ к ка-

ждому элементу массива осуществляется по индексу заключенному в квад-

ратные скобки (индекс может задаваться выражением соответствующего ти-

па), например:

b[1]:=5; c[k]:=a[k-2]+b[4*k+3];

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

занные в описании.

Type vek=array[1..100] of extended;

mat=array[1..20,1..20] of extended;

Var a, b: vek;

Page 46: НовыеЛекции ОАиП

46

w :mat;

c: array[byte] of char;

Однотипные массивы как целое могут участвовать только в операциях отно-

шения «рaвно», «не рaвно» и в операторе присваивания. Например: логиче-

ское выражение а=b возвращаeт значения true, если все элементы массивов а

и b одинаковы и false в противном случае, оператор присваивания а:=b; –

всем элементам массива а присваиваются значения соответствующих элемен-

тов массива b.

6.2. Некоторые возможности ввода и вывода массивов в Delphi

При вводе массивов с большим количеством элементов, обычно исход-

ные данные (элементы) готовятся заранее с помощью текстового редактора в

отдельном текстовом файле, и затем программа вводит их из этого файла.

При необходимости изменить некоторые исходные элементы производят ре-

дакцию текстового файла, после чего снова запускают программу. Проиллю-

стрируем это на примере следующей задачи: Ввести из файла и распечатать в

виде таблицы в окне Memo двумерный массив a размерности n m. Вначале с

помощью встроенного текстового редактора подготавливается файл исход-

ных данных, например следующего вида:

4 5 – значения n и m

0.1 0.2 0.8 1.2 5.6 – 1-я строка массива

1.8 2.1 4.2 6.3 2.5 – 2-я строка массива

0.8 0.2 0.6 1.2 1.4 – 3-я строка массива

4.1 7.3 5.8 3.2 1.5 – 4-я строка массива

который записывается под именем Prg.dat . Тогда фрагмент программы бу-

дет выглядеть:

Type mat=array[1..10,1..10] of extended;

Var a:mat;

Lr:TextFile;//описание текстового файла;

St:String;

begin

AssignFile(Lr,’Prg.dat’);

Reset(Lr);

Readln(Lr,n,m); // чтение n и m из 1-й строки файла

for i:=1 to n do

begin

st:=’’;

for j:=1 to m do

begin

Read(Lr,a[i,j]); // чтение i-й строки

st:=st+’ ’+FloatToStrF(a[i,j],fffixed,6,1);

end;

Readln(Lr); // перевод курсора на новую строку файла

Memo1.Lines.Add(st); // Вывод строки в окно Memo

Page 47: НовыеЛекции ОАиП

47

end;

В Delphi для ввода или вывода массивов можно использовать компонент

StringGrid (находится в меню компонентов Additional), который предназначен

для отображения информации в виде двумерной таблицы, каждая ячейка ко-

торой представляет собой окно однострочного редактора (аналогичному окну

Edit). После помещения этого компонента на форму в программе появляется

возможность работать с двумерным массивом

StringGrid1.Cells:array[0..ColCount-1,0..RowCount-1] of string;

Значения ColCount и RowCount, определяющие количество столбцов и строк в

отображаемой таблице, задают с помощью инспектора объектов или опреде-

ляют внутри программы. Каждый элемент массива Cells представляет собой

строку текста, содержимое которой отображается в соответствующей ячейке

на форме. В этом случае ввод вышеописанного массива a, и его вывод на

форму после преобразований реализуется следующим образом:

n:=4; m:=5;

StringGrid1.ColCount:=m;

StringGrid1.RowCount:=n;

...

Procedure Tform1.Button5Click(Sender:Tobject);

Begin

for i:=1 to n do // Ввод массива из stringgrid1

for j:=1 to m do

a[i,j]:=StrToFloat(StringGrid1.Cells[j-1,i-1]);

// Преобразоване массива

...

for i:=1 to n do // Вывод массива в stringgrid1

for j:=1 to m do

StriGrid1.Cells[j-1,i-1]:=FloatToStrF(a[i,j],fffixed,8,3);

end;

Здесь в каждую ячейку будет выведено число с тремя десятичными знаками

после запятой. Заметим, что в массиве Cells первый индекс соответствует но-

меру столбца в таблице отражаемой на форме, второй – номеру строки (нуме-

рация строк и столбцов начинается с нуля), в массиве же наоборот, первый

индекс трактуется как номер строки, второй – номер столбца соответствую-

щей матрицы.

6.3. Примеры алгоритмов работы с массивами

Сумма n элементов одномерного массива:

S:=0; for i:=1 to n do S:=S+a[i];

Сумма модулей всех элементов матрицы:

S:=0;

for i:=1 to n do

for j:=1 to m do

S:=S+abs(b[i,j]);

Page 48: НовыеЛекции ОАиП

48

Произведение диагональных элементов квадратной матрицы:

p:=1;

For i:=1 to n do

p:=p*b[i,i];

Нахождение максимального элемента одномерного маcсива:

max:=a[1];

for i:=2 to n do

if a[i]>max then max=a[i];

Нахождение номера максимального элемента:

m:=1;

for i:=2 to n do

if a[i]>a[m] then m:=i;

Перестановка строк с номерами к1 и к2:

for j:=1 to m do

begin

r:=a[k1,j];

a[k1,j]:=a[k2,j];

a[k2,j]:=r;

end;

Сортировка одномерного массива методом пузырька:

for i:=1 to n-1 do

for k:=1 to n- i do

if a[k]>a[k+1] then

begin

r:=a[k];

a[k]:=a[k+1];

a[k+1]:=r;

end;

Page 49: НовыеЛекции ОАиП

49

ТЕМА 7. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

УКАЗАТЕЛЕЙ

7.1. Статическое и динамическое распределение оперативной памяти

Все команды и данные программы во время ее выполнения размещают-

ся в определенных ячейках оперативной памяти. При этом часть данных раз-

мещается в ячейки памяти еще на этапе компиляции и в процессе работы про-

граммы их адреса относительно начала программы не изменяются. Такое

размещение данных и команд называется статистическим и соответствующие

этим данным переменные называются статистическими переменными. В

языке Object Pascal возможна также организация динамического размещения

данных, при котором под некоторые данные программы память выделяется

непосредственно во время выполнения по мере надобности, а после решения

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

щие таким данным переменные называются динамическими переменными.

7.2. Понятие указателя

Для организации динамического распределения памяти используются

переменные специального типа – указатели, которые обеспечивают работу

непосредственно с адресами ячеек памяти. Указатели делятся на типизиро-

ванные и нетипизированные. Под каждую переменную типа указатель отво-

дится ячейка объемом 4 байта, в которой можно поместить адрес любой пе-

ременной. Тип типизированного указателя вводится описанием ^тип, а нети-

пизированного – pointer.

Вводятся указатели следующим образом:

Type vec=array[1..1] of extended;

mat=array[1..1,1..1] of extended;

ps=String [20];

Var a: ^vec;

w: ^mat;

s: ^ps;

p, q: pointer;

где p, q – нетипизированные указатели; а, w, s – типизированные указате-

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

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

переменных, размещенных в памяти. Значение одного указателя можно пере-

дать другому с помощью оператора присваивания, например:

p:=q;

При этом надо помнить, что в операторе присваивания типизированные ука-

затели должны быть одного типа. Используя нетипизированные указатели,

можно передать адрес между указателями разного типа, например, так:

p:=a; w:=p;

Page 50: НовыеЛекции ОАиП

50

С типизированными указателями можно работать как с обычными перемен-

ными следующим образом: s^:=’Иванов’; Указатели одного типа можно срав-

нить на предмет равенства (=) и неравенства (<>). Следует заметить, что та-

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

своены конкретные значения (адреса). Адрес обычной статической перемен-

ной можно получить с помощью специальной функции Addr(): p:=Addr(m);

или c помощью операции @: p:=@m; Очистка адреса из указателя осуществ-

ляется с помощью специальной функции nil: p:=nil;

7.3. Динамическое распределение памяти

Память под динамические переменные выделяется в специальной Heap-

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

отведения памяти для динамической переменной, это осуществляется проце-

дурой New или GetMem. Процедура New(a:pointer); выделяет блок памяти,

размер которого позволяет разместить тип данных а и присваивает указателю

а значение адреса первого байта блока. После этого данный блок памяти за-

крепляется за переменной и с ним можно работать через возникшую в про-

грамме переменную a^. Такие переменные называются динамическими. После

того, как необходимость работы с этой переменной отпала, данный блок па-

мяти освобождается с помощью процедуры Dispose(a); Аналогичные дейст-

вия соответственно выполняют процедуры GetMem(a:pointer; size:Word); и

FreeMem(a:pointer; size:Word);, где size – обьем выделяемой памяти в байтах,

начиная с адреса, помещаемого в указатель a. Следует помнить, что память

под указатель выделяется 8-байтными порциями. В результате возможна не-

желательная фрагментация.

7.4. Организация динамических массивов

Обычно динамическое выделение и освобождение памяти используется

при работе с массивами данных. С помощью процедур Getmem и Freemem

можно создавать массивы с изменяемым размером – динамические массивы.

Для этого определяется тип указателя на массив с небольшим размером, а за-

тем на этапе выполнениия программы выделяется требуемая память:

Type vek=array[1..1] of <тип элементов>;

Var a:^vek; //указатель на массив

. . .

// выделение памяти под n элементов массива

getmem(a, n* sizeof(<тип элемента>));

. . .

// освобождение памяти

freemem(a,n* sizeof(<тип элемента>));

где функция sizeof(<тип>) возвращает обьем памяти требуемый для данного

типа.

Начиная с версии Delphi 4, в Object Pascal введены динамические

массивы, не требующие указания границ массивов:

Page 51: НовыеЛекции ОАиП

51

Var a: array of extended; // Одномерный динамический массив

b: array of array of integer; // Двумерный динамический массив

Распределение памяти и указание границ индексов по каждому измерению

осуществляется в ходе выполнения программы путем инициализации масси-

ва с помощью функции SetLength(имя динамического массива, количество

элементов). В ходе выполнения оператора SetLength(a, n) одномерный ди-

намический массив a будет инициализирован, т. е. для него будет отведена

память достаточная для размещения n переменных типа extended. Нижняя

граница индекса всегда будет равна 0, поэтому верхней границей индекса бу-

дет значение n-1. В многомерных массивах сначала устанавливается величина

первого измерения, затем второго, третьего и т. д. Поэтому инициализация

двумерного динамического массива b (матрицы, содержащей n строк и m

столбцов) производится следующим образом:

SetLength(b, n);

For k := 0 to n-1 do

SetLength(b[k], m);

Так как длина каждой строки задается отдельным оператором, то она может

быть разной, например:

SetLength(b, n);

For k := 0 to n-1 do

SetLength(b[k], k+1); // Треугольная матрица

или

SetLength(b, 3);

SetLength(b[0], 8); // 1-я строка – 8 элементов

SetLength(b[1], 2); // 2-я строка – 2 элемента

SetLength(b[2], 4); // 3-я строка – 4 элемента

Имя динамического массива является указателем. Поэтому после окончания

работы с массивом необходимо освободить память с помощью функции Fi-

nalize(<имя динамического массива>); или оператором <имя динамического

массива>:= nil; Процедуру SetLength() в процессе выполнения программы

можно вызывать произвольное количество раз. Каждый вызов приводит к из-

менению длины массива, причем содержимое массива сохраняется. Если при

вызове SetLength() длина массива увеличивается, то добавленные элементы

заполняются произвольными значениями, так называемым мусором. Если

длина массива уменьшается, то содержимое отброшенных элементов теряет-

ся. Для работы с динамическими массивами Object Pascal можно использо-

вать функции Low(), High(), Copy(). Функции Low(<имя динамического мас-

сива>) и High(<имя динамического массива>) возвращают наименьшее и

наибольшее значения индекса динамического массива, т. е. 0 и длина-1 соот-

ветственно. Для пустого массива возвращаемое функцией High() значение

равно -1. Функция copy() возвращает заданную часть массива и имеет вид:

Copy(<имя динамического массива>, <начальное значение индекса>,

<количество копируемых элементов>);

Page 52: НовыеЛекции ОАиП

52

Примеры работы с динамическими массивами приведены в лекции

«Списки на основе динамических массивов».

Page 53: НовыеЛекции ОАиП

53

ТЕМА 8. ПОДПРОГРАММЫ И БИБЛИОТЕКИ

8.1. Понятие подпрограммы

При решении многих задач, часто требуется производить вычисления

по одним и тем же алгоритмам при различных исходных данных. Для облег-

чения программирования в языках программирования такие алгоритмы

оформляются в виде подпрограмм. Подпрограмма – это последовательность

операторов, оформленная таким образом, что ее можно многократно вызы-

вать по имени из любой точки программы, и, передав ей определенные пара-

метры и получив требуемый результат, продолжить вычисления. В языке Ob-

ject Pascal подпрограмма может быть оформлена как подпрограмма-функция

или подпрограмма-процедура. Функция оформляется в виде

Function <имя функции>(список формальных параметров): тип результата;

<Разделы локальных описаний>

Begin

<Тело функции>

End;

Процедура оформляется в виде

Procedure <имя процедуры>(список формальных параметров);

<Разделы локальных описаний>

Begin

<Тело процедуры>

End;

где список формальных параметров содержит перечисление имен формаль-

ных параметров с указанием их типов, например:

x, y : extended; var m, k : integer; const s : string; out : extended Через эти параметры осуществляется обмен информацией между подпро-

граммой и той программой, которая к ней обращается. Отличие функции от

процедуры заключается в том, что результат выполнения тела функции дол-

жен быть занесен в имя функции или зарезервированную переменную result,

имеющие тип <тип результата>. Это позволяет использовать вызов функ-

ции как операнд в выражениях. Отличие переменной result от имени функции

в том, что переменная result может использоваться как операнд в выражени-

ях в теле функции. Вызов подпрограммы из какой либо точки программы

производится оператором вида:

<Имя подпрограммы>(<список фактических параметров>);

где <список фактических параметров> содержит перечисление значений

фактических параметров в вызывающей программе, который должен соответ-

ствуют списку формальных параметров по типу, порядку следования и коли-

честву. Для принудительного выхода из подпрограммы используются проце-

дуры return и exit.

Page 54: НовыеЛекции ОАиП

54

8.2. Обмен данными между подпрограммой и программой

Имеется два способа передачи данных между подпрограммой и про-

граммой, из которой производится ее вызов – через глобальные параметры и

через формальные параметры.

Передача данных через глобальные параметры

Параметры, которые введены и описаны внутри подпрограмм, называ-

ются локальными, т. к. они локализированы внутри той подпрограммы, в ко-

торой они описаны, и как бы «невидимы» снаружи (из других подпрограмм).

В то же время, параметры, которые введены и описаны в программе до опи-

сания подпрограммы, называются глобальными по отношению к этой подпро-

грамме, т. к. они «видимы» как внутри неѐ, так и в программе еѐ вызываю-

щей. Это позволяет использовать глобальные параметры для передачи дан-

ных.

Передача данных через формальные параметры Формальные параметры могут быть пяти разновидностей:

Параметры-значения, параметры-переменные, параметры-

константы, выходные параметры и нетипизированные параметры.

Параметры-значения описываются без ключевых слов в виде: список пара-

метров : тип. Для каждого формального параметра-значения транслятор

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

типом параметра. При вызове подпрограммы, происходит пересылка факти-

ческого параметра в эти ячейки памяти, после чего выполняется подпрограм-

ма. При этом значение ячеек, где находился сам фактический параметр, не

изменяется. Этот механизм обеспечивает, как, защищенность фактического

параметра, так и его универсальность, т. е. то, что фактическим параметром

может быть константа, переменная или выражение. Недостатком формально-

го параметра-значения является дублирование блоков памяти в вызывающей

программе и подпрограмме, что в случае, например, параметра-массива при-

водит к неоправданным затратам памяти. Параметры-переменные описыва-

ются с ключевым словом var в виде: var список параметров : тип. Эти пара-

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

мяти. В этом случае фактическим параметром может быть только имя пере-

менной того же типа. При вызове подпрограммы в качестве адреса формаль-

ного параметра передается адрес блока памяти переменной, в котором нахо-

дится фактический параметр, и все действия производятся над этом блоком.

Поэтому после окончания работы подпрограммы в блоке памяти фактическо-

го параметра будет находиться результат. Параметры-константы описыва-

ются с ключевым словом const в виде: const список параметров : тип. Они

отличаются от параметров-переменных только тем, что внутри подпрограммы

им нельзя присваивать новые значения. В этом случае фактическим парамет-

ром может быть переменная или константа. Выходные параметры описыва-

ются с ключевым словом out в виде: out список параметров : тип. Эти пара-

метры подобны параметрам-переменным, только им не присваиваются какие-

Page 55: НовыеЛекции ОАиП

55

либо значения при вызове подпрограммы. Для нетипизированных парамет-

ров не указывается тип параметра. При этом в стек передается адрес фактиче-

ского параметра, а внутри подпрограммы по этому адресу можно располо-

жить переменную любого типа. Можно передавать в качестве параметра име-

на других подпрограмм. Для этого создаются типы-функции и типы-

процедуры, например:

Type <имя типа-функции>=function (список формальных параметров):

тип результата;

<имя типа-процедуры>=procedure (список формальных параметров);

Затем в список формальных параметров подпрограммы добавляют описание:

параметр: <имя типа-функции> или параметр: <имя типа-процедуры>.

Подпрограммы могут иметь директивы, которые записываются после заго-

ловка. Директивой по умолчанию является директива register, которая опре-

деляет передачу параметров в стек слева направо. Директива forward означа-

ет, что дано только описание параметров вызова подпрограммы, а само опи-

сание подпрограммы будет дано ниже.

8.3. Оформление подпрограмм в библиотечный модуль

Набор подпрограмм, которые могут быть использованы при разработке

целого ряда программ удобно оформить в виде отдельных тематических биб-

лиотек. В разные библиотеки обычно собираются подпрограммы алгоритмов

решения задач по определенной теме, например вычисления всевозможных

арифметических функций, обработка массивов и матриц, решение уравнений

и др. Для организации таких пользовательских библиотек в Object Pascal вве-

дены модули. Модуль (unit) – это автономно-компилируемая программная

единица, структура которой представлена на рис. 8.1. Модуль состоит из ин-

терфейсного раздела, доступного для программ, к которым подключен мо-

дуль и раздела реализации. В интерфейсной части располагаются разделы

описаний типов, констант, переменных и заголовки подпрограмм, помещен-

ных в данный модуль. В разделе реализации располагаются описания типов,

констант, переменных и подпрограмм, доступные только внутри данного мо-

дуля и реализация тех подпрограмм, заголовки которых описаны в интер-

фейсном разделе. Кроме того, модуль может содержать инициирующий (initia-

lization) и завершающий (finalization) разделы, которые, однако, редко исполь-

зуются.

unit <имя модуля>;

interface

<Описания типов, констант, переменных и заголовков подпрограмм

«видимые» в программах к которым подключен модуль>

implementation

<описания, которые используются только внутри модуля>

Page 56: НовыеЛекции ОАиП

56

Initialization

Finalization

end.

Рис. 8.1. Структура модуля

Имя модуля должно совпадать с именем файла, в который записан текст мо-

дуля. Подключение модуля к программе осуществляется с помощью операто-

ра uses <имя модуля>; После подключения модуля к программе становятся

доступными все описания интерфейсной части модуля. Для создания модуля

в среде Delphi следует в меню File –>New выбрать опцию Unit. После этого

модуль наполнить содержанием, записать в файл с именем модуля используя

опцию Save As и добавить в проект основной программы окно с текстом мо-

дуля используя опцию Add to Project меню Project.

8.4. Пример создания библиотечного модуля

Создать библиотечный модуль содержаций функции rex(x)=x/7+cos(x2),

fox(x)=ln(x2+5)+sin(x/3) и процедуру вывода таблицы значений произвольной

функции f(x) в интервале [a, b] с шагом h в компанент типа TMemo.

unit biblio; Листинг 8.1

interface

uses SysUtils,StdCtrls;

type fun=function(x:extended):extended;

function rex(x:extended):extended;

function fox(x:extended):extended;

procedure tab(a,b,h:extended; f:fun; mem:TMemo);

implementation

function rex;

begin

result:=x/7+cos(x*x);

end;

function fox;

begin

result:=ln(x*x+5)+sin(x/3);

end;

procedure tab;

var x:extended;

begin

x:=a; mem.clear;

repeat

Page 57: НовыеЛекции ОАиП

57

mem.lines.add(' '+floattostrf(x,fffixed,6,2)+

' '+ floattostrf(f(x),fffixed,9,6) );

x:=x+h;

until x>b+0.00000001;

end;

end.

unit Unit1; Листинг 8.2

interface

uses Windows, Messages, SysUtils, Variants, Classes,

Graphics, Controls, Forms, Dialogs, Buttons, StdCtrls,

biblio;

type

TForm1 = class(TForm)

Memo1: TMemo;

Memo2: TMemo;

Button1: TButton;

BitBtn1: TBitBtn;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var z:extended;

begin

tab(0, 1, 0.1, rex, memo1);

tab(2, 3, 0.1, fox, memo2);

end;

end.

Page 58: НовыеЛекции ОАиП

58

ТЕМА 9. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

МНОЖЕСТВ

9.1. Понятие множества

В математике под множеством понимается неупорядоченный набор

различных однотипных элементов. Весь набор элементов ={ 1, 2, ..... n}

называется пространством элементов. Различные наборы, например:

А={ 2, 4, 1, 5}, В={ 4, 1, 3}, .... называется множествами.

Для работы с множествами в Object Pascal введен специальный тип перемен-

ных – множество, форма описания которого имеет вид:

Type <имя типа> = set of <базовый тип>;

Var <список переменных> : <имя типа>;

где <базовый тип> – любой порядковый тип, кроме word, integer, longint, т.

е. (перечисляемый, интервальный, char, byte, boolean). Максимальное количе-

ство элементов множества – 256. Конструктором множества называются

квадратные скобки, содержащие список элементов множества. Количество

элементов множества называется мощностью множества. Множество, не со-

держащее ни одного элемента, называется пустым. Мощность пустого мно-

жества равна 0. Примеры описаний множеств:

type sim=set of char;

var a, b : set of (‘a’..’z’);

c, d : sim;

e, g : set of byte;

c:=[‘ф’, ‘+’, ‘7’]; Задано множество из трех символов

g:=[14, 2, 30]; Задано множество из 3 чисел

d:=[]; Задано пустое множество

9.2. Операции над множествами

К множествам применимы операции:

Объединение множеств (+): D=A+B={ 1, 2, 3, 4, 5}, множество

D состоит из элементов, входящих или в А или в В.

Разность множеств (исключение из множества) (-): Е=А-В={ 2, 5},

множество Е состоит из элементов множества А, не входящих в В.

Пересечение множеств (*): F=A*B={ 1, 4}, множество F состоит из

элементов, одновременно входящих в А и в В.

Равенство множеств (=): А=В, результат равен true, если множества

А и В состоят из одних и тех же элементов.

Неравенство множеств (<>): А <> В, результат равен true в против-

ном случае.

Page 59: НовыеЛекции ОАиП

59

Подмножество (<=): A<=B, результат равен true, если все элементы

множества А являются элементами множества В.

Надмножество (>=): A>=B, результат равен true, если все элементы

множества В являются элементами множества А.

Операция принадлежности (in): ω in A, результат равен true, если

элемент ω входит в множество А.

Эти операции дополняют две процедуры:

Include (s, i); – процедура добавляет в множество s элемент i;

Exclude (s, i); – процедура исключает из множества s элемент i.

Элемент i должен быть базового типа. Эти операции выполняются значитель-

но быстрее, чем их эквиваленты s:=s+[i]; s:=s - [i];

Использование множеств в ряде случаев позволяет в более компактном виде

записать алгоритм. Например:

1. Вместо оператора: if (k=5) or (k=1) or (k=8) or (k=12) then . . .

достаточно записать if k in [5, 1, 8, 12] then . . .

2. Для выделения из множества символов a всех строчных латинских

букв достаточно записать w:=a*[‘a’..’z’];

3. Для удаления из множества символов a всех строчных латинских

букв достаточно записать w:=a-[‘a’..’z’];

9.3. Пример программы с использованием множеств

Выделить из строки символов отдельные слова и вывести их в алфа-

витном порядке. Пример программы приведен ниже (см. листинг 9.1).

Page 60: НовыеЛекции ОАиП

60

Рис. 9.1. Вид формы выполняемой программы

unit Unit1; Листинг 9.1

interface

uses Windows,Messages,SysUtils,Variants,Classes,

Graphics,Controls,Forms,Dialogs,StdCtrls,Buttons;

type

TForm1 = class(TForm)

ComboBox1: TComboBox;

BitBtn1: TBitBtn;

Memo1: TMemo;

procedure FormActivate(Sender: TObject);

procedure ComboBox1KeyPress(Sender: TObject; var

Key: Char);

procedure ComboBox1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

Page 61: НовыеЛекции ОАиП

61

var Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);

begin

combobox1.setfocus;

memo1.Clear;

end;

procedure TForm1.ComboBox1KeyPress(Sender: TObject;

var Key: Char);

begin

if key=#13 then

begin

combobox1.items.add( combobox1.text);

combobox1.text:='';

end;

end;

procedure TForm1.ComboBox1Click(Sender: TObject);

// список разделителей

const c : set of char = [' ', '.', ',', ':', ';',

'(', ')', '?', '!' , '[', ']', '{', '}'];

var s : string;

n,k,i : integer;

a : array of string;

begin

s:= combobox1.text+' '; n:=0; memo1.clear;

while s<>'' do

begin // удаление начальных разделителей

while (s<>'') and (s[1] in c) do delete(s,1,1);

if s<>'' then

begin

for k:=1 to length(s) do

if s[k] in c then break;

inc(n);

setlength(a,n);//отведение новой памяти для массива

a[n-1]:=copy(s,1,k-1);

delete(s,1,k);

end;

end;

Page 62: НовыеЛекции ОАиП

62

// Сортировка по алфавиту

for i:=2 to n do

for k:=0 to n-i do

if a[k]>a[k+1] then

begin

s:=a[k];

a[k]:=a[k+1];

a[k+1]:=s;

end;

for k:=0 to n-1 do memo1.lines.add(a[k]);

a:=nil; // освобождение памяти

end;

end.

Page 63: НовыеЛекции ОАиП

63

ТЕМА 10. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

СТРОК

10.1. Описание переменных строкового типа

«Короткие строки»

Это статические переменные, длина которых ограничена 255 символа-

ми. Форма описания их имеет вид: var список переменных : string[n]; n≤255

или var список переменных : shortstring; - короткая строка максимальной

длины, ее эквивалент - var список переменных : string[255];

«Длинные строки»

Это динамические переменные (указатели), память для которых (до 2

Гбайт) выделяется по мере надобности на этапе выполнения программы.

Форма описания их имеет вид: var список переменных : string;

«Широкие строки»

Они отличаются от «длинных строк» только тем, что каждый символ

строки кодируется не одним, а двумя байтами памяти (ansi-кодировка позво-

ляет работать только с 256 символами, что явно недостаточно, например, при

работе с китайским или японским алфавитом). Их описание имеет вид: var

список переменных : wideString;

Нуль- терминальные строки

Строковые переменные этого типа представляют собой цепочки симво-

лов, ограниченные символом конца строки #0. Форма их описания имеет вид:

var список переменных : PChar; Необходимость в нуль-терминальных строках

возникает только при прямом обращении к API-функциям операционной сис-

темы.

При работе с компонентами Delphi в основном используются более

удобные короткие и длинные строки. При работе со строковой переменной

имеется возможность обращаться к отдельным символам строки, как элемен-

там одномерного массива.

10.2. Основные операции над переменными строкового типа

Над данными строкового типами допустимы операции присваивания

(:=), сцепления (+) и операции отношения (=, <>, >, <, >=, <=). Операция сце-

пления используется для объединения нескольких строк в одну. Операции

отношения проводят сравнение двух строковых операндов. Сравнение строк

проводится посимвольно, слева направо, до первого несовпавшего символа и

та строка считается больше, в которой первый несовпавший символ имеет

больший кодовый номер. Например: ‘ax’ < ’bcd’ потому что ‘а’ < ’b’,

Page 64: НовыеЛекции ОАиП

64

‘Попов’ > ’Панин’ потому что ‘о’>’а’. Эта особенность позволяет сортиро-

вать массив строк по алфавиту сортируя его по возрастанию.

10.3. Некоторые процедуры и функции обработки строк

В Delphi имеется широкий набор специальных процедур и функций об-

работки строк, с помощью которых можно проводить работу со строками.

Приведем здесь некоторые из них.

Процедуры

Delete(s : string; pz, n : integer); – процедура удаляет n символов из

строки s, начиная с позиции pz, например: s:=’florex’; Delete(s, 4, 2); ре-

зультат – s=’flox’.

Insert(w, s : string; pz : integer); – процедура вставляет подстроку w в

строку s, начиная с позиции pz, например: s:=’это символы’; Insert(’не те ’,

s, 5); результат – s=’это не те символы’.

Str(x[: ширина : кол. десятич. знаков после запятой]; s : string); – про-

цедура преобразует число х целого или действительного типа в строковое

представление (в квадратных скобках – необязательные параметры), напри-

мер: x:=25.4e-1; k:=86;

Str(x:8:4, s); результат – s=’ 2.5400’

Str(x, s); результат – s=’2,540000e+00’

Str(k:3, s); результат – s=’ 86’

Val(s : string; x : (действит. или целое); Kod : integer); – процедура

преобразует строковое представление числа s в числовое в соответствии

с типом переменной х, Kod – код ошибки, Kod = 0 – преобразование успешно,

иначе Kod=номеру позиции в строке, где обнаружен символ не соответст-

вующий числовому представлению, например:

s1:=’2e-5’; s2:=’468’; s3=’0..256’

Val(s1, x, kod); результат – х=2 10-5

, kod = 0

Val(s2, x ,kod); результат – x=468, kod = 0

Val(s3, x, kod); результат – x не изменяется, kod=3

Функции

Copy(s, pz, n) – функция выделяет из строки s подстроку из n символов,

начиная с позиции pz, при этом s сохраняется, например:

s:=’d:\pas\prog.pas’; sp:=Copy(s, 8, 4); результат – sp=’prog’.

length(s) – функция определяет текущую длину строки s.

pos(sp,s) – функция определяет номер позиции, начиная с которой внут-

ри строки s расположена подстрока sp, если подстрока sp не найдена , тогда

результат = 0, например: pz:=pos(’pas’, s); // для вышеприведенной s –

pz=4.

strToFloat(s) – переводит строковое представление в действительное

число (аналог процедуры Val).

strToInt(s) – переводит строковое представление в целое число.

Page 65: НовыеЛекции ОАиП

65

floatTostrF(x, fffixed, 8, 4) - переводит действительное число

в строковое представление с форматом х : 8 : 4, (аналог процедуры str).

intTostr(m) – переводит целое число в строковое представление, причем

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

10.4. Примеры алгоритмов обработки строк

Заменить в строке буквы ‘н’ на ‘ф’

function zam( s : string) : string;

var k: word;

begin

for k:=1 to length (s) do

if s[k]=’н’ then s[k]:=’ф’;

result:=s;

end;

Посчитать количество цифр в строке

function kol( s : string) : byte;

var k:word;

begin

result:=0;

for k:=1 to length(s) do

if s[k] in [‘0’..’9’] then inc(result);

end;

Page 66: НовыеЛекции ОАиП

66

ТЕМА 11. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

ЗАПИСЕЙ

11.1. Понятие записи

Запись – это структура данных, в которой под одним именем объедине-

ны несколько переменные одинакового или разного типов, называемых по-

лями. Форма записи имеет вид:

Type <имя типа>=record

Поле 1: тип 1;

Поле 2: тип 2;

. . .

End;

Var <список переменных>=<имя типа>;

Допускается форма записи с вариантной частью

Type имя типа=record

Поле 1: тип 1; Разделы фиксированной части записи

Поле 2: тип2;

. . .

case порядковый тип of

1:(поле 01: тип 01; Разделы вариантной части записи

Поле 02: тип 02);

...

end;

end;

Все поля в одной записи должны иметь различные имена. Записи в общем

случае имеют фиксированную и вариантную части. Вариантная часть откры-

вается предложением case <порядковый тип> of, и всегда последняя. В ней

указывается несколько вариантов полей, каждый из которых заключен в

скобки, перед которыми стоит значение константы, имеющей тип, указанный

в предложении case. Всем вариантам отводится одна и та же область памяти,

объем которой равен максимальному из объемов вариантов полей. Возможны

записи, имеющие только фиксированную часть (отсутствует вариантная

часть) или имеющие только вариантную часть (отсутствует фиксированная

часть).

11.2. Операции над записями

Для однотипных записей допускается операция присваивания (:=), на-

пример: a:=b; при выполнении которой всем полям записи a присваиваются

значения соответствующих полей записи b. К каждому полю записи можно

получить доступ через составное имя, представляющее собой разделенные

точкой имя записи и имя поля (составное имя), например:

type stud=record

fam:string[20];

gr:integer;

Page 67: НовыеЛекции ОАиП

67

oc:array[1..5] of byte;

sr:extended;

end;

var a, b:stud;

w:array of stud;

. . .

a.fam:=’Попов’; a.gr:=123201; a.oc[1]:=7; w[1].fam:=’Иванов’;

Если поле, в свою очередь, имеет тип записи (вложенность записей), тогда

используется составное имя с двумя и более точками. Чтобы упростить дос-

туп к полям, используется оператор присоединения

With <имя записи> do

begin

<операции с полями записи>

end;

Например, with a do begin fam:=’Попов’; gr:=123201; oc[1]:=7; end;

То обстоятельство, что все варианты записи помещены в одном месте памяти

позволяет использовать эффект наложения друг на друга переменных различ-

ных типов.

Type zap=record

Case boolean do

true: (a:array[1..4] of integer);

false:(b:array[1..2,1..2] of integer);

end;

Var w:zap;

. . .

for k:=1 to 4 do w.a[k]:=k;

При выводе w.b[2,1] будет выведено число 3. В этом примере происходит

наложение одномерного массива на двумерный.

Page 68: НовыеЛекции ОАиП

68

ТЕМА 12. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

ФАЙЛОВ

12.1. Понятие файла

Файлом называется именованный участок внешней памяти. Файлы

предназначены для размещения данных на внешних носителях (обычно маг-

нитных дисках) и последующей работы с этими размещенными данными. В

языке Object Pascal для организации и последующей работы с файлами пре-

дусмотрен специальный файловый тип переменных. Операциям над перемен-

ными файлового типа соответствуют определенные действия над внешними

носителями (дисками, магнитными лентами, принтерами). Переменная фай-

лового типа, или коротко файл, представляет последовательность однотип-

ных компонент, соответствующих последовательности записей на внешнем

носителе. В отличие от массива, количество компонентов заранее не оговари-

вается, и компоненты файла не имеют индексов. Файлы (файловые перемен-

ные) могут быть типизированными, текстовыми и нетипизированными. Фор-

ма описания их в Delphi имеет вид:

Var

< файловая переменная>: file of <тип компонент>;//типизированные файлы

< файловая переменная> : TextFile; // текстовые файлы

< файловая переменная> : File; // нетипизированные файлы

Объясняя принципы работы с файлами, можно для наглядности считать, что

каждый файл записан на некоторой магнитной ленте, как это показано на

следующем рисунке:

.....

– указатель на компонент файла

n – количество записанных компонент.

Указатель определяет положение магнитной головки магнитофона, с помо-

щью которой осуществляется покомпонентная запись или чтение информа-

ции. В начале файла записана информация о файле BOF (Begin of File), его

имя, тип, длина и т. д., в конце файла помещается признак конца файла EOF

(End of File). Если файл пуст, то BOF и EOF совмещены, а указатель уста-

новлен в нуль. Если файл не пуст, то указатель совмещен либо с началом не-

которой компоненты и его значение равно номеру этой компоненты (нумера-

ция начинается с нуля), либо указатель совмещен с признаком конца и его

значение равно количеству компонент.

BO

F

0 1 2 n-2 n-1

EF 1

Page 69: НовыеЛекции ОАиП

69

12.2. Операции над файлами

12.2.1. Типизированные файлы

Пусть f – имя типизированной файловой переменной, а переменные x, y,

z имеют тот же тип, что и его компоненты.

Var f : file of < тип компонента >;

x, y, z : < тип компонента >;

Начинается работа над файлами с процедур открытия файла: AssignFile(f,

<имя файла>); Reset(f); или Rewrite(f); Процедура AssignFile() устанавлива-

ет соответствие между файловой переменной f и <именем файла> на внеш-

нем носителе (задает имя файла). Процедуры Reset(f) и Rewrite(f) иницииру-

ют (подготавливают) файл для работы. Если файл на внешнем носителе от-

сутствует, то новый файл открывается процедурой Rewrite(f), которая создает

новый файл с именем <имя файла>. Если необходимо работать с уже суще-

ствующим файлом с именем <имя файла>, то файл открывается процедурой

Reset(f). После выполнения процедур открытия файла указатель всегда уста-

новлен в начало файла (на компонент с номером 0). Если открытие произво-

дится процедурой Rewrite(f), то признак конца файла совмещен с началом

(т.е. файл пуст). Если перед этим в файле имелась некоторая информация, то

она стирается. Запись новых компанентов в файл производится с помощью

процедуры Write(f, x); или Write(f, x, y, z); После записи каждого нового ком-

понета значение указателя увеличивается на единицу, что соответствует его

перемещению к следующему компоненту файла. Если перед записью указа-

тель находился напротив признака конца файла, то после записи нового ком-

понента признак конца файла смещается на длину этой записи и количество

компонентов в файле возрастает на единицу. Количество компонентов, запи-

санных в файле, можно определить с помощью функции FileSize(f).Чтение

компонентов файла производится с помощью процедуры Read(f, x); или

Read(f, x, y, z); При чтении каждого компонента значение указателя увеличи-

вается на единицу. Если производится попытка чтения при указателе, уста-

новленном на конец файла, то происходит останов программы по ошибке

чтения. Распознать ситуацию, когда указатель установлен на конец файла,

можно с помощью функции Eof(f), возвращающей значение True, если дос-

тигнут конец файла, и False, в противном случае. Организовать чтение с про-

веркой этого условия можно, например, следующим образом: if not Eof(f) then

Read(f, x); При необходимости чтения или записи заданного компонента

файла нужно предварительно установить указатель на этот компонент. Это

делается с помощью процедуры Seek(f, <номер компонента>). Например,

при выполнении группы операторов Seek(f, 2); Read(f, x); Write(f, y); пере-

менная x будет прочитана из компонента с номером 2 (третьего), а перемен-

ная y запишется в компонент с номером 3 (четвертый). Текущее положение

указателя можно определить с помощью функции FilePos(f). После окончания

работы с файлом его следует обязательно закрыть с помощью процедуры Clo-

Page 70: НовыеЛекции ОАиП

70

seFile(f). Если этот оператор будет отсутствовать, то из-за специфики обмена

данными с файлом, часть информации, помещенной в файл, может быть уте-

ряна.

12.2.2. Текстовые файлы

Для удобства хранения текстовой информации, т. е. представленной по-

следовательностью строк символов, в языке Object Pascal введены файловые

переменные текстового типа или просто текстовые файлы. Текстовые файлы

можно представлять эквивалентным типизированным файлом, компонентами

которого являются символы. Однако в текстовом файле последовательность

символов разбита на строки различной длины, т. е. в конце каждой строки

(компонента) ставится специальный признак EOLN (End of LiNe), а в конце

файла признак конца файла EOF (End of File). При просмотре такого файла

текстовым редактором на экране возникает естественная «книжная» страница

текста, которую затем можно отредактировать. При работе с текстовым фай-

лом следует помнить, что в отличие от типизированного, после открытия

файла процедурой Reset (ft) разрешается только чтение: Read(ft, w); – чтение

одного символа, Readln(ft, a, b, c); – чтение трех компонент с последующим

переходом к следующему компоненту (строке), Readln(ft); – переход к сле-

дующей компоненте (строке) (ft – текстовая файловая переменная, w – пере-

менная типа char, a, b, c – переменные типа string). После открытия файла

процедурой Rewrite (ft) разрешается только запись в него, при этом предыду-

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

файле его следует открывать процедурой Append (ft). В этом случае указатель

устанавливается на конец файла и последующие записи добавляют новые

компаненты (строки) в конец файла. Для записи используются процедуры

Write(ft, a, b);, Writeln(ft, c:8,’переменная d=’, d:10:2); Для текстовых файлов

введены модификации операторов ввода – вывода Readln(ft), Writeln(ft), кото-

рые осуществляют переход на следующую строку после чтения или записи

указанных в операторе переменных, при этом оператор Writeln записывает

символ конца строки EOLN. Заметим, что тип переменных a, b, c здесь может

быть любого скалярного типа. При выводе широко используются форматиро-

вание и автоматически происходит преобразование чисел в их строковые

представления. При вводе строковые представления чисел, разделенные про-

белами автоматически преобразуются в числовые представления в соответст-

вии с типом переменных.

12.2.3. Нетипизированные файлы

Описываются: var fn: File; Открываются процедурами Reset(fn, size)

или Rewrite(fn, size), где size – размер блока в байтах. Тип компонентов

этих файлов заранее не оговорен и считается последовательностью байтов.

Поэтому их можно использовать для обработки файлов любого типа, а так же

для организации высокоскоростного обмена между дисками и памятью.

Page 71: НовыеЛекции ОАиП

71

12.3. Подпрограммы работы с файлами

AssignFile(var F; FileName: string) – связывает файловую переменную F

с файлом с именем FileName (задает имя файла).

Reset(var F[: File; RecSize: word]) – открывает существующий файл.

При открытии нетипизированного файла RecSize задает размер элемента фай-

ла.

Rewrite(var F[: File; RecSize: word]) – создает и открывает новый файл.

Append(var F: TextFile) – открывает текстовой файл для дозаписи текста

в конец файла.

Read(F,v1[,v2, …vn]) – осуществляет чтение значений переменных, на-

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

Write(F,v1[,v2,…vn]) – осуществляет запись значений переменных, на-

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

CloseFile(F) – закрывает ранее открытый файл.

Rename(var F; NewName: string) – переименовывает неоткрытый файл

любого типа.

Erase(var F) – удаляет неоткрытый файл любого типа.

Seek(var F; NumRec: Longint) – для типизированного файла устанавли-

вает указатель на компонент с номером NumRec.

Truncate(var F) – обрезает файл, начиная с текущей позиции.

IoResult: integer – возвращает код результата последней операции вво-

да-вывода.

FilePos(var F): longint – для типизированных файлов возвращает номер

текущей позиции. Нумерация начинается с нуля.

FileSize(var F): longint – для типизированных файлов возвращает коли-

чество компонентов в файле.

Eoln(var F: TextFile): boolean – возвращает True, если достигнут конец

строки.

Eof(var F) ): boolean – возвращает True, если достигнут конец файла.

SeekEoln(var F: TextFile): boolean – возвращает True, если пройден по-

следний значимый символ в строке или файле, отличный от пробела или зна-

ка табуляции.

SeekEof(var F: TextFile): boolean – то же, что и SeekEoln, но для всего

файла.

12.4. Компоненты OpenDialog и SaveDialog

Для удобства работы с файлами в Delphi имеются два специальных

компонента, предназначенных для выбора требуемого файла через удобное

окно просмотра. Результатом этого выбора является имя и маршрут к файлу,

помещаемому в переменную строкового типа OpenDialog1.FileName или Sa-

veDialog1.FileName, которые затем используются в процедуре AssignFile().

Компоненты OpenDialog и SaveDialog находятся на странице Dialogs меню

компонентов. Все компоненты этой страницы являются невизуальными, т. е.

не видны в момент выполнения программы. Поэтому их можно разместить в

Page 72: НовыеЛекции ОАиП

72

любом удобном месте формы. Оба рассматриваемых компонента имеют

идентичные свойства и отличаются только внешним видом. После вызова

компонента появляется диалоговое окно, с помощью которого выбирается

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

выбранного файла и маршрут поиска содержится в свойстве FileName. Для

фильтрации файлов, отображаемых в окне просмотра, используется свойство

Filter, а для задания расширения файла, в случае, если оно не задано пользо-

вателем, – свойство DefaultExt. Для того, чтобы файл автоматически записы-

вался, например, с расширением dat, в свойстве DefaultExt компонета

SaveDialog запишем требуемое расширение – dat (для текстового файла –

txt). Для изменения заголовка диалогового окна используется свойство Title.

12.5. Пример программы работы с файлами

Создать файл, содержащий список книг. Предусмотреть возможность

сортировки книг по алфавиту по фамилии автора и вывод, как всего списка,

так и списка книг заданного автора.

Рис. 12.1. Общий вид формы

Page 73: НовыеЛекции ОАиП

73

Рис. 12.2. Вид формы после запуска программы

Рис. 12.3. Вид окна SaveDialog1 после нажатия кнопки «Создать».

Page 74: НовыеЛекции ОАиП

74

Рис. 12.4. Вид формы после задания имени файла.

Рис. 12.5. Вид формы после нажатия кнопки «Закончить».

Page 75: НовыеЛекции ОАиП

75

Рис. 12.6. Вид формы после нажатия кнопки «Просмотреть».

Рис. 12.7. Вид формы после нажатия кнопки «Выбрать», задании фа-

милии интересующего автора и нажатия кнопки «Вывести».

unit Unit1; Листинг 12.1

interface

uses

Page 76: НовыеЛекции ОАиП

76

Windows, Messages, SysUtils, Classes, Graphics, Con-

trols, Forms, Dialogs,StdCtrls, ExtCtrls, Buttons;

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

BitBtn1: TBitBtn;

Panel1: TPanel;

Edit1: TEdit;

Edit2: TEdit;

Label1: TLabel;

Label2: TLabel;

Button3: TButton;

Button4: TButton;

OpenDialog1: TOpenDialog;

SaveDialog1: TSaveDialog;

Panel2: TPanel;

Button5: TButton;

Button6: TButton;

Button7: TButton;

Button8: TButton;

Panel3: TPanel;

Button9: TButton;

Button10: TButton;

Edit3: TEdit;

Label3: TLabel;

Panel4: TPanel;

Label4: TLabel;

Label5: TLabel;

Memo1: TMemo;

Memo2: TMemo;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

procedure Button5Click(Sender: TObject);

procedure Button6Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button8Click(Sender: TObject);

procedure Button7Click(Sender: TObject);

procedure Button9Click(Sender: TObject);

procedure Button10Click(Sender: TObject);

private

{ Private declarations }

Page 77: НовыеЛекции ОАиП

77

public

{ Public declarations }

end;

type book=record

avt:string[20];

naz:string[30];

end;

var

Form1: TForm1;

f:file of book;

w:book;

a:array[1..100] of book;

fname:string;

n,i,k:integer;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

begin

panel1.Hide; panel2.Hide;

panel3.Hide; panel4.Hide;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin // Создать

SaveDialog1.Title:='Создать файл';

if SaveDialog1.Execute then

begin

fname:=SaveDialog1.FileName;

AssignFile(f,fname);

Rewrite(f);

end;

Panel1.Show;

Button1.Hide; Button2.Hide; BitBtn1.Hide;

end;

procedure TForm1.Button3Click(Sender: TObject);

begin // Ввести

w.avt:=edit1.text;

w.naz:=edit2.text;

write(f,w);

Page 78: НовыеЛекции ОАиП

78

edit1.clear; edit2.clear;

end;

procedure TForm1.Button4Click(Sender: TObject);

begin // Закончить

CloseFile(f);

panel1.Hide;

panel2.show;

BitBtn1.show;

end;

procedure TForm1.Button5Click(Sender: TObject);

begin // Сортировать

reset(f); n:=0;

while not eof(f) do

begin

n:=n+1;

read(f,a[n]);

end;

closeFile(f);

for i:=1 to n-1 do

for k:=1 to n-i do

if a[k].avt > a[k+1].avt then

begin w:=a[k]; a[k]:=a[k+1]; a[k+1]:=w; end;

rewrite(f);

for i:=1 to n do write(f,a[i]);

closeFile(f);

end;

procedure TForm1.Button6Click(Sender: TObject);

begin // Просмотреть

panel4.Show; memo1.clear; memo2.clear;

reset(f);

while not eof(f) do

begin

read(f,w);

memo1.lines.add(w.avt);

memo2.lines.add(w.naz);

end;

closeFile(f);

end;

procedure TForm1.Button2Click(Sender: TObject);

begin // Открыть

Page 79: НовыеЛекции ОАиП

79

OpenDialog1.Title:='Открыть файл';

if OpenDialog1.Execute then

begin

fname:=OpenDialog1.FileName;

AssignFile(f,fname);

Reset(f);

end;

Panel2.Show;

Button1.Hide; Button2.Hide; BitBtn1.Hide;

end;

procedure TForm1.Button8Click(Sender: TObject);

begin // Выход из panel2

Button1.show; Button2.show; BitBtn1.show;

panel2.Hide;

end;

procedure TForm1.Button7Click(Sender: TObject);

begin // Выбрать

panel2.Hide; panel3.Show; bitbtn1.Hide;

memo1.clear; memo2.clear;

end;

procedure TForm1.Button9Click(Sender: TObject);

begin // Вывести

memo1.clear; memo2.clear;

reset(f);

while not eof(f) do

begin

read(f,w);

if w.avt=edit3.text then

begin

memo1.lines.add(w.avt);

memo2.lines.add(w.naz);

end;

end;

closeFile(f);

end;

procedure TForm1.Button10Click(Sender: TObject);

begin // Выход из panel3

panel3.Hide; panel4.Hide;

Button1.show; Button2.show; BitBtn1.show;

end; end.

Page 80: НовыеЛекции ОАиП

80

ТЕМА 13. ПРОГРАММИРОВАНИЕ С ОТОБРАЖЕНИЕМ

ГРАФИЧЕСКОЙ ИНФОРМАЦИИ

Как происходит отображение на экране

Любое изображение на экране монитора формируется из набора све-

тящихся элементов, получивших название пиксель. Этот процесс отобра-

жения осуществляется с помощью специальной микросхемы, называемой

графическим адаптером. Работа графического адаптера осуществляется

под управлением специальной программы – драйвера. Адаптер содержит

порты ввода-вывода информации, оперативную память, в которой поме-

щается таблица, содержащая информацию о каждом светящемся на экране

пикселе (его координате, цвете, яркости). Левый верхний угол экрана име-

ет нулевые координаты пикселя. Разрешающая возможность графического

адаптера определяется размерами одного пикселя. Поле рисования называ-

ется канвой или холстом.

13.1. Как рисуются изображения

Нарисовать изображение в среде Delphi можно на многих компонентах

(например на форме, на компоненте TPaintBox), однако наиболее удобно ис-

пользовать компонент TImage (страница Additional меню компонентов). Нари-

сованную в Image1 картинку можно перенести в отчет, используя процедуру

ClipBoard.Assign(Image1.Picture) (модуль Clipbrd). Для рисования используют

класс TСanvas, который является свойством многих компонентов, и представ-

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

ментов для рисования на нем. Каждый пиксель имеет координату (x, y), где x –

порядковый номер пикселя, начиная от левой границы холста, а y – порядко-

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

холста имеет координату (0, 0), а нижний правый (Image1.Width-1, Im-

age1.Height-1).

Основные свойства класса TCanvas

Property Pen : TPen; – карандаш. В свою очередь, имеет свойства Color

- цвет , Width - толщина и Style – стиль ( psSolid – сплошной, psDash – штри-

ховой, psDot – пунктирный, psClear – отсутствие линии и др.).

Property Brush : TBrush; – кисть. Это свойство определяет фон заполне-

ния замкнутых фигур. В свою очередь, имеет свойства Color - цвет и Style –

стиль ( bsSolid – сплошной, bsCross – сетка, bsClear – отсутствие фона и др.).

Property Font : TFont; – шрифт. В свою очередь, имеет свойства Color -

цвет, Size - размер и Style – стиль ( fsBold – жирный, fsitalic – курсив и др.).

Page 81: НовыеЛекции ОАиП

81

Некоторые методы класса TCanvas

Pгосеdure Еlliрsе(Х1, Y1, Х2, Y2: Integer) – рисует эллипс в охватываю-

щем прямоугольнике (X1, Y1), (Х2, Y2) и заполняет внутреннее пространство

эллипса текущей кистью.

Pгосedure LineТо (X, У: Integer) – рисует линию от текущего положения

пера до точки (X. У).

Procedure МоvеТо(Х, У: Integer) – перемещает карандаш в точку (X, У)

без вычерчивания линий.

Pгосedure Роlуgоn (Роints: аrrау оf ТРоint) – рисует многоугольник по

точкам, заданным в массиве Роints.

Например: Canvas.Polygon([Point(x1, y1), Point(x2, y2), Point(x3, y3]); Конеч-

ная точка соединяется с начальной и многоугольник заполняется кистью. Для

вычерчивания без заполнения используется метод Роlуline.

Pгосedure Rectangle (X1, У1, Х2, У2: Integer) – рисует и заполняет прямо-

угольник (X1, У1), (Х2, У2). Для вычерчивания без заполнения используется

FrameRect или РоlуLine.

Procedure ТехtОut (Х, У: Integer; const Техt: String) – выводит текстовую стро-

ку Техt так, чтобы левый верхний угол прямоугольника, охватывающего

текст, располагался в точке (X, У).

13.2. Построение графиков с помощью компонента Chart

Обычно результаты расчетов представляются в виде графиков и диа-

грамм. Среда Delphi имеет мощный пакет стандартных программ вывода на

экран и редактирования графической информации, который реализуется с

помощью визуально отображаемого на форме компонента Chart. Построение

графика (диаграммы) производится после вычисления таблицы значений

функции y=f(x). Полученная таблица передается в специальный двумерный

массив Chart.SeriesList[k] (k – номер графика (0, 1, 2,...)) компонента Сhart с

помощью метода AddXY. Компонент Chart осуществляет всю работу по ото-

бражению графиков, переданных в объект Chart.SeriesList[k]: строит и разме-

чает оси, рисует координатную сетку, подписывает название осей и самого

графика, отображает переданную таблицу в виде всевозможных графиков или

диаграмм. При необходимости, с помощью встроенного редактора

EditingChart компоненту Сhart передаются данные о толщине, стиле и цвете

линий, параметрах шрифта подписей, шагах разметки координатной сетки и

другие настройки. В процессе работы программы изменение параметров воз-

можно через обращение к соответствующим свойствам компонента Chart.

Так, например, свойство Chart.BottomAxis содержит значение максимального

предела нижней оси графика. Перенести график в отчет можно через буфер

обмена, используя процедуру Chart.CopyToClipboardMetafile(True).

Примеры. Построить графики функций sin(x) и cos(x) с помощью ком-

понента Chart. Текст и форма проекта приведены ниже.

Page 82: НовыеЛекции ОАиП

82

Рис. 13.1. Вид формы с компонентом chart выполняемой программы

unit Unit1; Листинг 13.1

interface

uses Windows,Messages,SysUtils,Variants,Classes,

Graphics,Controls,Forms,Dialogs,StdCtrls,TeEngine,

Series, ExtCtrls, TeeProcs, Chart, Buttons;

type

TForm1 = class(TForm)

Chart1: TChart;

Series1: TLineSeries;

Series2: TLineSeries;

Button1: TButton;

BitBtn1: TBitBtn;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

f:file of extended;

Page 83: НовыеЛекции ОАиП

83

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var k:integer; // Нарисовать

x,y,z:extended;

begin

for k:=0 to 100 do

begin

x:=0.02*pi*k; y:=sin(x); z:=cos(x);

series1.AddXY(x,y,'',clRed);

series2.AddXY(x,z,'',clGreen);

end;

end;

end.

Вывести на форму некоторые простейшие фигуры и текст.

Рис. 13.2. Вид формы выполняемой программы с построенными ней изо-

бражениями

unit Unit1; Листинг 13.2

Page 84: НовыеЛекции ОАиП

84

interface

uses

Windows,Messages,SysUtils,Variants,Classes,Graphics,

Controls,Forms,Dialogs,StdCtrls,Buttons;

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

BitBtn1: TBitBtn;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin

with form1.Canvas do

begin

pen.Width:=3;

pen.color:=clred;

brush.style:=bsCross;

brush.Color:=clgreen;

polygon([point(190,30), point(240,60),

point(170,40)]);

polyline([point(290,30), point(340,60),

point(270,40)]);

rectangle(200,100,280,140);

ellipse(20,150,220,220);

font.color:=clblue;

font.Size:=50;

textout(350,120,'test');

end;

end;

Page 85: НовыеЛекции ОАиП

85

procedure TForm1.Button2Click(Sender: TObject);

begin // Очистить

refresh;

end;

end.

Page 86: НовыеЛекции ОАиП

86

ТЕМА 14. ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

РЕКУРСИИ

14.1. Понятие рекурсии

Рекурсивным называется описание объекта, частично состоящее и оп-

ределяемое с помощью самого описываемого объекта. Рекурсия – это такой

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

ходе выполнения обращается сама к себе.

Классический пример: вычисление факториала n! = 1*2*3…(n-1)*n.

Рекурсивное описание: n! = (n-1)! * n, 0! = 1.

Рекурсивная функция:

Function fak(n:word):extended;

begin

if n=0 then result:=1

else result:=fak(n-1)*n

end;

Примечание: Тип результата вычислений (extended) выбран из-за

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

Нерекурсивная функция:

Function fak(n:word):extended;

Var k:word;

begin

result:=1;

if n>1 then for k:=2 to n do

result:=result*k;

end;

При выполнении рекурсивной подпрограммы осуществляется много-

кратный переход от текущего уровня организации алгоритма к нижнему

уровню последовательно, до тех пор, пока не будет получено тривиальное

решение задачи (в вышеприведенном примере, n=0). Рекурсивная форма за-

писи алгоритма обычно выглядит изящнее итерационной и дает более ком-

пактный текст программы, но при выполнении работает медленнее и может

вызвать переполнение программного стека (исключительная ситуация ES-

tackOverFlow), т. к. при каждом переходе к следующему уровню (рекурсив-

ной активации подпрограммы) происходит создание и запоминание всех ее

локальных и формальных параметров. В результате, после n-й активации в

памяти будет находиться список из n+1 комплектов таких параметров.

Рекурсивный вызов может быть прямым, как в вышеприведенном при-

мере, и косвенным. В этом случае подпрограмма обращается к себе опосредо-

ванно, путем вызова другой подпрограммы, в которой содержится обращение

к первой.

Page 87: НовыеЛекции ОАиП

87

// Опережающее описание

Procedure rex(<список параметров>); Forward;

Procedure fox(<список параметров>);

begin

...

rex(<список параметров>);

...

end;

Procedure rex;

begin

...

fox(<список параметров>);

...

end;

В этом примере обращение к процедуре rex() записано раньше, чем

ее описание, что недопустимо в Object Pascal. Для разрешения этой ситуации

используется опережающее описание с помощью стандартной директивы

Forward.

Внимание. Для предотвращения зацикливания рекурсивной подпро-

граммы необходимо предусмотреть обязательный выход на тривиальное ре-

шение, т. е. на ветвь, не содержащую обращение подпрограммы к самой себе.

15.2. Примеры рекурсивных вычислений

Найти максимальный элемент в массиве используя метод деления мас-

сива пополам max (a1…an) = max ( max ( a1…an/2 ), max ( an/2+1…an ) )

type vek=array[1..50] of extended;

function maxR(x:vek; m,n:integer):extended ;

var k:integer;

begin

if m=n then result:=x[m]

else begin k:=(m+n) div 2;

if maxR(x,m,k)>maxR(x,k+1,n)

then result:=maxR(x,m,k)

else result:=maxR(x,k+1,n);

end;

end;

Page 88: НовыеЛекции ОАиП

88

Найти максимальный элемент в массиве используя очевидное соотно-

шение max (a1…an) = max ( max(a1…an-1), an)

function maxRn(x:vek; n:integer):extended;

begin

if n=1 then result:=x[1]

else if maxRn(x,n-1)>x[n] then result:=maxRn(x,n-1)

else result:=x[n];

end;

Page 89: НовыеЛекции ОАиП

89

ТЕМА 15. ПОИСК И СОРТИРОВКА МАССИВОВ

15.1. Организация работы с базами данных

Для создания и обработки всевозможных баз данных широко применяются

массивы записей. Обычно база данных накапливается и хранится на магнитном

диске. К ней часто приходится обращаться, обновлять, перегруппировывать. Ра-

бота с базой может быть организована двумя способами:

1. Вносить изменения и осуществлять поиск можно прямо на диске, исполь-

зуя специфическую технику работы с записями на файлах, при этом временные

затраты на обработку данных (поиск, сортировку) значительно возрастают, но

нет ограничений на оперативную память.

2. В начале работы вся база (или ее необходимая часть) считывается в мас-

сивы записей и обработка производится в оперативной памяти, что значительно

сокращает ее время, однако требует затрат оперативной памяти. Наиболее час-

тыми операциями при работе с базами данных являются «поиск» и «сортировка».

При этом алгоритмы решения этих задач существенно зависят от того, организо-

ваны записи в массивы или размещены на диске. Обычно запись содержит некое

ключевое поле (ключ), по которому ее находят среди множества других анало-

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

пример, фамилия, номер расчетного счета или адрес. Основное требование к

ключу в задачах поиска состоит в том, чтобы операция проверки на равенство

была корректной. Поэтому, например, в качестве ключа не следует выбирать

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

нужного ключа может оказаться безрезультатным, хотя этот ключ в массиве име-

ется.

15.2. Поиск в массиве записей

Задача поиска требуемого элемента в массиве записей a[i], i = 1,.., n за-

ключается в нахождении индекса i, удовлетворяющего условию a[i].k = isk. Здесь

поле записи k выступает в качестве ключа, isk – искомый ключ. После нахожде-

ния i обеспечивается доступ ко всем другим полям найденной записи a[i].

Линейный (последовательный) поиск используется, когда нет никакой до-

полнительной информации о разыскиваемых данных. Он представляет собой по-

следовательный перебор массива до обнаружения требуемого ключа или до кон-

ца, если ключ не обнаружен:

i:=1;

while (i<=n) and (a[i].k <> isk) do i:=i+1;

if i=n+1 then < вывод(‘элемент не найден’)>

else <вывод(‘индекс искомого элемента= ’, i)>;

Поиск с барьером. Видно, что на каждом шаге требуется увеличивать ин-

декс и вычислять логическое выражение. Уменьшить затраты на поиск можно

упростив логическое выражение с помощью введения вспомогательного элемен-

Page 90: НовыеЛекции ОАиП

90

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

конец массива добавляется элемент с искомым ключом. Количество проверок на

каждом шаге уменьшается (одна, а не две) т. к. нет необходимости проверки вы-

хода за пределы массива – элемент с искомым ключом обязательно будет найден

до выхода за пределы массива.

a[n+1].k := isk; i:=1;

while a[i].k <> isk do i:=i+1;

if i=n+1 then <вывод( ‘элемент не найден’ ) >

else <вывод( ‘индекс искомого элемента= ’ , i) >;

Поиск делением пополам (бинарный поиск) используется, когда дан-

ные упорядочены по возрастанию ключа k, т. е. a[i]. k a[i+1]. k. Основная

идея поиска – берется «средний» (m-й) элемент. Если a[m].k < isk, то все

элементы i m можно исключить из дальнейшего поиска, если a[m]. k isk,

то можно исключить все i > m:

i:=1; j:=n;

while i < j do

begin

m := ( i+j ) div 2;

if a[m].k < isk then i:=m+1 else j:=m;

end;

if a[i].k = isk then <вывод( ‘индекс искомого элемента=’ , i) >

else <вывод( ‘элемент не найден’) > ;

В этом алгоритме отсутствует проверка внутри цикла совпадения a[m].k =

isk. На первый взгляд это кажется странным, однако тестирование показыва-

ет, что в среднем выигрыш от уменьшения количества проверок превосхо-

дит потери от нескольких «лишних» вычислений до выполнения условия

i=j.

15.3. Сортировка массивов

Под сортировкой понимается процесс перегруппировки элементов мас-

сива, приводящий к их упорядоченному расположению относительно ключа.

Цель сортировки – облегчить последующий поиск элементов. Метод сорти-

ровки называется устойчивым, если в процессе перегруппировки относи-

тельное расположение элементов с равными ключами не изменяется. Основ-

ное условие при сортировке массивов –не вводить дополнительных масси-

вов, т. е. все перестановки элементов должны выполняться «на том же мес-

те» в исходном массиве. Сортировку массивов принято называть внутренней

в отличиe от сортировки файлов (списков), которую называют внешней.

Методы внутренней сортировки классифицируются по времени их ра-

боты. Хорошей мерой эффективности может быть число сравнений ключей

– С и число пересылок элементов – Р. Эти числа являются функциями С(n),

Р(n) от числа сортируемых элементов n. Быстрые (но сложные) алгоритмы

сортировки требуют (при n ) порядка n log n сравнений, прямые (про-

стые) методы – n2.

Page 91: НовыеЛекции ОАиП

91

Прямые методы коротки, просто программируются. Быстрые, услож-

ненные, методы требуют меньшего числа операций, но эти операции обычно

сами более сложны, чем операции прямых методов, поэтому для достаточно

малых n (n 50) прямые методы работают быстрее. Значительное преимуще-

ство быстрых методов (в n/log(n) раз) начинает проявляться при n~

100.

Среди простых методов наиболее популярны:

1) Метод прямого обмена (пузырьковая сортировка).

2) Метод прямого выбора.

3) Сортировка с помощью прямого (двоичного) включения.

4) Шейкерная сортировка (модификация пузырьковой).

Улучшенные методы сортировки:

1) Метод Д. Шелла , усовершенствование метода прямого

включения.

2) Сортировка с помощью дерева, метод HeapSort, Д. Уильямсон.

3) Сортировка с помощью разделения, метод QuickSort, Ч. Хоар, улуч-

шенная версия пузырьковой сортировки. На сегодняшний день это самый

эффективный метод сортировки. Сравнение методов сортировок показывает,

что при n>100 наихудшим является метод пузырька, метод QuickSort в 2 – 3

раза лучше, чем HeapSort, и в 3 – 7 раз, чем метод Шелла.

Рассмотрим алгоритмы и реализацию некоторых методов.

15.3.1. Метод пузырька

В алгоритме сортировки методом пузырька сравниваются два соседних

элемента. Если они расположены в неправильной последовательности, то

выполняется перестановка этих элементов. Сортировка осуществляется пу-

тем многократного прохождения по списку элементов. При сортировке по

возрастанию элементы с малыми значениями поднимаются вверх в начало

списка, подобно пузырькам воздуха в воде. Процедура пузырьковой сорти-

ровки имеет вид

type vec = array[1..100] of extended;

ind = array[1..100] of integer;

Procedure PuzSort(var a:vec; n:integer);

var k,kol:integer; // Метод Пузырька

w:extended;

p:boolean;

begin

kol:=1;

repeat

p:=true;

for k:=1 to n-kol do

Page 92: НовыеЛекции ОАиП

92

if a[k]>a[k+1] then

begin

w:=a[k];

a[k]:=a[k+1];

a[k+1]:=w;

p:=false;

end;

inc(kol);

until p;

end;

В общем случае для сортировки требуется n–1 проход по массиву. Что-

бы исключить ненужные проходы, если массив уже полностью или частично

отсортирован, используется не цикл с заданным количеством повторений

(for kol := 1 to n – 1 do), а оператор repeat с флажком p.

15.3.2. Метод прямого выбора

Сортировка осуществляется путем многократного прохождения по спи-

ску элементов. На каждом (k-ом) проходе находится минимальный элемент

с к-го по n-й элементы, который затем переставляется с к-м элементом. Про-

цедура этой сортировки имеет вид

Procedure PramSort(var a:vec; n:integer);

var k,i,m:integer;

w:extended;

begin

for k:=1 to n-1 do

begin

m:=k;

for i:=k+1 to n do

if a[i]<a[m] then m:=i;

w:=a[m]; a[m]:=a[k]; a[k]:=w;

end;

end;

15.3.3. Метод Шелла

Алгоритм Шелла намного эффективнее, чем метод пузырька. Сначала

сравниваются отдаленные, а затем близкорасположенные элементы. Пере-

менная kol содержит интервал, разделяющий сравниваемые элементы. На-

чальное значение kol равно половине количества элементов. В процессе сор-

тировки значение kol уменьшается в два раза на каждом проходе, пока не

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

Процедура сортировки Шелла имеет вид

Page 93: НовыеЛекции ОАиП

93

Procedure ShellSort(var a:vec; n:integer);

var k,kol:integer; //Метод Шелла

w:extended;

p:boolean;

begin

kol:=n div 2; // Зазор

repeat

repeat

p:=true;

for k:=1 to n-kol do

if a[k]>a[k+kol] then

begin

w:=a[k];

a[k]:=a[k+kol];

a[k+kol]:=w;

p:=false;

end;

until p;

kol:=kol div 2;

until kol=0;

end;

Полезный совет: перестановка элементов со сложными типами данных

– довольно длительный процесс. Поэтому рекомендуется вместо переста-

новки самих данных переставлять индексы. Такой прием используется прак-

тически во всех коммерческих приложениях. В этом случае процедура сор-

тировки Шелла имеет вид

type ind=array[1..100] of integer;

Procedure ShellSortInd(a:vec; n:integer; var nom:ind);

var k,kol,w:integer;

p:boolean;

begin

for k:=1 to n do nom[k]:=k;

kol:=n div 2; // Зазор

repeat

repeat

p:=true;

for k:=1 to n-kol do

if a[nom[k]]>a[nom[k+kol]] then

begin

w:=nom[k];

nom[k]:=nom[k+kol];

nom[k+kol]:=w;

p:=false;

Page 94: НовыеЛекции ОАиП

94

end;

until p;

kol:=kol div 2;

until kol=0;

end;

15.3.4. Метод Хоара (Hoare)

В алгоритме Хоара сначала выбирается так называемое опорное значе-

ние. Затем элементы со значением, меньше опорного, переносятся влево, а

со значением, большим или равным ему, – вправо. Таким образом, на пер-

вом шаге алгоритм Хоара делит элементы на два раздела: со значениями,

меньшими опорного, и со значениями, большими или равными ему. Затем

подпрограмма, рекурсивно вызывая сама себя, продолжает разбивку разде-

лов. В каждом разделе выбирается новое опорное значение, и элементы раз-

дела переставляются влево и вправо. Процесс разбивки на разделы рекур-

сивно продолжается до тех пор, пока размер раздела достигнет одного или

двух элементов. Эффективность метода зависит от объема данных и выбора

метода опорного сечения. В приведенном ниже алгоритме в качестве опор-

ного выбирается средний элемент раздела. Процедура сортировки Хоара

имеет вид

Procedure QuickSort(var a:vec; low,high:integer);

var l,r:integer; // Метод Хоара

op,w:extended;

begin

op:=a[(low+high) div 2]; // Опорный элемент

// Перенос элементов, меньших опорного, влево, а больших - вправо

l:=low; r:=high;

repeat

while (l<=high) and (a[l]<op) do inc(l);

while (r>=low) and (a[r >op) do dec(r);

if l<=r then begin

w:=a[l]; a[l]:=a[r]; a[r]:=w;

inc(l); dec(r);

end;

until l>r;

if r>low then QuickSort(a,low,r);

if l<high then QuickSort(a,l,high);

end;

Page 95: НовыеЛекции ОАиП

95

ТЕМА 16. РАБОТА СО СПИСКАМИ НА ОСНОВЕ

ДИНАМИЧЕСКИХ МАССИВОВ

16.1. Работа со списками

В практике программирования довольно часто встречается задача обра-

ботки набора однотипных данных, количество которых меняется в зависимо-

сти от ситуации. Их надо разместить в оперативной памяти и по мере надоб-

ности с ними работать: добавлять новые данные в список, освобождаться от

старых данных, находить нужную информацию. Показательным примером

является задача обслуживания очереди заказов на покупку товара. Данные

могут содержать информацию о заказчике: ФИО, адрес, финансовые возмож-

ности и др. По мере появления новых заказчиков их дописывают в конец оче-

реди, по мере поступления товара и обслуживания заказчиков из начала оче-

реди данные об этих заказчиках стираются. При решении подобных задач

программисты вводят понятие списка.

Список – это последовательность однотипных элементов (данных), с

которыми надо работать в оперативной памяти: добавлять новые элементы в

группу, удалять использованные, сортировать, находить нужные. В процессе

работы список может возрастать и уменьшаться. Простейшая форма органи-

зации списка – это массив данных. Данные, размещенные в массиве, имеют

свой номер (индекс), что придает эффект «видимости» каждому элементу.

Для организации работы со списками на основе динамического массива, не-

обходимы процедуры добавления нового элемента в список на заданную по-

зицию, удаление элемента с заданным номером, процедуры поиска и сорти-

ровки. Две последние операции рассмотрены ранее.

16.2. Добавление элемента в список на заданную позицию

При добавлении нового элемента в список необходимо выделить па-

мять, на один элемент большую существующей, затем скопировать старый

список в новый раздел памяти, сдвинув элементы от заданной позиции до

конца списка на одну позицию правее и добавить на освободившееся место

новый элемент. Для организации добавления элемента avs на позицию nvs

можно создать следующую процедуру:

Type Tspis=integer; // Описание базового типа массива

var a:array of Tspis; // Указатель на динамический массив

procedure addvec(avs:Tspis; nvs:integer);

begin // Вставка avs на nvs-ю позицию

setlength(a,high(a)+2); // Новая длина массива

for k:=high(a)-1 downto nvs do a[k+1]:=a[k]; // Сдвиг

a[nvs]:=avs; // Вставка

end;

Page 96: НовыеЛекции ОАиП

96

Напомним, что при задании нового размера массива процедурой set-

length() старые значения элементов массива сохраняются.

16.3. Удаления элемента с заданным номером

Процедура удаления элемента с номером nyd тоже требует, кроме вы-

деления новой памяти и копирования, еще и «схлопывания», т. е. сдвига эле-

ментов с (nyd+1)-го до конца списка на одну позицию влево, чтобы запол-

нить освободившуюся nyd-ю позицию. Процедура имеет вид;

procedure delvec(nyd:integer);

begin

for k:=nyd+1 to high(a) do a[k-1]:=a[k]; // Сдвиг

setlength(a,high(a)); // Новая длина массива

end;

Это простая схема хорошо работает для небольших списков, но у нее

есть существенный недостаток: при каждом добавлении приходится менять

размер выделенной памяти и, что еще хуже, сдвигать часть элементов на одну

позицию вправо или влево.

16.4. Пример программы

Ниже приведен пример программы создания списка на основе динами-

ческого массива. При нажатии кнопки Button1 в список добавляется новый

элемент со случайным значением в интервале min‚max (компоненты Edit1,

Edit2) на позицию, не нарушающую сортировки. Таким образом, последова-

тельно нажимая кнопку Button1, формируем отсортированный список. При

нажатии кнопки Button2 из списка удаляется элемент с номером, задаваемым

в компоненте Edit3.

Page 97: НовыеЛекции ОАиП

97

Рис. 16.1. Вид формы выполняеиой программы

unit Unit1; Листинг 16.1

interface

uses Windows,Messages,SysUtils,Variants,Classes,

Graphics,Controls,Forms,Dialogs,Buttons,StdCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Label1: TLabel;

Label2: TLabel;

Button1: TButton;

Button2: TButton;

Memo1: TMemo;

BitBtn1: TBitBtn;

procedure Button1Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure Edit1Change(Sender: TObject);

procedure Edit2Change(Sender: TObject);

procedure Edit3Change(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure BitBtn1Click(Sender: TObject);

private

Page 98: НовыеЛекции ОАиП

98

{ Private declarations }

public

{ Public declarations }

end;

type Tspis=integer; //Описание типа динам. массива

var

Form1: TForm1;

a:array of Tspis; //Указатель на динам. массив

k:integer;

implementation

{$R *.dfm}

procedure addvec(avs:Tspis; nvs:integer);

begin // Вставка avs на nvs-ю позицию

setlength(a,high(a)+2);// Новая длина массива

for k:=high(a)-1 downto nvs do a[k+1]:=a[k];

a[nvs]:=avs;

end;

procedure delvec(nyd:integer);

begin // Удаление элемента с nyd-ой позиции

for k:=nyd+1 to high(a) do a[k-1]:=a[k];

setlength(a,high(a));// Новая длина массива

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

if (edit1.text='') or (edit2.text='') then

button1.enabled:=false;

if edit3.text='' then button2.enabled:=false;

end;

procedure TForm1.Edit1Change(Sender: TObject);

begin

if (edit1.text<>'') and (edit2.text<>'') then

button1.enabled:=true;

end;

procedure TForm1.Edit2Change(Sender: TObject);

begin

if (edit1.text<>'') and (edit2.text<>'') then

button1.enabled:=true;

end;

Page 99: НовыеЛекции ОАиП

99

procedure TForm1.Edit3Change(Sender: TObject);

begin

if edit3.text<>'' then button2.enabled:=true;

end;

procedure TForm1.Button1Click(Sender: TObject);

var min,max,n:integer; // Добавить

w:Tspis;

begin

min:=strtoint(edit1.text);

max:=strtoint(edit2.text);

randomize;

w:=min+random(max-min+1); // Новый элемент

if high(a)=-1 then

begin setlength(a,1); a[0]:=w;end;//если список пуст

else

begin

n:=high(a)+1;

for k:=0 to high(a) do//Находим позицию вставки

if w<a[k] then begin n:=k; break; end;

addvec(w,n); // Вставка нового элемента

end;

memo1.clear;

for k:=0 to high(a) do

memo1.Lines.Add(inttostr(k+1)+'.'+inttostr(a[k]));

end;

procedure TForm1.Button2Click(Sender: TObject);

var n:integer; // Удалить

begin

n:=strtoint(edit3.Text)-1;

if n>high(a) then

begin

edit3.Clear; button2.enabled:=false; exit;

end;

delvec(n); // Удаление n-го элемента

memo1.clear;

for k:=0 to high(a) do

memo1.Lines.Add(inttostr(k+1)+'.'+inttostr(a[k]));

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

Page 100: НовыеЛекции ОАиП

100

begin

a:=nil; // Освобождение памяти

end;

end.

Page 101: НовыеЛекции ОАиП

101

ТЕМА 17. СВЯЗАННЫЕ СПИСКИ НА ОСНОВЕ

РЕКУРСИВНЫХ ДАННЫХ

17.1. Определение стека и очереди

Ранее была рассмотрена простейшая форма организации списка – на

основе динамических массивов данных. Недостатком таких списков является

то, что при добавлении или удалении элементов в список приходится копиро-

вать динамические массивы и менять размер выделенной памяти, чтобы пере-

строить массив, сдвигая на одну позицию все элементы расположенные пра-

вее места вставки (удаления). Более эффективная организация списка, не тре-

бующая копирования динамических массивов, может осуществляться на ос-

нове рекурсивного типа данных. Рекурсивный тип данных при своем описа-

нии допускает обращение к самому себе. В Object Pascal рекурсивный тип

данных представляет собой запись, содержащую набор полей для хранения

информационной части элемента и одного (односвязный) или двух (двухсвяз-

ный список) полей, представляющих собой указатели (т. е. адреса) на сосед-

ний или соседние элементы списка.

Связанный список – это структура данных в виде списка, элементы ко-

торого связаны друг с другом с помощью указателей. Наибольшее распро-

странение получили две формы списка – стек и очередь.

Стек – это список с одной точкой входа. Данные добавляются в список

и удаляются из него только с одной стороны списка (вершины стека). Таким

образом, реализуется принцип – «первым вошел – последним вышел». На-

глядный пример – трубка, запаянная с одного конца и заполняемая шариками,

имеющими диаметр, равный внутреннему диаметру трубки. Первый встав-

ляемый шарик всегда будет доставаться последним.

Очередь – это список с двумя точками входа. С одной стороны после-

довательности данные добавляются в список (в конец очереди), с другой сто-

роны списка данные удаляются из него (из начала очереди). Таким образом,

реализуется принцип – «первым вошел – первым вышел». Наглядный пример

– трубка, открытая с обеих сторон, заполняемая шариками, имеющими диа-

метр, равный внутреннему диаметру трубки. С одной стороны трубки шарики

добавляются в нее, с другой вынимаются.

17.2. Понятие рекурсивных данных и односвязных списков

Рекурсивный тип данных для односвязных списков имеет вид:

Type Tinf=integer; // Описание типа информационной части

TSel=^Sel; // Описание типа указателя на элемент односвязных списков

Sel=record

inf : Tinf;

a : TSel;

Page 102: НовыеЛекции ОАиП

102

end;

Тип Tinf содержит описание информационной части элемента списка,

которая в каждом конкретном случае своя. В данном случае и при последую-

щем изложении материала будет использована эта простейшая структура ин-

формационной части. Не следует забывать переопределить еѐ в той или

иной конкретной программе. Как видим, описание типа TSel содержит внут-

ри обращение к самому себе (a:TSel), т. е. оно рекурсивно. При этом a являет-

ся указателем на ячейку памяти точно такой же структуры. В поле inf разме-

щается информационная часть элемента списка, причем, по крайней мере, в

одном из полей inf, а иногда и в отдельном поле записи расположены сведе-

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

Это поле будем обозначать key:Tkey, а сведения называть ключом. С помо-

щью такого рекурсивного типа организуются однонаправленные связанные

списки следующим образом: элементы списка размещаются в ячейках памяти

типа TSel, причем в поле a каждой ячейки помещается адрес следующей за

ней ячейки (рис. 17.1):

Рис 17.1. Связанный список

Все ячейки динамически размещаются в куче по адресам sp1, sp2, …, spk.

При такой организации списков очень просто удалять или вставлять новые

ячейки. Так, чтобы удалить ячейку с адресом sp2, в адресную часть предше-

ствующей ячейки нужно занести адрес последующей ячейки и освободить

память, занимаемую удаляемой ячейкой ( sp1^.a:=sp3; dispose(sp2);) (см. рис.

17.2).

Рис 17.2. Удаление элемента из связанного списка

sp1 sp2 sp3 sp k-1 sp k

a1

inf1

a2

inf2

a3

inf3

ak-1

infk-1

ak

infk

sp1 sp2 sp3 sp k-1 sp k

a1

inf1

a2

inf2

a3

inf3

ak-1

infk-1

ak

infk

Page 103: НовыеЛекции ОАиП

103

Для добавления новой ячейки между ячейками с адресами sp1 и sp2, необхо-

димо создать новую ячейку, занести в нее информационную часть, в адрес-

ную часть предшествующей ячейки занести адрес новой ячейки, а в адресную

часть новой ячейки адрес последующей ячейки (new(sp); sp^.inf:=inf;

sp1^.a:=sp; sp^.a:=sp2;) (см. рис. 17.3).

Рис. 17.3. Добавление новой ячейки в связанный список

Адресная часть последней ячейки spk^.a:=nil; Для стека задается вершина

стека, равная адресу 1-й ячейки (в обозначениях рис. 17.1) w:=sp1;, а для од-

носвязной очереди адрес начала очереди w1:=sp1; и адрес конца очереди

(адрес последней ячейки) wk:=spk; .

Пример. Создать стек, содержащий целые числа, и найти количество

положительных элементов стека

Type

Tinf=integer; // Описание типа информационной части

TSel=^Sel;

Sel=record

inf:Tinf;

a:TSel;

end;

var k,n,kol:integer;

w,t:TSel;

begin

n:=strtoint(edit1.Text); // Количество элементов стека

w:= nil; Randomize; // Вершина стека

for k:=1 to n do

sp1 sp2

a1

inf1

a2

inf2

aвст

infвст

Page 104: НовыеЛекции ОАиП

104

begin

New(t); // Создаем новый элемент

t^.inf:=random(101)-50; // Запись информационной части

t^.a:=w; // В адресную часть заносим прежнюю вершину

w:=t; // Задаем новую вершину

end;

ListBox1.Clear;

t:=w; kol:=0;

while t<>nil do

begin

k:=t^.inf; // Читаем информ. часть текущего элемента

ListBox1.items.add(inttostr(k));

if k>0 then inc(kol);

t:=t^.a; // Задаем адрес следующего элемента

end;

label1.Caption:='Кол. полож. элементов стека = ' +inttostr(kol);

end;

Для работы с односвязными списками необходимо создать, например,

модуль List1S, содержащий описание рекурсивного типа и набор специали-

зированных процедур.

17.3. Процедуры для работы со стеками

Добавить новый элемент в стек

procedure AddStek(var w:TSel; inf:Tinf);

var t:TSel;

begin

New(t); // Создать новый элемент

t^.inf:=inf; // Запись информационной части

t^.a:=w; // В адресную часть заносим прежнюю вершину

w:=t; // Задаем новую вершину

end;

Прочитать n-й элемент стека ( от вершины )

procedure ReadStek(w:TSel; n:integer; var inf:Tinf);

var i:integer;

t:TSel;

begin

if w=nil then exit;

t:=w; // Текущий адрес=вершине

for i:=1 to n do

begin

inf:=t^.inf;

Page 105: НовыеЛекции ОАиП

105

t:=t^.a; // Задаем адрес следующего элемента

end;

end;

Прочитать и удалить последний элемент стека ( 1-й от вершины )

procedure DelLast(var w:TSel; var inf:Tinf);

var t:TSel;

begin

if w=nil then exit; // Стек пуст

inf:=w^.inf;

t:=w; // Запоминаем адрес вершины

w:=w^.a; // За новую вершину стека берем адрес след элем

dispose(t); // Освобождаем память

end;

Удалить стек

procedure DelStek(var w:TSel);

var inf:Tinf;

begin

while w<>nil do DelLast(w,inf);

end;

Вывод стека в ListBox

procedure WrtStek(w:Tsel; LS:TListBox);

var t:Tsel;

begin

LS.clear;

t:=w; // Текущий адрес = вершине стека

while t<>nil do

begin

LS.Items.Add(intToStr(t^.inf));

t:=t^.a; // Задаем адрес след элемента

end;

end;

Перестановка адресов двух соседних элементов, следующих за элемен-

том с адресом sp

procedure RevAfter(sp:TSel);

var t:TSel;

begin

t:=sp^.a^.a;

sp^.a^.a:=t^.a;

t^.a:=sp^.a;

sp^.a:=t;

Page 106: НовыеЛекции ОАиП

106

end;

Обмен информации между элементом с адресом sp и следующим за

ним

Procedure Revinf(sp:TSel);

var inf:Tinf;

begin

inf:=sp^.inf;

sp^.inf:=sp^.a^.inf;

sp^.a^.inf:=inf;

end;

Пузырьковая сортировка стека перестановкой адресов

procedure SortAfter(var w:TSel);

var p,t:Tsel;

inf:Tinf;

begin

if (w=nil)or(w^.a=nil) then exit; // Пуст или 1 элемент

AddStek(w,0); // Добавляем пустой элемент

t:=nil;

repeat

p:=w;

while p^.a^.a<>t do

begin

if p^.a^.inf>p^.a^.a^.inf then RevAfter(p);

p:=p^.a;

end;

t:=p^.a;

until w^.a^.a=t;

DelLast(w,inf); // Удаляем пустой элемент

end;

Пузырьковая сортировка стека обменом информации

procedure Sortinf(w:TSel);

var p,t:Tsel;

begin

if (w=nil)or(w^.a=nil) then exit; // Пуст или 1 элемент

t:=nil;

repeat

p:=w;

while p^.a<>t do

begin

if p^.inf>p^.a^.inf then Revinf(p);

p:=p^.a;

Page 107: НовыеЛекции ОАиП

107

end;

t:=p;

until w^.a=t;

end;

17.4. Процедуры для работы с односвязными очередями

Добавление нового элемента в начало очереди

procedure AddBeg(var w1,wk:TSel; inf:Tinf);

var t:TSel;

begin

if w1=nil then begin // Если очередь пуста

new(w1);

w1^.inf:=inf;

w1^.a:=nil;

wk:=w1;

end

else begin

new(t);

t^.inf:=inf;

t^.a:=w1;

w1:=t;

end;

end;

Добавление нового элемента в конец очереди

procedure AddEnd(var w1,wk:TSel; inf:Tinf);

var t:TSel;

begin

if wk=nil then begin // Если очередь пуста

new(wk);

wk^.inf:=inf;

wk^.a:=nil;

w1:=wk;

end

else begin

new(t);

t^.inf:=inf;

t^.a:=nil;

wk^.a:=t;

wk:=t;

end;

end;

Page 108: НовыеЛекции ОАиП

108

Добавление нового элемента в середину стека или очереди после эле-

мента с адресом sp

procedure AddAfter(sp:TSel; inf:Tinf);

var t:TSel;

begin

if sp^.a=nil then exit; // Нельзя вставлять в конец

new(t);

t^.inf:=inf;

t^.a:=sp^.a;

sp^.a:=t;

end;

Чтение и удаление элемента из начала очереди

procedure DelBeg(var w1,wk:TSel; var inf:Tinf);

var t:tsel;

begin

if w1=nil then exit; // Если очередь пуста

inf:=w1^.inf;

t:=w1;

w1:=w1^.a; // новое начало - адрес след элемента

dispose(t); // Освобождаем память

if w1=nil then wk:=nil;

end;

Чтение и удаление элемента из середины стека или очереди после эле-

мента с адресом sp

procedure DelAfter(sp:TSel; var inf:Tinf);

var t:tsel;

begin // Нельзя удалять последний элемент

if (sp^.a=nil) or (sp^.a^.a=nil) then exit;

t:=sp^.a; // Адрес удаляемого элемента

inf:=t^.inf; // Читаем информацию

sp^.a:=t^.a; // Задаем адрес эл. стоящего за удаляемым

dispose(t); // Освобождаем память

end;

Удаление очереди

procedure DelSpis(var w1,wk:TSel);

var a:Tinf;

begin

while w1<>nil do DelBeg(w1,wk,a);

end;

Page 109: НовыеЛекции ОАиП

109

Процедура сортировки очереди слиянием двух отсортированных оче-

редей SortSl() требует двух вспомогательных процедур: слияния двух отсор-

тированных очередей в одну (отсортированную) slip() и разбиения очереди

на две div1s():

procedure slip (var sq1,sqk,sr1,srk,sp1,spk:TSel);

var infq,infr:Tinf;

begin

sp1:=nil; spk:=nil;

while (sq1<>nil) and (sr1<>nil) do

begin

DelBeg(sq1,sqk,infq);

DelBeg(sr1,srk,infr);

if infq<infr then begin

AddEnd(sp1,spk,infq);

AddBeg(sr1,srk,infr);

end

else begin

AddEnd(sp1,spk,infr);

AddBeg(sq1,sqk,infq);

end;

end;

while sq1<>nil do

begin

DelBeg(sq1,sqk,infq);

AddEnd(sp1,spk,infq);

end;

while sr1<>nil do

begin

DelBeg(sr1,srk,infr);

AddEnd(sp1,spk,infr);

end;

end;

procedure div1s(var sp1,spk,sq1,sqk,sr1,srk:TSel);

var inf:Tinf;

begin

sr1:=nil; srk:=nil;

sq1:=nil; sqk:=nil;

while sp1<>nil do

begin

DelBeg(sp1,spk,inf);

AddEnd(sq1,sqk,inf);

Page 110: НовыеЛекции ОАиП

110

if sp1<>nil then begin

DelBeg(sp1,spk,inf);

AddEnd(sr1,srk,inf);

end;

end;

end;

procedure SortSl(var w1,wk:TSel);

var sq1,sr1,sqk,srk:TSel;

begin

if w1<>wk then

begin

div1s(w1,wk,sq1,sqk,sr1,srk);

sortsl(sq1,sqk);

sortsl(sr1,srk);

slip(sq1,sqk,sr1,srk,w1,wk);

end;

end;

17.5. Пример программы по созданию стека

Создать стек из случайных целых чисел, формированию из него двух

стеков, содержащих четные и нечетные числа, и сортировку методами обме-

на информации и адресов.

Page 111: НовыеЛекции ОАиП

111

Рис. 17.4. Вид формы выполняемой программы

unit Unit1; Листинг 17.1

interface

uses Windows,Messages,SysUtils,Variants,Classes,

Graphics,Controls,Forms,Dialogs,StdCtrls,ExtCtrls,

Buttons;

type

TForm1 = class(TForm)

ListBox1: TListBox;

ListBox2: TListBox;

ListBox3: TListBox;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

BitBtn1: TBitBtn;

BitBtn2: TBitBtn;

RadioGroup1: TRadioGroup;

RadioGroup2: TRadioGroup;

BitBtn3: TBitBtn;

BitBtn4: TBitBtn;

BitBtn5: TBitBtn;

Page 112: НовыеЛекции ОАиП

112

Edit1: TEdit;

Label4: TLabel;

procedure BitBtn1Click(Sender: TObject);

procedure BitBtn2Click(Sender: TObject);

procedure BitBtn3Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure RadioGroup1Click(Sender: TObject);

procedure BitBtn5Click(Sender: TObject);

procedure RadioGroup2Click(Sender: TObject);

procedure BitBtn4Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var Form1: TForm1;

implementation

uses List1S;

var w1,w2,w3:TSel;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

bitbtn2.enabled:=false; // Разбить

bitbtn3.enabled:=false; // Сортировать

bitbtn5.Enabled:=false; // Очистить

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

var k,n : integer; // Создать стек

begin

n:=strtoint(edit1.Text);

ListBox1.Clear;

ListBox2.Clear;

ListBox3.Clear;

w1:=nil; Randomize;

for k:=1 to n do AddStek(w1,Random(100));

WrtStek(w1,ListBox1);

bitbtn2.enabled:=true; // Разбить

bitbtn3.enabled:=true; // Сортировать

bitbtn5.Enabled:=true; // Очистить

end;

Page 113: НовыеЛекции ОАиП

113

procedure TForm1.BitBtn2Click(Sender: TObject);

var t:TSel; // Разбить стек

k:integer;

begin

ListBox2.Clear; ListBox3.Clear;

t:=w1; w2:=nil; w3:=nil;

while t<>nil do

begin

k:=t^.inf; //Читаем информ. часть текущего элемента

if odd(k) then AddStek(w2,k)

else AddStek(w3,k);

t:=t^.a; // Задаем адрес следующего элемента

end;

WrtStek(w2,ListBox2);

WrtStek(w3,ListBox3);

bitbtn2.enabled:=false; // Разбить

end;

procedure TForm1.BitBtn3Click(Sender: TObject);

begin // Сортировать

case RadioGroup2.ItemIndex of

0: begin

case RadioGroup1.ItemIndex of

0: SortAfter(w1);

1: Sortinf(w1);

end;

WrtStek(w1,ListBox1);

end;

1: begin

case RadioGroup1.ItemIndex of

0: SortAfter(w2);

1: Sortinf(w2);

end;

WrtStek(w2,ListBox2);

end;

2: begin

case RadioGroup1.ItemIndex of

0: SortAfter(w3);

1: Sortinf(w3);

end;

WrtStek(w3,ListBox3);

end;

end;

bitbtn3.enabled:=false;

Page 114: НовыеЛекции ОАиП

114

end;

procedure TForm1.RadioGroup1Click(Sender: TObject);

begin

bitbtn3.enabled:=true;

end;

procedure TForm1.RadioGroup2Click(Sender: TObject);

begin

bitbtn3.Enabled:=true;

end;

procedure TForm1.BitBtn5Click(Sender: TObject);

begin // Очистить

listbox1.Clear;

listbox2.Clear;

listbox3.Clear;

DelStek(w1);// Стирание стека

DelStek(w2);// Стирание стека

DelStek(w3);// Стирание стека

bitbtn2.Enabled:=false;

bitbtn3.Enabled:=false;

bitbtn5.Enabled:=false;

end;

procedure TForm1.BitBtn4Click(Sender: TObject);

begin // Сlose

DelStek(w1); // Стирание стека

DelStek(w2); // Стирание стека

DelStek(w3); // Стирание стека

end;

end.

17.6. Работа с двухсвязными очередями

Двухсвязные списки организуются, когда требуется просматривать спи-

сок, как в прямом, так и в обратном направлениях. Эта проблема легко реша-

ется, если ввести рекурсивный тип с двумя адресными ячейками:

Type Tinf=integer; // Описание типа информационной части

Tseld=^seld; // Описание типа указателя на элемент 2-связных списков

seld=record

inf:Tinf;

a,b:Tseld;

end;

Page 115: НовыеЛекции ОАиП

115

Структура двухсвязного списка, схемы удаления внутреннего элемента

списка и вставки нового элемента в середину списка приведены соответст-

венно на рис. 17.5 – 17.7 ниже.

Рис. 17.5. Двухсвязный связанный список

Рис. 17.6. Удаление элемента из двухсвязного списка

sp1 sp2 sp3 sp k-1 sp k

a1

inf1

b1

a2

inf2

b2

a3

inf3

b3

ak-1

infk-1

bk-1

ak

infk

bk

sp1 sp2 sp3 sp k-1 sp k

a1

inf1

b1

a2

inf2

b2

a3

inf3

b3

ak-1

infk-1

bk-1

ak

infk

bk

Page 116: НовыеЛекции ОАиП

116

Рис. 17.7. Вставка нового элемента в двухсвязный список

17.7. Процедуры для работы с двусвязными очередями

Для работы с двухсвязными списками необходимо создать, например,

модуль List2S, содержащий описание рекурсивного типа и набор специали-

зированных процедур.

Вставка нового элемента в начало очереди

Procedure AddBegD(var w1,wk:Tseld; inf:Tinf);

var t:Tseld;

begin

New(t);

t^.inf:=inf;

t^.b:=nil;

if w1=nil then begin t^.a:=nil; w1:=t; wk:=t; end

else begin t^.a:=w1; w1^.b:=t; w1:=t; end;

end;

Вставка нового элемента в конец очереди

Procedure AddEndD(var w1,wk:Tseld; inf:Tinf);

var t:Tseld;

begin

New(t);

spn spn+1

an

infn

bn

an+1

infn+1

bn+1

aвст

infвст

bвст

Page 117: НовыеЛекции ОАиП

117

t^.inf:=inf;

t^.a:=nil;

if wk=nil then begin t^.b:=nil; w1:=t; wk:=t; end

else begin t^.b:=wk; wk^.a:=t; wk:=t; end;

end;

Вставка нового элемента после элемента с адресом sp

Procedure AddAfterD(sp:Tseld; inf:Tinf);

var t:Tseld;

begin // Нельзя добавлять в конец

if (sp=nil) or (sp^.a=nil) then exit;

New(t);

t^.inf:=inf;

t^.a:=sp^.a;

t^.b:=sp;

sp^.a:=t;

t^.a^.b:=t;

end;

Вставка нового элемента перед элементом с адресом sp

Procedure AddBefD(sp:Tseld; inf:Tinf);

var t:Tseld;

begin // Нельзя добавлять в начало

if (sp=nil) or (sp^.b=nil) then exit;

New(t);

t^.inf:=inf;

t^.a:=sp;

t^.b:=sp^.b;

sp^.b^.a:=t;

sp^.b:=t;

end;

Чтение и удаление элемента с начала очереди

Procedure DelBegD(var w1,wk:Tseld; var inf:Tinf);

var t:Tseld;

begin

if w1=nil then exit;

inf:=w1^.inf;

t:=w1;

if w1=wk then begin w1:=nil; wk:=nil; end

else begin w1^.a^.b:=nil; w1:=w1^.a; end;

Dispose(t);

end;

Page 118: НовыеЛекции ОАиП

118

Чтение и удаление элемента с конца очереди

Procedure DelEndD(var w1,wk:Tseld; var inf:Tinf);

var t:Tseld;

begin

if wk=nil then exit;

inf:=wk^.inf;

t:=wk;

if w1=wk then begin w1:=nil; wk:=nil; end

else begin wk^.b^.a:=nil; wk:=wk^.b; end;

Dispose(t);

end;

Чтение и удаление внутреннего элемента очереди c адресом sp

Procedure DelD(sp:Tseld; var inf:Tinf);

begin // Нельзя удалять первый или последний

if (sp=nil) or (sp^.a=nil) or (sp^.b=nil) then exit;

inf:=sp^.inf;

sp^.b^.a:=sp^.a;

sp^.a^.b:=sp^.b;

Dispose(sp);

end;

Удаление очереди

Procedure DelSpisD(var w1,wk:Tseld);

var inf:Tinf;

begin

while w1<>nil do DelBegD(w1,wk,inf);

end;

Вывод в Memo с начала очереди

procedure WrtBegD(w1:Tseld; s:TMemo);

var t:Tseld;

begin

t:=w1; s.clear;

while t<>nil do

begin

s.lines.add(IntToStr(t^.inf));

t:=t^.a;

end;

end;

Вывод в Memo с конца очереди

procedure WrtEndD(wk:Tseld; s:TMemo);

var t:Tseld;

Page 119: НовыеЛекции ОАиП

119

begin

t:=wk; s.clear;

while t<>nil do

begin

s.lines.add(IntToStr(t^.inf));

t:=t^.b;

end;

end;

Процедура сортировки очереди слиянием двух отсортированных оче-

редей SortSlD() требует двух вспомогательных процедур: слияния двух от-

сортированных очередей в одну (отсортированную) slipD() и разбиения оче-

реди на две div2s():

procedure slipD (var sq1,sqk,sr1,srk,sp1,spk:TSeld);

var infq,infr:Tinf;

begin

sp1:=nil; spk:=nil;

while (sq1<>nil) and (sr1<>nil) do

begin

DelBegD(sq1,sqk,infq);

DelBegD(sr1,srk,infr);

if infq<infr then begin

AddEndD(sp1,spk,infq);

AddBegD(sr1,srk,infr);

end

else begin

AddEndD(sp1,spk,infr);

AddBegD(sq1,sqk,infq);

end;

end;

while sq1<>nil do

begin

DelBegD(sq1,sqk,infq);

AddEndD(sp1,spk,infq);

end;

while sr1<>nil do

begin

DelBegD(sr1,srk,infr);

AddEndD(sp1,spk,infr);

end;

end;

procedure div2s(var sp1,spk,sq1,sqk,sr1,srk:TSeld);

Page 120: НовыеЛекции ОАиП

120

var inf:Tinf;

begin

sr1:=nil; srk:=nil;

sq1:=nil; sqk:=nil;

while sp1<>nil do

begin

DelBegD(sp1,spk,inf);

AddEndD(sq1,sqk,inf);

if sp1<>nil then begin

DelBegD(sp1,spk,inf);

AddEndD(sr1,srk,inf);

end;

end;

end;

procedure sortslD(var w1,wk:TSeld);

var sq1,sr1,sqk,srk:TSeld;

begin

if w1<>wk then

begin

div2s(w1,wk,sq1,sqk,sr1,srk);

sortslD(sq1,sqk);

sortslD(sr1,srk);

slipD(sq1,sqk,sr1,srk,w1,wk);

end;

end;

17.8. Пример программы по работе с двухсвязным списком

Создать два двухсвязных списка из случайных целых чисел. Заменить

элементы между максимальным и минимальным 1-го списка вторым списком.

Создать новый список из удаленных элементов. Отсортировать результи-

рующий список..

Page 121: НовыеЛекции ОАиП

121

Рис. 17.8. Вид формы выполняемой программы

unit Unit1; Листинг 17.2

interface

uses Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, ExtCtrls, StdCtrls,Grids,

Buttons, List2S;

type TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

Button3: TButton;

BitBtn1: TBitBtn;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

Button4: TButton;

Memo1: TMemo;

Memo2: TMemo;

Memo3: TMemo;

Memo4: TMemo;

Memo5: TMemo;

Button5: TButton;

Memo6: TMemo;

Page 122: НовыеЛекции ОАиП

122

Label1: TLabel;

Label2: TLabel;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

procedure Button5Click(Sender: TObject);

procedure BitBtn1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

w11, w12, w13, wk1, wk2, wk3 : Tseld;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

begin

memo1.Clear; memo2.Clear; memo3.Clear;

memo4.Clear; memo5.Clear; memo6.Clear;

w11:=nil; wk1:=nil; w12:=nil; wk2:=nil;

w13:=nil; wk3:=nil; Randomize;

button4.enabled:=false;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin // добавить в 1-й список

AddEndD(w11,wk1,Random(100));

WrtBegD(w11,memo1); // вывод 1-го списка

button3.Enabled:=true;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin // Добавить во 2-й список

AddEndD(w12,wk2,Random(100));

WrtBegD(w12,memo2); // вывод 2-го списка

end;

Page 123: НовыеЛекции ОАиП

123

procedure TForm1.Button3Click(Sender: TObject);

var t,tmin,tmax:Tseld; // Выполнить

i,min,max:integer;

inf:Tinf;

begin

t:=w11; tmin:=t; tmax:=t;

i:=1; min:=1; max:=1;

while t<>nil do

begin

if t^.inf<tmin^.inf then begin tmin:=t; min:=i; end;

if t^.inf>tmax^.inf then begin tmax:=t; max:=i; end;

t:=t^.a; inc(i);

end;

if min=max then

begin

ShowMessage('Заново создать 1-й список');

button3.Enabled:=false;

exit;

end;

if min>max then

begin t:=tmin; tmin:=tmax; tmax:=t; end;

if abs(max-min)>1 then

begin

t:=tmin^.a;

while t<>tmax do

begin//Удаление элем. между min и max в 1-м списке

DelD(t,inf);

AddEndD(w13,wk3,inf); //Вставка их в 3-й список

t:=tmin^.a;

end;

end;

WrtBegD(w11,memo3); // вывод промежуточного 1-го списка

WrtBegD(w13,memo4); // вывод вырезанного списка

t:=tmin;

while w12<>nil do

begin

DelBegD(w12,wk2,inf); // Вставка 2-го списка

AddAfterD(t,inf); // между min и max 1-го списка

t:=t^.a;

end;

WrtBegD(w11,memo5); // вывод итогового списка

button4.enabled:=true;

end;

Page 124: НовыеЛекции ОАиП

124

procedure TForm1.Button4Click(Sender: TObject);

begin // Сортировать

sortslD(w11,wk1);

WrtBegD(w11,memo6);

end;

procedure TForm1.Button5Click(Sender: TObject);

begin // Очистить

memo1.Clear; memo2.Clear; memo3.Clear;

memo4.Clear; memo5.Clear; memo6.Clear;

DelSpisD(w11,wk1); // Удаление очереди

DelSpisD(w12,wk2); // Удаление очереди

DelSpisD(w13,wk3); // Удаление очереди

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

begin // Close

DelSpisD(w11,wk1); // Удаление очереди

DelSpisD(w12,wk2); // Удаление очереди

DelSpisD(w13,wk3); // Удаление очереди

end;

end.

Page 125: НовыеЛекции ОАиП

125

ТЕМА 18. АЛГОРИТМЫ РЕШЕНИЯ СИСТЕМ ЛИНЕЙНЫХ

АЛГЕБРАИЧЕСКИХ РЕШЕНИЙ

18.1. Основные понятия и определения

Выделяют четыре основные задачи линейной алгебры: решение СЛАУ,

вычисление определителя матрицы, нахождение обратной матрицы, опреде-

ление собственных значений и собственных векторов матрицы. Задача оты-

скания решения СЛАУ с n неизвестными – одна из наиболее часто встречаю-

щихся в практике вычислительных задач, т. к. большинство методов решения

сложных задач основано на сведении их к решению некоторой последова-

тельности СЛАУ. Обычно СЛАУ записывается в виде

1

; 1 ,n

ij j i

j

a x b i n или в матричном виде ,Ax b

11 12 1 1 1

21 22 2 2 2

1 2

...

..., ,

... ......

...

n

n

n nn n nn

a a a x b

a a a x bA x b

x ba a a

(18.1)

Здесь А и b заданы, требуется найти x *, удовлетворяющий (18.1). Известно,

что если определитель матрицы det 0A , то СЛАУ имеет единственное ре-

шение. В противном случае решение либо отсутствует (если 0b ), либо име-

ется бесконечное множество решений (если 0b ). При решении систем,

кроме условия det 0A , важно чтобы задача была корректной, т. е. чтобы

при малых погрешностях правой части b и (или) коэффициентов ija по-

грешность решения *x также оставалась малой. Признаком некорректности,

или плохой обусловленности, является близость к нулю определителя матри-

цы. Плохо обусловленная система двух уравнений геометрически соответст-

вует почти параллельным прямым (рис. 18.1).

Page 126: НовыеЛекции ОАиП

126

Точка пересечения таких прямых (решение) при малейшей погрешности ко-

эффициентов резко сдвигается. Обусловленность (корректность) СЛАУ ха-

рактеризуется числом 1 1A A . Чем дальше от 1, тем хуже обу-

словлена система. Обычно при 310 система некорректна и требует специ-

альных методов решения - методов регуляризации. Приведенные ниже мето-

ды применимы только для корректных систем. Методы решения СЛАУ де-

лятся на прямые и итерационные.

Прямые методы дают в принципе точное решение (если не учитывать

ошибок округления) за конечное число арифметических операций. Для хоро-

шо обусловленных СЛАУ небольшого порядка 200n применяются практи-

чески только прямые методы. Наибольшее распространение среди прямых

методов получили метод Гаусса для СЛАУ общего вида, его модификация

для трехдиагональной матрицы – метод прогонки и метод квадратного

корня для СЛАУ с симметричной матрицей.

Итерационные методы основаны на построении сходящейся к точно-

му решению *x рекуррентной последовательности векторов 1 2 *, , , ..., .o k

kx x x x x Итерации выполняют до тех пор, пока норма

разности 1

1max .k k

k kk i i

ix x x x ( - заданная малая величина).

Итерационные методы выгодны для систем большого порядка n>100, а

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

ных методов решения СЛАУ объясняется возможностью большого выбора

рекуррентных последовательностей, определяющих метод. Наибольшее рас-

пространение среди итерационных методов получили одношаговые методы

простой итерации и Зейделя с использованием релаксации. Для контроля

полезно найти невязку полученного решения x :

Рис. 18.1. Решения СЛАУ

Page 127: НовыеЛекции ОАиП

127

1

1

max ;n

k ki ik n

i

b a x

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

описание алгоритмов указанных методов решения СЛАУ.

18.2. Прямые методы решения СЛАУ

18.2.1. Метод Гаусса

Метод основан на приведении с помощью преобразований, не меняю-

щих решение, исходной СЛАУ (18.1) с произвольной матрицей к СЛАУ с

верхней треугольной матрицей вида

11 1 12 2 1 1

22 2 2 2

...

...

.............................................

n n

n n

nn n n

a x a x a x b

a x a x b

a x b

(18.2)

Этап приведения к системе с треугольной матрицей называется прямым хо-

дом метода Гаусса. Решение системы с верхней треугольной матрицей

(18.2), как легко видеть, находится по формулам, называемым обратным хо-

дом метода Гаусса:

1

1/ ; , 1, 2, ..., 1.

n

n n nn k k ki i

kk i k

x b a x b a x k n na

(18.3)

Прямой ход метода Гаусса осуществляется следующим образом: вычтем из

каждого m-го уравнения (m=2, 3,.., n) первое уравнение, умноженное на

1 11/ ,ma a и вместо m-го уравнения подставим полученное. В результате в мат-

рице системы исключаются все коэффициенты 1-го столбца ниже диагональ-

ного. Затем, используя 2-е полученное уравнение, аналогично исключим эле-

менты второго столбца (m=3, 4,.., n) ниже диагонального и т. д. Такое исклю-

чение называется циклом метода Гаусса. Проделывая последовательно эту

операцию с расположенными ниже k-го уравнениями (k=1, 2 ,..., n-1), мы при-

ходим к системе вида (18.2). При указанных операциях решение СЛАУ не из-

меняется. На каждом k-м шаге преобразований прямого хода элементы мат-

риц изменяются по формулам прямого хода метода Гаусса:

, 1, 1, , ;

, 1, .

mkmi mi ki

kk

mkm m k

kk

aa a a k n i k n

a

ab b b m k n

a

(18.4)

Элементы kka называются главными. Заметим, что если в ходе расчетов по

данному алгоритму на главной диагонали окажется нулевой элемент 0kka ,

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

каждый цикл по k начинать с перестановки строк: среди элементов k-го

Page 128: НовыеЛекции ОАиП

128

столбца ,mka k m n находят номер p главного, т. е. наибольшего по моду-

лю, и меняют местами строки k и p. Такой выбор главного элемента значи-

тельно повышает устойчивость алгоритма к ошибкам округления, т. к. в фор-

мулах (18.4) при этом производится умножение на числа /mk kka a меньшие

единицы и ошибка, возникшая ранее, уменьшается.

18.2.2. Метод прогонки

Многие задачи (например, решение дифференциальных уравнений 2-го

порядка) приводят к необходимости решения СЛАУ с трехдиагональной мат-

рицей:

1 1 1 1

2 2 2 2 2

3 3 3 3 3

1 1 1 1 1

0 0 .. 0 0 0

0 .. 0 0 0

0 .. 0 0 0

.. .. .. .. .. .. .. .. .. ..

0 0 0 0 ..

0 0 0 0 .. 0

n n n n n

n n n n

q r x d

p q r x d

p q r x d

p q r x d

p q x d

(18.5)

или коротко эту систему записывают в виде

1 1 1 2 1

1 1

1

,

,

,

2 1.

i i i i i i i

n n n n n

q x r x d

p x q x r x d

p x q x d

i n

(18.6)

В этом случае расчетные формулы метода Гаусса значительно упрощаются.

После исключения поддиагональных элементов в результате прямого хода

метода Гаусса и последующего деления каждого уравнения на диагональный

элемент систему (18.5) можно привести к виду

1 11

2 22

1 11

1 0 .. 0 .. 0 0

0 1 .. 0 .. 0 0

.. .... .. .. .. .. .. .. ..

0 0 0 .. 0 .. 1

0 0 0 .. 0 .. 0 1

n nn

n n

x

x

x

x

(18.7)

При этом формулы прямого хода для вычисления ,i i , как нетрудно полу-

чить, имеют вид

1 1 1 1 1 1

1 1 1

/ ; / ;

/( ); ( ) /( );

2,3,..., 1.

i i i i i i i i i i i i

–r q d q

r q p d p q p

i n

(18.8)

Когда такое преобразование (прямой ход) сделано, формулы обратного хода

метода Гаусса получаются в виде

Page 129: НовыеЛекции ОАиП

129

1 1

1

( ) /( );

,

1, 2, ..., 1.

n n n n n n n

i i i i

x d p q p

x x

i n n

(18.9)

Расчетные формулы (18.8), (18.9) получили название метод прогонки. Доста-

точным условием того, что в формулах метода прогонки не произойдет деле-

ния на нуль и расчет будет устойчив относительно погрешностей округления,

является выполнение неравенства i i iq p r (хотя бы для одного i должно

быть строгое неравенство).

18.2.3. Метод квадратного корня

Метод предназначен для решения СЛАУ с симметричной матрицей.

Этот метод основан на представлении такой матрицы в виде произведения

трех матриц: ,TA S D S где D – диагональная с элементами di= 1; S –

верхняя треугольная ( 0,iks если i>k, причем 0iis ), TS – транспонирован-

ная нижняя треугольная. Матрицу S можно по аналогии с числами трактовать

как корень квадратный из матрицы A, отсюда и название метода. Если мат-

рицы S и D известны, то решение исходной системы TA x S D S x b

сводится к последовательному решению трех систем – двух c треугольной и

одной с диагональной матрицами:

; ;TS z b Dy z Sx y , (18.10)

где ,z DS x y S x . Решение систем (18.10) ввиду треугольности матрицы

S осуществляется по формулам, аналогичным обратному ходу метода Гаусса:

1

1 1 11 1

1

1

/ ; ( ) / ; 2, 3 ,..., ;

/ ; ( ) / ; 1, 2, ..., 1.

i

i i k k ki ii i

k

n

n n nn i i ik k ii

k i

y b s d y b d y s s d i n

x y s x y s x s i n n

Нахождение элементов матрицы S (извлечение корня из А) осуществляется

по рекуррентным формулам:

21

1

( )k

k kk i ik

i

d sign a d s ;

12

1

;

1,2,..., ;

k

kk kk i ik

i

s a d s

k n

(18.11)

1

1

( ) /( );

1, 2, ..., .

k

kj kj i ik ij kk k

i

s a d s s s d

j k k n

Page 130: НовыеЛекции ОАиП

130

В этих формулах сначала полагаем k=1 и последовательно вычисляем

1 11 11 11( );d sign a s a и все элементы первой строки матрицы

1( , 1)jS s j , затем полагаем k=2, вычисляем 22s и вторую строку 1 js для j>2

и т.д. Метод квадратного корня почти вдвое эффективнее метода Гаусса, т. к.

полезно использует симметричность матрицы. Функция sign(x) возвращает –

1 для всех x<0 и +1 для всех x>0.

18.3. Итерационные методы решения СЛАУ

18.3.1. Метод простой итерации

В соответствии с общей идеей итерационных методов исходная систе-

ма (18.1) должна быть приведена к виду, разрешенному относительно x :

( )x Gx c x , (18.13)

где G – матрица; c – столбец свободных членов. При этом решение (18.13)

должно совпадать с решением (18.1). Затем строится рекуррентная последо-

вательность первого порядка в виде 1 1( ) , 1, 2, ...k k kx x Gx c k

В начале вычислений задается некоторое начальное приближение 0x (напри-

мер, 0 01 1, ..., 1)nx x , для окончания – некоторое малое . Получаемая по-

следовательность будет сходиться к точному решению, если норма матрицы

1G . Привести исходную систему к виду (18.13) можно различными спосо-

бами, например, ( ) ( ) ,x x Ax b E A x b Gx c где E – единич-

ная матрица; α - некоторый параметр, подбирая который, можно добиться,

чтобы 1.G E A В частном случае, если исходная матрица A имеет

преобладающую главную диагональ, т. е. 1

n

ii ik

kk i

a a , то преобразование

(18.1) к (18.13) можно осуществить просто, решая каждое i-е уравнение отно-

сительно ix . В результате получим следующую рекуррентную формулу:

1 1

1 1

/n n

k k ki i ij j ii ij j i

j jj i

x b a x a g x c . (18.14)

/ ; 0; /ij ij ii ii i i iig a a g c b a .

18.3.2. Метод Зейделя

Метод Зейделя является модификацией метода простой итерации. Суть

его состоит в том, что при вычислении очередного приближения (2 )kix i n

Page 131: НовыеЛекции ОАиП

131

в формуле (18.14) используются вместо 1 11 1, ...,k k

ix x уже вычисленные ранее

1 1, ..., ,k kix x т. е. (18.14) преобразуется к виду

1

1

1 1

i nk k ki ij j ij j i

j j i

x g x g x c (18.17)

Такое усовершенствование позволяет ускорить сходимость итераций почти в

два раза. Кроме того, данный метод может быть реализован на компьютере

без привлечения дополнительного массива, так как полученное новое kix сра-

зу засылается на место старого. Схема алгоритма аналогична схеме метода

простой итерации, если x0

j заменить на xj и убрать строки x0

i=1, x0

i=xi.

18.3.3. Понятие релаксации

Методы простой итерации и Зейделя сходятся примерно так же, как

геометрическая прогрессия со знаменателем G . Если норма матрицы G

близка к 1, то сходимость очень медленная. Для ускорения сходимости ис-

пользуется метод релаксации. Суть его в том, что полученное по методу про-

стой итерации или Зейделя очередное значение kix пересчитывается по фор-

муле

1,(1 )k k ki i ix x x (18.19)

где 0 < 2 – параметр релаксации. Если < 1 – нижняя релаксация, если

>1–- верхняя релаксация. Параметр подбирают так, чтобы сходимость

метода достигалась за минимальное число итераций.

18.4. Нахождение обратных матриц

Матрица A-1

называется обратной по отношению к квадратной матрице

A, если их произведение равно единичной матрице E

AA-1

=A-1

A=E

Если определитель матрицы A отличен от нуля (такие матрицы называются

невырожденными или неособенными), то обратная матрица всегда существу-

ет. При этом detA-1

=1/detA. Обозначим искомую обратную матрицу n-го по-

рядка X.

X=A-1

=

11 12 1

21 22 2

1 2

...

...

... ... ... ...

...

n

n

n n nn

x x x

x x x

x x x

Равенство AX=E, служащее определением обратной матрицы X может

быть использовано для нахождения элементов обратной матрицы. Мы имеем

систему 2n линейных алгебраических уравнений для 2n неизвестных элемен-

тов обратной матрицы, которую можно решить одним из методов решения

Page 132: НовыеЛекции ОАиП

132

систем линейных алгебраических уравнений. Вся эта система распадается на

n групп независимых уравнений с n неизвестными в каждой. Все они имеют

одну и ту же матрицу коэффициентов A, отличаясь лишь свободными члена-

ми. Запишем равенство AX=E в виде

n1, i k,

ij jk 0, i k,

j 1

a x {

i=1,2,...,n ; k=1,2,...,n

т. е. в k-й группе независимых уравнений неизвестными являются элементы

k-го столбца искомой обратной матрицы, а отличен от нуля и равен единице

только свободный член k-го уравнения. Таким образом, для нахождения эле-

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

алгебраических уравнений n-го порядка. Так как все они имеют одну и ту же

матрицу коэффициентов A, то при использовании метода Гаусса процедура

прямого хода (исключение неизвестных для приведения исходной системы к

эквивалентной системе с верхней треугольной матрицей) проводится только

один раз. При этом решение этих n систем можно объединить в одной схеме,

рассматривая одновременно n столбцов свободных членов.

Page 133: НовыеЛекции ОАиП

133

ТЕМА 19. СОБСТВЕННЫЕ ЗНАЧЕНИЯ И СОБСТВЕННЫЕ

ВЕКТОРЫ МАТРИЦЫ

Собственными значениями квадратной матрицы A называют числа ,

удовлетворяющие соотношению

Ax= x, где x=[x1, x2, …, xn]T – вектор - столбец, (19.1)

которое может быть представлено в виде (A- E)x=0, где E – единичная мат-

рица. Матрица

D=A- E =

11 12 1

21 22 2

1 2

...

...

... ... ... ...

...

n

n

n n nn

a a a

a a a

a a a

,

называется характеристической матрицей матрицы A. Собственные значе-

ния матрицы A находят как корни характеристического уравнения

det D=0, (19.2)

которое является алгебраическим уравнением n-го порядка. Вектор x={x1, x2,

... ,xn}, соответствующий некоторому собственному значению и удовлетво-

ряющий системе уравнений (19.1) называется собственным вектором матри-

цы A.

19.1. Интерполяционный метод

В области расположения собственных значений зададим n+1 произ-

вольное значение 0, 1, ..., n. В каждой из выбранных точек i вычислим оп-

ределитель f( )=det D=det (A- E). По таблице i, f( i) построим интерполя-

ционный полином Pn( ), который в силу единственности будет характеристи-

ческим. Теперь для нахождения собственных значений необходимо найти n

корней алгебраического уравнения Pn( )=0, что можно сделать одним из ме-

тодов нахождения корней нелинейных уравнений. В этом случае метод не

требует вычисления определителя на каждой итерации. Однако здесь задача

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

Отметим некоторые свойства собcтвенных значений для частных типов ис-

ходной матрицы.

1. Все собственные значения симметричной матрицы действительны.

2. Если собственные значения матрицы действительны и различны, то

соответствующие им собственные векторы ортогональны и образуют базис

рассматриваемого пространства. Следовательно, любой вектор в данном про-

странстве можно выразить через совокупность линейно независимых собст-

венных векторов.

3. Если две матрицы A и B подобны, т. е. они связаны соотношением

B=P-1

AP (19.3)

Page 134: НовыеЛекции ОАиП

134

то их собственные значения совпадают. Преобразование подобия (19.3) мож-

но использовать для упрощения исходной матрицы, а задачу о вычислении ее

собственных значений свести к аналогичной задаче для более простой матри-

цы. Очевидно, самым лучшим упрощением исходной матрицы A было бы

приведение ее к треугольному виду. Определитель треугольной матрицы ра-

вен произведению ее диагональных элементов, поэтому характеристический

многочлен в этом случае имеет вид (b11 - ) (b22 - ) ... (bnn - )=0. Таким обра-

зом, собственные значения треугольной матрицы равны ее диагональным

элементам. То же самое относится и к диагональной матрице.

19.2. Метод вращений Якоби

Метод вращений Якоби применяется только для симметричных матриц

A (A=AT) и решает полную проблему собственных значений и собственных

векторов таких матриц. Метод основан на приведении действительной сим-

метричной матрицы A к диагональной D путем преобразования подобия D=T-

1AT, где T

-1 – обратная матрица, а поскольку для симметричных матриц A

матрица преобразования подобия T является ортогональной (T-1

=TT), то

D=TTAT, где T

T – транспонированная матрица. Диагональные элементы мат-

рицы D будут собственными значениями исходной матрицы A, а столбцы

матрицы T будут являться соответственно собственными векторами. Матрица

T находится как предел бесконечного произведения элементарных матриц

вращения T=T1T2T3 ... . Алгоритм метода следующий:

Для известной на s-й итерации матрицы A(s)

(A(0)

=A) выбирается макси-

мальный по модулю недиагональный элемент akm(s)

матрицы A(s)

(akm(s)

=max|aij(s)

|, i<j). Находится такая ортогональная матрица T(s)

, чтобы в ре-

зультате преобразования подобия A(s+1)

=T(s)T

A(s)

T(s)

произошло обнуление эле-

мента akm(s+1)

матрицы A(s+1)

. В качестве ортогональной матрицы выбирается

матрица вращения T(s)

представляющую собой единичную матрицу в которой

элементы tkm(s)

=–sinφ(s)

, tmk(s)

=sinφ(s)

, tkk(s)

=cosφ(s)

, tmm(s)

=cosφ(s)

, где угол враще-

ния φ(s)

определяется из условия akm(s+1)

=0:

φ(s)

=1/2*arctg(2akm(s)

/(akk(s)

–amm(s)

)), если akk(s)

≠amm(s)

,

φ(s)

=π/4, если akk(s)

=amm(s)

.

Затем вычисляется матрица A(s+1)

=T(s)T

A(s)

T(s)

. Процесс продолжается до тех

пор, пока все недиагональные элементы матрицы A не станут по модулю

меньше заданной точности ε: |aij| < ε, i < j. Отметим, что на каждой итерации

выполняется соотношение a2

kk(s+1)

+a2

mm(s+1)

=a2

kk(s)

+a2

mm(s)

+2akm(s)

, т. е. сумма

квадратов диагональных элементов на каждой итерации увеличивается. Соот-

ветственно на эту же величину уменьшается и сумма квадратов недиагональ-

ных элементов, откуда и следует сходимость к диагональной матрице. Эле-

менты, которые однажды обратились в нуль, при последующих итерациях

могут стать ненулевыми.

Page 135: НовыеЛекции ОАиП

135

19.3. Итерационный метод

Часто в практических вычислениях нужны не все собственные значе-

ния, а лишь некоторые из них. Для решения частичной проблемы собствен-

ных значений, состоящей в определении одного или нескольких собственных

значений и соответствующих им собственных векторов, обычно используют-

ся итерационные методы. Строится итерационный процесс, который сходит-

ся к одному собственному значению и собственному вектору. Итерационный

процесс строится на основе системы уравнений (19.1) ( k )

x( k )

= Ax( k – 1 )

, k=1, 2, ... (19.4)

Если наибольшее по модулю собственное значение – простое, то, начиная с

произвольного начального вектора x(0)

вычисляют последовательность x(1)

,

x(2)

, x(3)

,.... При возрастании k векторы x(k)

будут приближаться к собственному

вектору, принадлежащему доминирующему собственному значению . При

этом на каждой итерации (k)

вычисляется из условия, чтобы наибольшая по

модулю координата вектора x(k)

равнялась единице. Итерационный процесс

завершается при выполнении условия |((k)

- (k-1)

)/(k)

| < , где – заданная

относительная погрешность вычисления собственного значения. Скорость

сходимости итерационного процесса зависит от удачного выбора начального

приближения. Если начальный вектор x(0)

близок к истинному собственному

вектору, то итерации сходятся быстро. Если нужно искать не наибольшее, а

наименьшее собственное значение матрицы А, то умножая левую и правую

части уравнения (19.1) на A-1

получаем уравнение вида x/ =A-1

x. В этом

случае итерационный процесс строится по формуле x(k)

/(k)

=A-1

x(k – 1)

, Эта за-

дача отличается от ранее рассматриваемой (19.4) тем, что здесь будет вычис-

ляться наибольшее собственное значение 1/ , что будет достигнуто при наи-

меньшем значении (собственные значения матриц A и A-1

обратны друг дру-

гу).

Page 136: НовыеЛекции ОАиП

136

ТЕМА 20. АППРОКСИМАЦИЯ ФУНКЦИЙ

20.1. Определение аппроксимации

Одной из наиболее часто встречающихся задач является установление

характера зависимости между различными величинами. Математической мо-

делью зависимости одной величины от другой является понятие функции

y=f(x). Аппроксимацией называется получение некой функции (x) прибли-

женно описывающей какую-то функциональную зависимость f(x), заданную

таблицей значений, либо заданную в виде, неудобном для вычислений. Функ-

цию (x) при этом выбирают такой, чтобы она была максимально удобной

для последующих расчетов. Основной подход к решению этой задачи заклю-

чается в том, что функция (x) выбирается зависящей от нескольких свобод-

ных параметров c1, c2, …, cn, т. е. φ(x)=φ(x, c1, c2, …, cn), , значения которых

подбираются из некоторого условия близости f(x) и (x). Обоснование спосо-

бов нахождения удачного вида функциональной зависимости ( , )x с и под-

бора параметров с составляет задачу теории аппроксимации функций. В за-

висимости от способа подбора параметров с получают различные методы

аппроксимации, среди которых наибольшее распространение получили ин-

терполяция и среднеквадратичное приближение, частным случаем которого

является метод наименьших квадратов. Наиболее простой, хорошо изучен-

ной и нашедшей широкое применение в настоящее время является линейная

аппроксимация, при которой выбирают функцию ( , )x с , линейно завися-

щую от параметров с , т. е. в виде обобщенного многочлена:

1 1

1

( , ) ( ) ... ( ) ( )n

n n k k

k

x с с x с x с x , (20.1)

где 1{ ( ), ..., ( )}nx x – известное семейство линейно независимых (базисных)

функций. В качестве семейства {φk(x)} в принципе могут быть выбраны лю-

бые элементарные функции: например тригонометрические, экспоненты, ло-

гарифмические или комбинации таких функций. Важно, чтобы система ба-

зисных функций была полной, т. е. обеспечивающей аппроксимацию f(x) мно-

гочленом (20.1) с заданной точностью при n . Приведем хорошо известные

и часто используемые системы. При интерполяции обычно используется се-

мейство линейно независимых функций {φk(x)=xk-1

}. Для среднеквадратичной

аппроксимации удобнее в качестве семейства {φk(x)} брать ортогональные на

интервале [-1, 1] многочлены Лежандра:

1 2 1 11; ; 2 1 , 2,3, ...,k k kx x x x k x x k x k n ;

1

1

0;k lx x dx k l .

Page 137: НовыеЛекции ОАиП

137

Заметим, что если функция ( )f x задана на отрезке [a, b], то при использова-

нии этой системы необходимо предварительно осуществить преобразование

координат 2

2

b ax x

b a, приводящее интервал a x b к интервалу

1 1x . Для аппроксимации периодических функций используют ортого-

нальную на отрезке [a, b] систему тригонометрических функций

cos(2 ),k

x ax k

b a sin(2 )k

x ax k

b a. В этом случае обобщенный

многочлен (20.1) записывается в виде: 1

( ) ( )n

k k k k

k

y c x d x .

20.2. Интерполяция

Интерполяция является одним из способов аппроксимации функций.

Суть ее состоит в следующем. В области значений x, представляющей неко-

торый интервал [a, b], где функции f(x) и (x) должны быть близки, выбирают

упорядоченную систему точек (узлов) 1 2 ... ,nx x x (обозначим

1( , ..., )nx x x ), число которых равно количеству искомых параметров

1 2, , ... , nс с с . Далее, параметры с подбирают такими, чтобы функция ( , )x с

совпадала с функцией f(x) в этих узлах, т. е. φ(xi)=f(xi), i=1, 2, …, n (см. рис.

20.1), для чего решают полученную систему n алгебраических, в общем слу-

чае нелинейных, уравнений. В случае линейной аппроксимации (20.1) систе-

ма для нахождения коэффициентов с линейна и имеет следующий вид:

1

( ) ; 1, 2, ..., ; ( ),n

k k i i i i

k

с x f i n f f x (20.2)

Система базисных функций {φk(x)}, используемых для интерполяции, должна

быть чебышевской, т. е. такой, чтобы определитель матрицы системы (20.2)

был отличен от нуля и, следовательно, задача интерполяции имела единст-

венное решение. Для большинства практически важных приложений при ин-

терполяции наиболее удобны обычные алгебраические многочлены, ибо они

легко обрабатываются.

Page 138: НовыеЛекции ОАиП

138

Интерполяционным многочленом называют алгебраический многочлен сте-

пени n-1, совпадающий с аппроксимируемой функцией в n выбранных точ-

ках. Общий вид алгебраического многочлена

2 1 11 1 2 3

1

( , ) ( ) ...n

n kn n k

k

x с P x с с x с x с x a x . (20.3)

Матрица системы (20.2) в этом случае имеет вид

11 1

12 2

0

1

1 ..

1 ..;

.. .. .. ..

1 ..

n

n

k m

n k m

nn n

x x

x xG G x x

x x

(20.4)

и ее определитель отличен от нуля, если точки xi разные. Поэтому задача

(20.2) имеет единственное решение, т. е. для заданной системы различных то-

чек существует единственный интерполяционный многочлен. Погрешность

аппроксимации функции f(x) интерполяционным многочленом степени n-1,

построенным по n точкам, можно оценить, если известна ее производная по-

рядка n, по формуле

1

2 ( )( ) ( ) ( / 2) ,

( 1)

nn

n С n

С

d f xf x P x h

n dx 1max | | .i i

ih x x (20.5)

Из (20.5) следует, что при h 0 порядок погрешности p при интерполяции ал-

гебраическим многочленом равен количеству выбранных узлов p=n. Величи-

на может быть сделана малой как за счет увеличения n, так и уменьшения h.

В практических расчетах используют, как правило, многочлены невысокого

порядка (n 6), в связи с тем, что с ростом n резко возрастает погрешность

вычисления самого многочлена из-за погрешностей округления.

Рис. 20.1. Аппроксимируемая и аппроксимирующая

функции

Page 139: НовыеЛекции ОАиП

139

20.3. Многочлены и способы интерполяции

Один и тот же многочлен можно записать по-разному, например 2 21 2 ( 1)x x x . Поэтому в зависимости от решаемых задач применяют

различные виды представления интерполяционного многочлена и способы

интерполяции. Наряду с общим представлением (20.3) наиболее часто в при-

ложениях используют интерполяционные многочлены в форме Лагранжа и

Ньютона. Их особенность в том, что не надо находить параметры с , так как

многочлены в этой форме прямо записаны через значения таблицы

( , ), 1 ...i ix y i n

20.3.1. Интерполяционный многочлен Ньютона

Аппроксимация в виде (20.1), дополненная системой (20.2) называется

аппроксимацией общего вида. Недостатком такого вида аппроксимации явля-

ется необходимость решения системы линейных алгебраических уравнений

(20.2) для определения коэффициентов 1 2( , , ..., )nс с с с . Ньютоном была

предложена форма записи многочлена (20.3) в виде, не требующем решения

системы линейных алгебраических уравнений

1

1 1 1 2

1

( ) ( )( )...( ) ,n

n T T T T k k

k

N x f x x x x x x (20.6)

где Tx – текущая точка, в которой надо вычислить значение многочлена, k –

разделенные разности порядка k, которые вычисляются по следующим рекур-

рентным формулам:

1 1 1 1 21 1 2 1 2

1 2

( ) ( )( ) ; ( ) ; . . .i i i i i i i

i i i i i

i i i i

f f f x x f x xf x x f x x x

x x x x

20.3.2. Линейная и квадратичная интерполяции

Иногда при интерполяции по заданной таблице при m>3 точек приме-

няют квадратичную (n=3) или линейную (n=2) интерполяцию. В этом случае

для приближенного вычисления значения функции f(x) в текущей точке xТ

находят в таблице ближайшие к этой точке (i-1), i, (i+1)-й узлы из общей

таблицы, строят интерполяционный многочлен Ньютона первой или второй

степени по формулам

11 1 1 1

1

( ) ( ) ; ;i iT i T i i T i

i i

f fN x f x x x x x

x x (20.7)

1 1

1 12 1 1 1 1,

1 1

( ) ( ) ( )( ) ;

i i i i

i i i iT T T i T i i T i

i i

f f f f

x x x xN x N x x x x x x x x

x x

Page 140: НовыеЛекции ОАиП

140

и за значение f(x) принимают 1( )N x (линейная интерполяция) или 2( )N x

(квадратичная интерполяция).

20.3.3. Интерполяционный многочлен Лагранжа

Лагранжем была предложена своя форма записи многочлена (20.3) в

виде, не требующем решения системы линейных алгебраических уравнений:

1

1 1

( )nn

T in T k

k k iii k

x xL x f

x x. (20.8)

Произведение 1

nT i

k iii k

x x

x x выбрано так, что во всех узлах, кроме k-го, оно об-

ращается в нуль, а в k-м узле оно равно единице:

1

1,

0,

nT kT i

T kk iii k

при x xx x

при x xx x

Поэтому из выражения (20.8) видно, что 1( )n i iL x f

20.3.4. Интерполяция общего вида

Следует отметить, что ввиду громоздкости многочлены Ньютона и Ла-

гранжа уступают по эффективности расчета многочлену общего вида (20.3),

если предварительно найдены коэффициенты .с Поэтому, когда требуется

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

таблице, оказывается выгодно вначале один раз найти коэффициенты с (ре-

шив систему линейных алгебраических уравнений) и затем использовать

формулу (20.3). Коэффициенты с находят прямым решением системы (20.2)

c матрицей (20.4), затем вычисляют его значения по экономно программи-

руемой формуле (алгоритм Горнера)

1 1 2 2 1( ... ( ( ) ...)n n n nP x c x c x c x c xc . (20.9)

20.4. Среднеквадратичная аппроксимация

Суть среднеквадратичной аппроксимации заключается в том, что пара-

метры с функции ,x c подбираются такими, чтобы обеспечить минимум

квадрата расстояния между функциями f(x) и ,x c , т. е. из условия

21,...,

min ( ) ,n

Lc cf x x c . (20.12)

В случае линейной аппроксимации (20.1) задача (20.12) сводится к решению

СЛАУ для нахождения необходимых коэффициентов с :

Page 141: НовыеЛекции ОАиП

141

2 2

1

, ; 1,..., ,n

i k k iL Lk

c f i n (20.13)

где 2 2

, ,i k iL Lf – скалярные произведения в L2. Матрица системы

(20.13) симметричная, и ее следует решать методом квадратного корня. Осо-

бенно просто эта задача решается, если выбрана ортогональная система

функций k x , т. е. такая, что

2

0,

, .i k

k

i k

i k

Тогда матрица СЛАУ (20.13) диагональная и параметры c находятся по фор-

мулам

2

, kk

k

fc . В этом случае представление (20.1) называется обобщен-

ным рядом Фурье, а kc называются коэффициентами Фурье.

20.4.1. Метод наименьших квадратов

Метод наименьших квадратов является частным случаем среднеквадра-

тичной аппроксимации. При использовании метода наименьших квадратов

аналогично задаче интерполяции в области значений x, представляющей не-

который интервал [a, b], где функции f(x) и (x) должны быть близки, выби-

рают систему различных точек (узлов) x1, ..., xm, число которых больше, чем

количество искомых параметров 1, ..., nc c , .m n Далее, потребовав, чтобы

сумма квадратов невязок во всех узлах была минимальна (см. рис. 20.2)

2 2

1 1

min [ ( ) ( , )] min min ( ),m m

j j jc c c

j j

f x x c c (20.13)

находим из этого условия параметры 1, ..., nc c .

Рис. 20.2. Аппроксимируемая и аппроксимирующая

функции

Page 142: НовыеЛекции ОАиП

142

В общем случае эта задача сложная и требует применения численных методов

оптимизации. Однако в случае линейной аппроксимации (20.1), составляя ус-

ловия минимума суммы квадратов невязок во всех точках c (в точке ми-

нимума все частные производные должны быть равны нулю):

1 2( , ,..., )0, 1,2,..., ,n

i

c c ci n

c (20.14)

получаем систему n линейных уравнений относительно n неизвестных

1, ..., nc c следующего вида:

1

( ) ( , ), 1,...,n

i k k i

k

c f i n или Gс b , (20.15)

где 1 2 1( ), ( ), ... , ( ) , , ... ,i i i i m mx x x f f f – векторы-столбцы функ-

ций. Элементы матрицы G и вектора b в (20.15) определяются выражениями

1

1

( ) ( ) ( ),

( , ) ( )

m

ik i k i j k j

j

m

i i j i j

j

g x x

b f f x

скалярные произведения векторов.

Система (20.15) имеет симметричную матрицу G и решается методом квад-

ратного корня. При аппроксимации по методу наименьших квадратов обычно

применяют такие функции i , которые используют особенности решаемой

задачи и удобны для последующей обработки.

Page 143: НовыеЛекции ОАиП

143

ТЕМА 21. ВЫЧИСЛЕНИЕ ПРОИЗВОДНЫХ ИНТЕГРАЛОВ

21.1. Формулы численного дифференцирования

Формулы для расчета производной /m md f dx в точке x получаются сле-

дующим образом. Берется несколько близких к x узлов 1 2, , ..., nx x x (n

m+1), называемых шаблоном (точка x может быть одним из узлов). Вычисля-

ются значения ( )i if f x в узлах шаблона, строится интерполяционный мно-

гочлен Ньютона и после взятия производной от этого многочлена 1 /m mnd P dx

получается выражение приближенного значения производной (формула чис-

ленного дифференцирования) через значения функции в узлах шабло-

на: 1/ [ ] /m m n m mm nd f dx f d P dx . При n=m+1 формула численного диф-

ференцирования не зависит от положения точки x внутри шаблона. Так как m-

я производная от полинома m-й степени Pm(x) есть константа, такие формулы

называют простейшими формулами численного дифференцирования. Ана-

лиз оценки погрешности вычисления производной

1

( )max ( )max [ ] max .

( )n

mm

n n mxm im

x x x i

f xd ff x x Ch

n mdx (21.1)

1max ; , 1i ih x x C const n m

показывает, что погрешность минимальна для значения x в центре шаблона и

возрастает на краях. Поэтому узлы шаблона, если это возможно, выбираются

симметрично относительно x. Заметим, что порядок погрешности при h 0

равен n-m 1, и для повышения точности можно либо увеличивать n, либо

уменьшать h (последнее более предпочтительно). Приведем несколько важ-

ных формул, получаемых с использованием (20.7) для равномерного шабло-

на.

21 2 11 1 2[ ( )] ;

df dP f ff x x x x

dx dx h. (21.2)

Простейшая формула (21.2) имеет второй порядок погрешности в центре ин-

тервала и первый по краям.

32 2 1 1 2 31 1 2 2

2[ ( )] (2 )

2

df dP f f f f ff x x x x

dx dx h h (21.3)

Эта формула имеет второй порядок погрешности во всем интервале 1 3x x x

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

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

что из (21.3) получается три важные формулы второго порядка точности

32 3 11 2

( )[ ( )] ;

2

df x f ff x

dx h (21.4)

Page 144: НовыеЛекции ОАиП

144

31 1 2 31 1

( ) 3 4[ ( )] ;

2

df x f f ff x

dx h (21.5)

33 1 2 31 3

( ) 4 3[ ( )] ;

2

df x f f ff x

dx h (21.6)

Для вычисления второй производной часто используют следующую про-

стейшую формулу

2 2

2 1 2 32 1 32 2 2

2[ ( )] ;

d f d P f f ff x x x x

dx dx h, (21.7)

которая имеет второй порядок погрешности в центральной точке x2.

21.2. Формулы численного интегрирования

Формулы для вычисления интеграла ( )

b

a

U f x dx получают следую-

щим образом. Область интегрирования [a, b] разбивают на m малых отрезков

с шагом /h b a m . Значение интеграла по всей области равно сумме ин-

тегралов на отрезках

11

( )i

i

xb m

ia x

f x dx f x dx , где .ix a ih Выбирают

на каждом отрезке 1,i ix x 1 – 5 узлов и строят для каждого отрезка интерпо-

ляционный многочлен соответствующего порядка. Вычисляют интеграл от

этого многочлена на отрезке. В результате получают выражение интеграла

(формулу численного интегрирования) через значения подынтегральной

функции в выбранной системе точек. Такие выражения называют квадратур-

ными формулами.

21.2.1. Формула средних

Формула средних получается, если на каждом i-ом отрезке [xi-1, xi] взять

один центральный узел xi-1/2 = xi - h/2, соответствующий середине отрезка.

Функция на каждом отрезке аппроксимируется многочленом нулевой степени

(константой) P0(x) = f(xi-1/2). В этом случае получим:

1

0 1/ 2 р

1 1

( ) ( )i

i

xb m m

i c

i ia x

f x dx P x dx h f f . (21.8)

Погрешность формулы средних имеет второй порядок по h:

2

р рmax ( ) ( ) .24

b b

с c

a a

hf x dx f f x dx (21.9)

Page 145: НовыеЛекции ОАиП

145

21.2.2. Формула трапеций

Формула трапеций получается при аппроксимации функции f(x) на ка-

ждом отрезке 1,i ix x интерполяционным многочленом первого порядка, т. е.

прямой, проходящей через точки 1 1( , )i ix f , ( , )i ix f . Площадь криволинейной

фигуры заменяется площадью трапеции с высотами 1,i if f и основанием h

1

11 0

1 р

1 1 1

( ) ( )2 2

i

i

xb m m mi i m

i m

i i ia x

f f f ff x dx P x dx h h f f . (21.10)

Погрешность формулы трапеций в два раза больше, чем погрешность форму-

лы средних:

2

р рmax ( ) ( )12

b b

m m

a a

hf x dx f f x dx . (21.11)

21.2.3. Формула Симпсона

Формула Симпсона получается при аппроксимации функции f(x) на ка-

ждом отрезке 1,i ix x интерполяционным многочленом второго порядка (па-

раболой) c узлами 1 1/ 2, ,i i ix x x . После интегрирования параболы получаем

1

2 1 1/ 2

1 1

( ) ( ) ( 4 )6

i

i

xb m m

i i i сu

i ia x

hf x dx P x dx f f f f (21.12)

После приведения подобных членов формула (21.12) приобретает удобный

для программирования вид:

1

01/ 2

1 1

23 2

m mm

i icui i

h f ff f f

Погрешность формулы Симпсона имеет четвертый порядок по h:

4

(4)max ( ) ( )2880

b b

си cu

a a

hf x dx f f x dx . (21.13)

21.2.4. Формулы Гаусса

При построении предыдущих формул в качестве узлов интерполяцион-

ного многочлена выбирались середины и (или) концы интервала разбиения.

При этом оказывается, что увеличение количества узлов не всегда приводит к

уменьшению погрешности (сравни формулы средних и трапеций), т. е. за счет

удачного расположения узлов можно значительно увеличить точность. Суть

методов Гаусса с n узлами состоит в таком расположении этих n узлов ин-

терполяционного многочлена на отрезке 1,i ix x , при котором достигается

минимум погрешности квадратурной формулы. Детальный анализ показыва-

ет, что узлами, удовлетворяющими такому условию, являются нули

ортогональнoго многочлена Лежандра n-й степени. Так, для n=1 один узел

РИС. 4.3

Page 146: НовыеЛекции ОАиП

146

должен быть выбран в центре. Следовательно, метод средних является фор-

мулой Гаусса с одним узлом. Для n=2 узлы на отрезке 1,i ix x должны быть

выбраны следующим образом:

1,21/ 2 0.5773502692

2i i

hx x

и соответствующая формула Гаусса с двумя узлами имеет вид

1 2

1

( ) [ ( ) ( )]2

b m

i i

ia

hf x dx f x f x . (21.15)

Порядок погрешности этой формулы при h 0 – четвертый, т. е. такой же, как

у метода Симпсона, хотя используется только два узла! Для n=3 узлы на от-

резке 1,i ix x выбираются следующим образом:

0 1,2 01/ 2, 0.7745966692

2i i i i

hx x x x

и соответствующая формула Гаусса с тремя узлами имеет вид

1 0 2

1

( ) 5 ( ) 8 ( ) 5 ( )18

b m

i i i

ia

hf x dx f x f x f x . (21.16)

Порядок погрешности этой формулы при h 0 – шестой, т. е. значительно

выше, чем у формулы Симпсона, практически при одинаковых затратах на

вычисления. Следует отметить, что формулы Гаусса, особенно широко при-

меняются для вычисления несобственных интегралов специального вида, ко-

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

Page 147: НовыеЛекции ОАиП

147

ТЕМА 22. МЕТОДЫ РЕШЕНИЯ НЕЛИНЕЙНЫХ

УРАВНЕНИЙ

22.1. Как решаются нелинейные уравнения

Математической моделью многих физических процессов является

функциональная зависимость y=f(x). Поэтому задачи исследования различ-

ных свойств функции f(x) часто возникают в инженерных расчетах. Одной из

таких задач является нахождение значений x, при которых функция f(x) обра-

щается в нуль, т. е. решение уравнения f(x)=0 . (22.1)

Точное решение удается получить в исключительных случаях, и обычно для

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

уравнения (22.1) при этом осуществляется в два этапа:

1. Приближенное определение местоположения, характер и выбор ин-

тересующего нас корня.

2. Уточнение выбранного корня с заданной точностью .

На рис. 22.1 представлены три вида корней:

а) кратный корень: *1 1 1( ) 0, ( ) ( ) 0;f x f f

б) простой корень: *2 2 2( ) 0, ( ) ( ) 0;f x f f

в) вырожденный корень: *3( )f x не существует, 3 3( ) ( ) 0f f .

Как видно из рис. 22.1, в случаях a) и в) значение корня совпадает с точкой

экстремума функции и для нахождения таких корней рекомендуется исполь-

зовать методы поиска минимума функции. На втором этапе вычисление

значения корня с заданной точностью осуществляется одним из итерацион-

ных методов. При этом, в соответствии с общей методологией m-шагового

итерационного метода, на интервале [a, b], где находится интересующий нас

корень x, выбирается m начальных значений x0, x1, …, xm-1 (обычно x0=α, xm-

1=b), после чего последовательно находятся члены (xm, xm+1, ..., xn-1, xn) рекур-

Рис. 22.1. Виды корней нелинейного уравнения

Page 148: НовыеЛекции ОАиП

148

рентной последовательности порядка m по правилу 1( , ..., )k k k mx x x до

тех пор, пока 1n nx x . Последнее значение nx выбирается в качестве

приближенного значения корня (x*

xn), найденного с погрешностью . Мно-

гообразие методов определяется возможностью большого выбора законов

(x). Наиболее часто используемые на практике методы описаны ниже.

22.2. Итерационные методы уточнения корней

22.2.1. Метод простой итерации

Очень часто в практике вычислений встречается ситуация, когда урав-

нение (22.1) записано в виде разрешенном, относительно x: ( )x x (22.2)

Заметим, что переход от записи уравнения (22.1) к эквивалентной записи

(22.2) можно сделать многими способами, например, положив

φ(x)=x+ψ(x)f(x), (22.3)

где ψ(x) – произвольная, непрерывная, знакопостоянная функция (часто дос-

таточно выбрать ψ(x)=const). В этом случае корни уравнения (22.2) являются

также корнями (22.1), и наоборот. Исходя из записи (22.2) члены рекуррент-

ной последовательности в методе простой итерации вычисляются по закону

1( ), 1,2,...k kx x k . (22.4)

Метод является одношаговым, и для начала вычислений достаточно знать од-

но начальное приближение x0=a или x0=b или x0=(a+b)/2. Условием сходимо-

сти метода простой итерации, если ( )x дифференцируема, является выпол-

нение неравенства |φ'(ξ)| < 1 для любого ξ [a, b], x*

[a, b]. (22.5)

Максимальный интервал [a, b], для которого выполняется неравенство (22.5),

называется областью сходимости. При выполнении условия (22.5) метод

сходится, если начальное приближение x0 выбрано из области сходимости.

При этом скорость сходимости погрешности *k kx x к нулю вблизи

корня приблизительно такая же, как у геометрической прогрессии 1k k q

со знаменателем q |φ'(x*)|, т. е. чем меньше q, тем быстрее сходимость, и на-

оборот. Поэтому при переходе от (22.1) к (22.2) функцию ψ(x) в (22.3) выби-

рают так, чтобы выполнялось условие сходимости (22.5) для как можно

большей области [a, b] и с наименьшим q. Удачный выбор этих условий га-

рантирует эффективность расчетов. Часто положительные результаты дает

применение релаксации.

22.2.2. Метод Ньютона

Этот метод является модификацией метода простой итерации и часто

называется методом касательных. Если f(x) имеет непрерывную производную,

тогда, выбрав в (22.3) ψ(x)= -1/f'(x), получаем эквивалентное уравнение x=x–

f(x)/f'(x)=φ(x), в котором q |φ'(x*)|≈0. Поэтому скорость сходимости рекур-

рентной последовательности метода Ньютона

Page 149: НовыеЛекции ОАиП

149

11 1

1

( )( )

( )

kk k k

k

f xx x x

f x (22.6)

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

но равна квадрату погрешности предыдущего 21( *)k kx . Из (22.6)

видно, что этот метод одношаговый (m=1) и для начала вычислений требует-

ся задать одно начальное приближение x0 из области сходимости, опреде-

ляемой неравенством | f(x)f''(x) |<[f'(x)]2. Метод Ньютона получил также вто-

рое название метод касательных благодаря геометрической иллюстрации его

сходимости, представленной на рис. 22.2. Этот метод позволяет находить как

простые, так и кратные корни. Основной его недостаток – малая область схо-

димости и необходимость вычисления производной f'(x).

22.2.3. Метод секущих

Данный метод является модификацией метода Ньютона, позволяющей

избавиться от явного вычисления производной путем ее замены приближен-

ной формулой (21.2). Это эквивалентно тому, что вместо касательной на рис.

22.2 проводится секущая. Тогда вместо процесса (22.6) получаем

11 1

1 1

( )( ),

( ) ( )

kk k k

k k

f x hx x x

f x f x h (22.7)

где h – некоторый малый параметр метода, который подбирается из условия

наиболее точного вычисления производной. Метод одношаговый (m=1), и его

условие сходимости при правильном выборе h такое же, как у метода Ньюто-

на.

Рис. 22.2. Геометрическая интерпретация мето-

да Ньютона

Page 150: НовыеЛекции ОАиП

150

22.2.4. Метод Вегстейна

Этот метод является модификацией предыдущего метода секущих. В

нем предлагается при расчете приближенного значения производной по раз-

ностной формуле использовать вместо точки 1kx h в (22.7) точку 2kx , по-

лученную на предыдущей итерации. Расчетная формула метода Вегстейна:

1 1 21 1 2

1 2

( )( )( , ).

( ) ( )

k k kk k k k

k k

f x x xx x x x

f x f x (22.8)

Метод является двухшаговым (m=2), и для начала вычислений требуется за-

дать два начальных приближения 0 1,x x . Лучше всего x0=a, x1=b. Метод Вег-

стейна сходится медленнее метода секущих, однако, требует в два раза мень-

шего числа вычислений f(x) и за счет этого оказывается более эффективным.

22.2.5. Метод парабол

Предыдущие три метода (Ньютона, секущих, Вегстейна) фактически

основаны на том, что исходная функция f(x) аппроксимируется линейной за-

висимостью вблизи корня и в качестве следующего приближения выбирается

точка пересечения аппроксимирующей прямой с осью абсцисс. Ясно, что ап-

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

квадратичную. На этом и основан один из самых эффективных методов – ме-

тод парабол. Суть его в следующем: в окрестности корня задаются три на-

чальные точки 0 1 2 0 2 1 0 2, , , ( ( ) ( ) 0, ( ) / 2 )x x x f x f x x x x , в этих точках

рассчитываются три значения функции 0 1 2( ) : , ,f x f f f и строится интерпо-

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

2 2

2 2 2( ) ( ) ( )xP a x x b x x c az bz c . (22.9)

Коэффициенты этого многочлена вычисляются по формулам:

z=x-x2; z0=x0-x2; z1=x1-x2; c=f2;

0 2 0 1 2 10 2 0 0

0 1

( ) / ( ) /; ( ) / .

f f z f f za b f f z a z

z z (22.10)

Полином (22.9) имеет два корня:

21, 2 ( 4 ) /(2 ),z b b ac a

из которых выбирается наименьший по модулю zm и рассчитывается следую-

щая точка 2 .m mx x z Если выполняется условие 1 ,mx x то за значение

корня принимается xm, в противном случае одна из крайних точек заменяется

на точку xm: если xm < x1 то x2=x1, f2=f1, x1=xm, f1=f(xm), иначе x0=x1, f0=f1,

x1=xm, f1=f(xm) и процесс повторяется.

22.2.6. Метод деления отрезка пополам

Все вышеописанные методы могут работать, если функция f(x) является

непрерывной и дифференцируемой вблизи искомого корня. В противном слу-

Page 151: НовыеЛекции ОАиП

151

чае они не гарантируют получение решения. Для разрывных функций, а так-

же. если не требуется быстрая сходимость, для нахождения простого корня

на интервале [a, b] применяют надежный метод деления отрезка пополам. Его

алгоритм основан на построении рекуррентной последовательности по сле-

дующему закону: в качестве начального приближения выбираются границы

интервала, на котором имеется один простой корень x0=a, x1=b, далее нахо-

дится середина интервала 0 1( ) / 2,x x x после чего отбрасывается половин-

ка интервала, не содержащая корня. Очередная точка x выбирается как сере-

дина нового, в два раза меньшего, интервала.

Алгоритм метода.

1. Вычисляем 0 0 1 1( ), ( )f f x f f x .

2. Вычисляем 0 1 / 2, ( )mx x x f f x .

3. Если 0 0,mf f то 0 0, ,mx x f f иначе 1 1, .mx x f f

4. Если 1 0 ,x x то повторить с п. 2.

5. Вычисляем корень 0 1* ( ) / 2.x x x

За одно вычисление функции интервал уменьшается вдвое, то есть ско-

рость сходимости невелика, однако метод устойчив к ошибкам округления и

всегда сходится.

Page 152: НовыеЛекции ОАиП

152

ТЕМА 23. РЕШЕНИЕ ОБЫКНОВЕННЫХ

ДИФФЕРЕНЦИАЛЬНЫХ УРАВНЕНИЙ

23.1. Задачи для обыкновенных дифференциальных уравнений

Обыкновенные дифференциальные уравнения или системы таких урав-

нений часто используются для построения математических моделей динами-

ческих процессов, т. е. процессов перехода физических систем из одного со-

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

ния, возникающие в электрических цепях, распространении радиоволн, явле-

ния химической кинетики, движения материальных точек и многое другое.

Однако классы решений, для которых разработаны точные решения, доволь-

но узки и охватывают только малую часть возникающих на практике задач. В

силу этого важное значение имеют приближенные численные методы реше-

ния, ориентированные на широкий класс встречающихся на практике диффе-

ренциальных уравнений. Известно, что заменой переменных дифференциаль-

ное уравнение n-го порядка всегда может быть сведено к эквивалентной сис-

теме n дифференциальных уравнений 1-го порядка. Среди таких систем вы-

делим класс систем, разрешенных относительно производной неизвестных

функций

11 1

1

( )( , , ..., )

. . . . . . . . . . . . . .

( )( , , ..., )

m

mm m

du xf x u u

dx

du xf x u u

dx

(23.1)

Обычно требуется найти решение системы 1( ) ( ), ..., ( )mu x u x u x для значе-

ний x из заданного интервала a x b . Известно, что система (23.1) имеет

бесконечное множество решений, семейство которых в общем случае зависит

от m произвольных параметров 1, ..., mс с c и может быть записано в виде

( , )u u x c . Для определения значений этих параметров, т. е. для выделения

одного нужного решения, надо наложить дополнительно m условий на функ-

ции 1, ..., mu u u . В зависимости от способа постановки дополнительных

условий можно выделить два основных типа задач, наиболее часто встре-

чающихся на практике:

краевая (граничная) задача, когда часть условий задается на границе a

(при x=a), остальные условия – на границе b (при x=b). Обычно это значения

искомых функций на границах;

задача Коши (задача с начальными условиями), когда все условия за-

даны в начале отрезка в виде

0 0

1 1( ) ; ...; ( )m mu a u u a u . (23.2)

Page 153: НовыеЛекции ОАиП

153

При изложении методов решения задачи Коши воспользуемся компактной

записью задачи (23.1), (23.2) в векторной форме:

0( , ); ( )du

f x u u a udx

. (23.3)

Требуется найти ( )u x для a x b.

23.2. Основные положения метода сеток для решения задачи Коши

Чаще всего задача (23.3) решается методом сеток. Суть метода сеток

состоит в следующем. В области интегрирования выбирается упорядоченная

система точек 0 1 2 ... ,na x x x x b называемая сеткой. Точки ix назы-

вают узлами, а 1k k kh x x – шагом сетки. Если ( ) /kh h b a n , сетка на-

зывается равномерной. Для неравномерной сетки обозначим max kk

h h ; Для

упрощения, в дальнейшем будим считать сетку равномерной. Решение ( )u x

ищется в виде таблицы значений в узлах выбранной сетки ( )kku u x , для че-

го дифференциальное уравнение заменяется системой алгебраических урав-

нений, связывающих между собой значения искомой функции в соседних уз-

лах. Такая система называется конечно-разностной схемой. Имеется несколь-

ко распространенных способов получения конечно-разностных схем. Приве-

дем здесь один из самых универсальных – интегро-интерполяционный ме-

тод. Согласно этому методу для получения конечно-разностной схемы про-

интегрируем уравнение (23.3) на каждом интервале 1,k kx x для k=1,2,...,n

1 1

1 ( , ( ))k k

k k

x x

k k

x x

dudx u u f x u x dx

dx

Переписав последнюю формулу в виде

1

1 ( , ( ))k

k

x

k k

x

u u f x u x dx (23.4)

получаем, что значение искомой функции в к-ом узле определяется через зна-

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

Аппроксимируя интеграл одной из квадратурных формул, получаем те или

иные формулы относительно приближенных неизвестных значений искомой

функции, которые в отличие от точных обозначим .k ky u Структура конеч-

но-разностной схемы для задачи Коши такова, что она устанавливает закон

рекуррентной последовательности 1k ky y для искомого решения

0 1 2, , , ..., ny y y y . Поэтому, используя начальное условие задачи (23.2) и за-

давая 0 0y u , затем по рекуррентным формулам последовательно находят все

, 1, ..., .ky k n При замене интеграла приближенной квадратурной формулой

вносится погрешность аппроксимации дифференциального уравнения разно-

Page 154: НовыеЛекции ОАиП

154

стным. Говорят, что разностная схема аппроксимирует исходную дифферен-

циальную задачу с порядком p, если при 0h погрешность аппроксимации

( ) , .ph Ch C const Чем больший порядок аппроксимации p, тем выше

точность решения:

( ) max k k

kh y u y u (23.5)

Основная теорема теории метода сеток утверждает, что если схема устой-

чива, то при 0h погрешность решения ( )h стремится к нулю с тем же по-

рядком, что и погрешность аппроксимации 0 0ph C h C C h ,

где С0 – константа устойчивости. Неустойчивость обычно проявляется в том,

что с уменьшением h решение ky при возрастании k, что легко устанав-

ливается экспериментально с помощью просчета на последовательности се-

ток с уменьшающимся шагом h, h/2, h/4… Если при этом ky , то метод

неустойчив. Таким образом, если имеется аппроксимация и схема устойчива,

то, выбрав достаточно малый шаг h, можно получить решение с заданной

точностью при этом затраты на вычисления резко уменьшаются с увеличени-

ем порядка аппроксимации p, т. е. при большем p можно достичь той же точ-

ности, используя более крупный шаг h. Большое разнообразие методов обу-

словлено возможностью по-разному выбирать узлы и квадратурные формулы

для аппроксимации интеграла в (23.4).

23.2.1. Явная схема 1-го порядка (метод Эйлера)

Вычисляя интеграл в (23.4) по формуле левых прямоугольников полу-

чим

1 1

1( , ), 1, 2, ...,k k kky y h f x y k n . (23.6)

Задавая 0 0y u , с помощью (23.6) легко получить все последующие значения

, 1, 2, ...,ky k n , так как формула явно разрешается относительно ky . По-

грешность аппроксимации (h) и соответственно точность ε(h) имеют первый

порядок в силу того, что формула левых прямоугольников на интервале

1,k kx x имеет погрешность первого порядка, а схема устойчива.

23.2.2. Неявная схема 1-го порядка

Вычисляя интеграл в (23.4) по формуле правых прямоугольников полу-

чим

1 ( , ), 1, 2, ...,k k k

ky y h f x y k n .. (23.7)

Эта схема явно не разрешена относительно ky , поэтому для получения ky

требуется использовать итерационную процедуру решения уравнения (6.7):

, 1 , 1( , ); 1, 2, ...k s k k s

ky y h f x y s , где s – номер итерации.

Page 155: НовыеЛекции ОАиП

155

За начальное приближение можно взять значение , 0 1k ky y из предыдущего

узла. Обычно, если h выбрано удачно, достаточно сделать 2 – 3 итерации для

достижения заданной погрешности , , 1k s k sy y . Эффективность неявной

схемы заключается в том, что у нее константа устойчивости С0 значительно

меньше, чем у явной схемы.

23.2.3. Неявная схема 2-го порядка

Вычисляя интеграл в (23.4) по формуле трапеций получим

1 11( , ) ( , )

2

k k k kk k

hy y f x y f x y . (23.8)

Так как формула трапеций имеет второй порядок точности, то и погрешность

метода имеет второй порядок. Схема (23.8) явно не разрешена относительно ky , поэтому требуется итерационная процедура:

, 1 1 , 1 ,0 11( , ) ( , ) , 1, 2, ...,

2

k s k k k s k kk k

hy y f x y f x y s y y

23.2.4. Схема Рунге – Кутта 2-го порядка

Вычисляя интеграл в (23.4) по формуле средних прямоугольников по-

лучим

1 1/ 21/ 2( , )k k k

ky y h f x y . (23.9)

Уравнение разрешено явно относительно ky , однако в правой части присут-

ствует неизвестное значение 1/ 2ky в середине отрезка 1[ , ]k kx x . Для решения

этого уравнения используют следующий способ. Вначале по явной схеме

(23.6) рассчитывают 1/ 2ky (предиктор):

1/ 2 1 11( , )

2

k k kk

hy y f x y

После этого рассчитывают ky по (23.9) (корректор). В результате схема ока-

зывается явной и имеет второй порядок. Заметим, что эта схема получается из

схемы предыдущего метода, если в ней выполнять только две итерации (s=1,

2).

23.2.5. Схема Рунге – Кутта 4-го порядка

Вычисляя интеграл в (23.4) по формуле Симпсона получим

1 1 1/ 21 1/ 2[ ( , ) 4 ( , ) ( , )]

6

k k k k kk k k

hy y f x y f x y f x y . (23.10)

Ввиду того, что формула Симпсона имеет четвертый порядок, погрешность

метода тоже имеет четвертый порядок. Можно по-разному реализовать расчет

Page 156: НовыеЛекции ОАиП

156

неявного по ky уравнения (23.10), однако наибольшее распространение полу-

чил следующий способ. Вычисляют предиктор

1/ 2,1 1 11

1/ 2, 2 1 1/ 2,11/ 2

,1 1 1/ 2, 21/ 2

( ( , ),2

( , ),2

( , ),

k k kk

k k kk

k k kk

hy y f x y

hy y f x y

y y hf x y

затем корректор по формуле

1 1 1/ 2,11 1/ 2,

1/ 2, 2 , 11/ 2,

[ ( , ) 2 ( )6

2 ( ) ( , )]

k k k kk k

k kk k

hy y f x y f x y

f x y f x y

23.3. Многошаговые схемы Адамса

При построении всех предыдущих схем для вычисления интеграла в

правой части (23.4) использовались лишь точки в диапазоне одного шага

1[ , ]k kx x . Поэтому при реализации таких схем для вычисления следующего

значения ky требуется знать только одно предыдущее значение 1ky . Такие

схемы называют одношаговыми. Мы, однако, видели, что для повышения

точности при переходе от узла 1kx к узлу kx приходилось использовать и

значения функции 1/ 21/ 2,( )k

kf x y внутри интервала 1[ , ]k kx x . Схемы, в ко-

торых это используется (методы 23.2.4, 23.2.5), называют схемами с дробны-

ми шагами. В этих схемах повышение точности достигается за счет дополни-

тельных затрат на вычисление функции ( , )f x y в промежуточных точках ин-

тервала 1[ , ]k kx x . Идея методов Адамса заключается в том, чтобы для по-

вышения точности использовать уже вычисленные на предыдущих шагах

значения 1 2 3, , , ....k k ky y y в нескольких предыдущих узлах.

Заменим в (23.4) подынтегральную функцию интерполяционным мно-

гочленом Ньютона вида

1 21 1

1 2 31 2 2

( ) ( )( ) ( ) ( )

( ) 2 ( ) ( )( )( ) ... .

2

k kk k

k k kk k

f x f xf x f x x x

h

f x f x f xx x x x

h

(23.11)

После интегрирования на интервале 1[ , ]k kx x получим явную экстраполяци-

онную схему Адамса. (Экстраполяцией называется получение значений ин-

терполяционного многочлена в точках, выходящих за крайние узлы сетки). В

нашем случае интегрирование производится на интервале 1[ , ]k kx x , а поли-

ном строится по узлам 1 2 3, ,k k kx x x . Порядок аппроксимации схемы в этом

Page 157: НовыеЛекции ОАиП

157

случае определяется количеством использованных при построении полинома

узлов (например, если используется два узла 1, ,k kx x то схема второго по-

рядка). Если в (23.4) ) подынтегральную функцию заменим многочленом

Ньютона вида

1

1 21 2

( ) ( )( ) ( ) ( )

( ) 2 ( ) ( )( )( ) ... ,

2

k kk k

k k kk k

f x f xf x f x x x

h

f x f x f xx x x x

h

(23.12)

то после интегрирования получим неявную интерполяционную схему Адамса.

Заметим, что неявная интерполяционная схема Адамса второго порядка сов-

падает с ранее рассмотренной неявной схемой второго порядка.

23.3.1. Явная экстраполяционная схема Адамса 2-го порядка

Заменив в (23.4) подынтегральную функцию интерполяционным мно-

гочленом Ньютона вида

1 21 1

( ) ( )( ) ( ) ( ) ,k k

k k

f x f xf x f x x x

h

получим формулу

1 1 21 2[3 ( , ) ( , )]

2

k k k kk k

hy y f x y f x y (23.13)

Схема двухшаговая, поэтому для начала расчетов необходимо, сделав один

шаг, найти 1y по методу Рунге – Кутта 2-го порядка, после чего 2 3, , ...y y

вычислять по (23.13).

23.3.2. Явная экстраполяционная схема Адамса 3-го порядка

Заменив в (23.4) подынтегральную функцию интерполяционным мно-

гочленом Ньютона вида

1 21 1

1 2 31 2 2

( ) ( )( ) ( ) ( )

( ) 2 ( ) ( )( )( ) ,

2

k kk k

k k kk k

f x f xf x f x x x

h

f x f x f xx x x x

h

получим формулу

1 1 2 31 2 3[23 ( , ) 16 ( , ) 5 ( , )

12

k k k k kk k k

hy y f x y f x y f x y (23.14)

Схема трехшаговая, поэтому для начала расчетов необходимо, сделав два ша-

га, найти 1 2,y y по методу Рунге – Кутта 4-го порядка, после чего

3 4, , ...y y

вычислить по (23.14).

Page 158: НовыеЛекции ОАиП

158

23.3.3. Неявная схема Адамса 3-го порядка

Заменив в (23.4) подынтегральную функцию интерполяционным мно-

гочленом Ньютона вида

1

1 21 2

( ) ( )( ) ( ) ( )

( ) 2 ( ) ( )( )( ) ,

2

k kk k

k k kk k

f x f xf x f x x x

h

f x f x f xx x x x

h

получим формулу

1 1 21 2[5 ( , ) 8 ( , ) ( , )]

12

k k k k kk k k

hy y f x y f x y f x y . (23.15)

Так как схема двухшаговая, то для начала расчетов необходимо, сделав один

шаг, найти 1y по методу Рунге – Кутта 4-го порядка, после чего 2 3, , ...y y

вычисляются по (23.15). Эта формула явно не разрешена относительно ky ,

поэтому для получения ky требуется использовать итерационную процедуру

решения уравнения (23.15)

, 1 , 1 1 21 25 ( , ) 8 ( , ) ( , )

12

k s k k s k kk k k

hy y f x y f x y f x y

Значение , 0ky следует рассчитать по формуле (23.13):

,0 1 1 21 23 ( , ) ( , )

2

k k k kk k

hy y f x y f x y

23.4. Краевая (граничная) задача

Рассмотрим граничную задачу для линейного дифференциального урав-

нения второго порядка с переменными коэффициентами

y//+p(x) y

/ + q(x) y = f(x) (23.16)

на отрезке [a, b] с граничными условиями общего вила

1 y(a) + 1 y/(a) = A

2 y(b) + 2 y/(b) = B (23.17)

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

ским методом, используются приближенные или численные методы. Суть

приближенных методов.

Выбирается система линейно-независимых дважды дифференцируемых

функций { 0(x), 1(x), …, n(x)}, при этом функция 0(х) должна удовлетво-

рять граничным условиям (23.17), а функции 1(x), 2(x), …, n(x) – соответ-

ствующим однородным граничным условиям. Искомое решение представля-

ется в виде линейной комбинации базисных функций

Page 159: НовыеЛекции ОАиП

159

0

n

k kk 1

y(x) (x) c (x) (23.18)

Подставим выражение (23.18) в (23.16) и найдем невязку левой и правой час-

тей уравнения (23.16)

1 2 n 0 0 0(x,c ,c ,...,c ) (x) p(x) (x) q(x) (x) f (x)

k k k

n

kk 1

[ (x) p(x) (x) q(x) (x)]c (23.19)

Коэффициенты с1, с2, …, сn подбирают так, чтобы невязка (23.19) была мини-

мальна. Способ определения этих коэффициентов и характеризует тот или

иной метод. В методе коллокаций выбирают n точек xk [a,b], k=1,2,…,n, на-

зываемых точками коллокации, невязки в которых приравниваются нулю.

Решив полученную систему линейных алгебраических уравнений получают

значений искомых коэффициентов с1, с2, …, сn. Метод наименьших квадра-

тов основан на минимизации суммы квадратов невязок в заданной системе

точек xk [a,b], k=1,2,…,m; m>n. Из условия равенства нулю частных про-

изводных от суммы квадратов невязок по искомым коэффициентам сk , k=1, 2,

…, n также получают систему линейных алгебраических уравнений. В основе

метода Галеркина лежит требование ортогональности базисных функций

1(х), 2(х), …, n(х) к невязке (23.19), которое выражается в виде b

1 2 n k

a

(x,c ,c ,...,c ) (x)dx 0, k 1,2,...,n.

Из этого условия также получается система алгебраических уравнений. Ре-

шив полученную систему линейных алгебраических уравнений получают

значений искомых коэффициентов с1, с2, …, сn . В этом методе нет необходи-

мости выбора семейства узловых точек.

23.5. Численные методы решения краевых задач

23.5.1. Метод стрельбы

Сущность метода стрельбы заключается в сведении решения граничной

задачи (23.16) – (23.17) к многократному решению задачи Коши. Введя заме-

ну переменных y1(x)=dy/dx, заменим дифференциальное уравнение второго

порядка системой двух дифференциальных уравнений первого порядка:

dy/dx = y1, (23.20)

dy1/dx = f(x) – p(x)y1 – q(x)y

с граничными условиями общего вида:

1y(a) + 1y1(a)=A, (23.21)

2y(b) + 2y1(b)=B.

Задавшись произвольным начальным условием для y(x):

y(a)=y0 (23.22a)

Page 160: НовыеЛекции ОАиП

160

из первого уравнения (23.21) получаем начальное условие для y1(x):

y1(a)=(A- 1 y0)/ 1 (6.22б)

Система уравнений (23.20) с начальными условиями (23.22) представляет со-

бой задачу Коши, которая решается одним из ранее рассмотренных методов.

Получив в результате решения задачи Коши значения y(b), y1(b) на правом

конце отрезка [a, b], проверяют, выполнилось ли второе условие (23.21), ко-

торое может быть представлено в виде F(y0)= 2 y(b)+ 2 y1(b)–B=0. Таким об-

разом граничная задача (23.16) – (23.17) в итоге сводится к нахождению кор-

ня уравнения F(y0)=0 для вычисления правой части которого необходимо ре-

шить задачу Коши (23.20), (23.22).Описанный алгоритм называется методом

стрельбы, поскольку в нем как бы проводится «пристрелка» по углу наклона

интегральной кривой в начальной точке.

23.5.2. Метод конечных разностей

Сущность метода в том, что он сводит решение граничной задачи для

дифференциального уравнения к решению системы линейных алгебраиче-

ских уравнений относительно значений искомой функции на заданном мно-

жестве точек. Это достигается путем замены производных, входящих в диф-

ференциальное уравнение их конечно – разностными аппроксимациями. Рас-

смотрим применение этого метода для решения дифференциального уравне-

ния (23.16) с граничными условиями (23.17). Выберем на отрезке [a,b] систе-

му равноотстоящих точек xk=a+kh, k=0, 1, 2, …, n; h=(b– a)/n. Решение

граничной задачи (23.16) – (23.17) сведем к вычислению значений искомой

функции y(x) в узловых точках xk. Обозначим yk = y(xk). Заменим производ-

ные, входящие в (23.16) их конечно – разностными аппроксимациями:

y/(xk)=(yk +1–yk –1)/(2h),

y//(xk)=(yk +1–2 yk+yk –1)/h

2

и запишем уравнение (23.16) во внутренних узловых точках xk, k =1,2, …,n –1:

(yk+1–2yk+yk –1)/h2+pk(yk +1–yk –1)/(2h)+qk yk=f k

(23.23)

k=1,2, ..., n–1,

где введены обозначения pk=p(xk), qk=q(xk), fk=f(xk). Граничные условия так-

же должны представляться в разностном виде путем аппроксимации произ-

водных y/(a), y

/(b) помощью конечно-разностных соотношений. Если исполь-

зовать односторонние разности, при которых производные аппроксимируют-

ся с первым порядком точности, то разностные граничные условия в точках х0

и хn принимают вид:

1y0+ 1(y1–y0)/h=A

2yn+ 2(yn–yn-1)/h=B

Однако предпочтительнее аппроксимировать первые производные со вторым

порядком точности с помощью следующих соотношений:

y/(x0)=(-3y0+4y1–y2)/(2h)

y/(xn) =(3yn-4yn-1+yn-2)/(2h)

Page 161: НовыеЛекции ОАиП

161

В этом случае граничные условия примут вид:

( 1–3 1/2h) y0+ 1(4y1–y2)/(2h)=A (23.24)

( 2+3 2/2h)yn+ 2(-4yn-1+yn-2)/(2h)=B

Выражения (23.23), (23.24) образуют систему линейных алгебраических

уравнений (n+1)-го порядка, решив которую, получают решение граничной

задачи (23.16), (23.17) в виде значений искомой функции y(x) в узловых точ-

ках х0, х1, …, хn.

Page 162: НовыеЛекции ОАиП

162

ТЕМА 24. МЕТОДЫ ОПТИМИЗАЦИИ

24.1. Постановка задач оптимизации, их классификация

Трудно назвать область деятельности, где не возникали бы задачи оп-

тимизационного характера. Это, например, задачи определения наиболее эф-

фективного режима работы различных систем, поиск оптимальных парамет-

ров приборов и конструкций и т. д. Постановка каждой задачи оптимизации

включает в себя моделирование рассматриваемой ситуации с целью получе-

ния математической функции, которую необходимо минимизировать, а также

определения ограничений, если таковые существуют и выбора подходящей

процедуры для осуществления минимизации функции. Задача оптимизации

заключается в выборе среди элементов множества Х (множества допусти-

мых решений) такого решения, которое было бы с определенной точки зрения

наиболее предпочтительным. В дальнейшем понятие решения отождествля-

ется с вектором (точкой) n-мерного евклидова пространства nR . В соответст-

вии с этим допустимое множество Х представляет собой некоторое подмно-

жество пространства nR , т. е. nX R , а целевая функция (а также критерий

качества или критерий оптимальности) ( )f x – это функция n переменных

1 2, ,..., .nx x x Сравнение решений по предпочтительности осуществляется с по-

мощью целевой функции ( )f x , которую формулируют таким образом, чтобы

наиболее предпочтительному решению (0)

x соответствовал минимум целевой

функции:

(0)

( ) min ( )f x f x

x X (24.1)

При этом решение (0)

x называют оптимальным (точнее говоря, минималь-

ным) , а значение (0)

( )f x – оптимумом ( минимумом). Существует два вида

минимумов : локальный и глобальный. Говорят, что точка (0)

x X доставляет

функции ( )f x на множестве Х локальный минимум, если существует такая

окрестность (0)

( ) ( 0)U x точки (0)

x , что неравенство (0)

( ) ( )f x f x спра-

ведливо для всех (0)

( ).x X U x Глобальный минимум функции ( )f x

доставляет точка (0)

,x X для которой записанное выше неравенство выпол-

няется при всех .x X Если множество допустимых значений nX R , то гово-

рят о задаче минимизации без ограничений. В этом случае нужно найти такую

точку (0)

x , чтобы неравенство (0)

( ) ( )f x f x выполнялось для всех точек про-

странства nR без ограничения. Задачу минимизации без ограничений назы-

Page 163: НовыеЛекции ОАиП

163

вают также задачей безусловной минимизации. При этом для характеристики

точки минимума и самого минимума добавляют прилагательное «безуслов-

ный». Если nX R , то имеет место задача минимизации с ограничениями. В

этом случае также говорят о задаче условной минимизации, о точках условно-

го минимума и об условном минимуме. Если допустимое множество Х задано

в виде

| ( ) 0, 1,2,..., ; ( ) 0, 1,...,n

j jX x R g x j k g x j k m (24.2)

где все функции ( )jg x определены на nR , то говорят о задаче математиче-

ского программирования. Среди задач этого класса различают задачи с огра-

ничениями типа неравенств – когда множество Х имеет вид (24.2) и m = k;

задачи с ограничениями типа равенств – когда в (24.2) неравенства отсутст-

вуют (k = 0), и задачи со смешанными ограничениями – когда в задании

множества Х встречаются как равенства, так и неравенства. Следует отметить,

что ограничение типа равенства ( ) 0g x всегда можно заменить двумя огра-

ничениями типа неравенства ( ) 0 ( ) 0, ( ) 0.g x g x g x С другой стороны,

ограничение-неравенство всегда можно заменить эквивалентным ему ограни-

чением-равенством, введя дополнительную переменную 1nx 2

1( ) 0 ( ) 0.ng x g x x

24.2. Методы нахождения минимума функции одной переменной

Задача нахождения минимума функции одной переменной min f(x) не-

редко возникает в практических приложениях. Кроме того, многие методы

решения задачи минимизации функции многих переменных сводятся к мно-

гократному поиску одномерного минимума. Поэтому разработка новых, бо-

лее эффективных одномерных методов оптимизации продолжается и сейчас,

несмотря на кажущуюся простоту задачи.

Примечание. В дальнейшем, если не будет особо оговорено, под мини-

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

Нахождение минимума функции осуществляется в два этапа:

1. Приближенное определение местоположения минимума.

2. Вычисление точки минимума xmin c заданной точностью одним из

нижеприведенных методов.

На первом этапе, задав некоторую начальную точку x0, спускаются с

заданным шагом h в направлении уменьшения функции и устанавливают ин-

тервал длиной 2h, на котором находится минимум, из условия f(x-h)> f(x) <

f(x+h). Для функции, изображенной на рис. 21.1, если A < x0 < xg , будет вы-

делен интервал [a,b] с локальным минимумом xmin1, а если xg < x0 < B – с гло-

бальным минимумом xmin2, т. е. тот, в области «притяжения» которого оказа-

лась начальная точка x0. Если на отрезке [a,b] функция f(x) унимодальна, т. е.

она имеет на этом отрезке единственную точку минимума xmin и слева от этой

точки является строго убывающей, а справа – строго возрастающей, то для

Page 164: НовыеЛекции ОАиП

164

вычисления точки минимума с заданной точностью могут использоваться

нижеприведенные методы.

Рис. 24.1. Виды минимумов

24.2.1. Метод деления отрезка пополам

Алгоритм метода.

Задаются интервал [a, b] и погрешность .

1. Вычисляется середина интервала [a, b]: ( ) / 2x a b .

2. Отбрасывается половина интервала, не содержащая минимум:

Если ( ) ( ),f x f x то ,a x иначе .b x

3. Если |b-a| > , то повторяем с п. 1.

4. Вычисляем min min min( ) / 2, ( ).x a b f f x

Этот метод прост в реализации, позволяет находить минимум разрыв-

ной функции, однако требует большого числа вычислений функции для обес-

печения заданной точности.

24.2.2. Метод золотого сечения

Золотое сечение – это такое деление отрезка [a, b] на две неравные час-

ти при котором отношение большего отрезка ко всему интервалу равно от-

ношению меньшего отрезка к большему. При этом имеет место следующее

соотношение

1 1 1( ) /( ) ( ) /( ) 1 0.618, (3 5) / 2 0.382.b x b a x a b x

О точке, которая расположена на расстоянии длины от одного из концов от-

резка, говорят, что она осуществляет золотое сечение данного отрезка. Каж-

дый отрезок имеет две такие точки, расположенные симметрично относи-

тельно середины. Алгоритм поиска минимума аналогичен вышеописанному

методу деления пополам и отличается тем, что вначале точки x1 и x2 выбира-

ются так, чтобы они осуществляли золотое сечение отрезка, и вычисляются

значения функции в этих точках

Page 165: НовыеЛекции ОАиП

165

1 2 1 1 2 2( ), ( ), ( ), ( ).x a b a x b b a f f x f f x

В последующем, после сокращения интервала путем отбрасывания неблаго-

приятной крайней точки, на оставшемся отрезке уже имеется точка, деля-

щая его в золотом отношении, (точка x1 на рис. 24.2) известно и значение

функции в этой точке. Остается лишь выбрать ей симметричную и вычислить

значение функции в этой точке для того, чтобы вновь решить, какую из край-

них точек отбросить.

Алгоритм метода.

Задаются a, b и погрешность .

1. Вычисляются две точки золотого сечения

x1=a+ξ(b-a), x2=b-ξ(b-a), f1=f(x1), f2=f(x2).

2. Если f1>f2, то a=x1, x1=x2, f1=f2, x2=b-ξ(b-a), f2=f(x2),

иначе b=x2, x2=x1, f2=f1, x1=a+ξ(b-a), f1=f(x1).

3. Если |b-a|> ε, то повторить с п. 2.

4. Вычисляется xmin=(a+b)/2, fmin=f(xmin).

При одинаковом количестве вычислений функции отрезок, на котором нахо-

дится xmin, уменьшается быстрее, чем в методе деления пополам.

24.2.3. Метод Фибоначчи

На практике количество вычислений значений функции часто бывает

ограничено некоторым числом n (тем самым ограничено и число шагов вы-

числений по методу золотого сечения; оно не превышает n-1). Метод Фибо-

наччи отличается от метода золотого сечения лишь выбором первых двух

симметричных точек и формул их пересчета и гарантирует более точное при-

ближение к точке xmin за n-1 шаг, чем метод золотого сечения за то же количе-

ство шагов. Согласно методу Фибоначчи, на нулевом шаге первые две сим-

метричные точки вычисляют по формулам:

Рис. 24.2. Метод золотого сечения

Page 166: НовыеЛекции ОАиП

166

x10=a0+Fn(b0–a0)/Fn + 2,

x20=b0-Fn (b0 -a0)/Fn + 2=a0+Fn+1(b0–a0)/Fn + 2,

где Fn , Fn+1, Fn+2 – числа Фибоначчи, определяемые рекуррентной формулой

F1=F2=1, Fk =Fk-1+Fk–2 , k=3, 4, ...

Запишем первые десять чисел Фибоначчи:

F1=1, F2=1, F3=2, F4=3, F5=5, F6=8, F7=13, F8=21, F9=34, F10=55.

В последующем, после сокращения интервала путем отбрасывания неблаго-

приятной крайней точки, одна из точек пересчитывается по одной из соответ-

ствующих формул

x1k=ak+Fn-k(b0–a0)/Fn+2,

x2k=ak+Fn-k+1(b0–a0)/Fn+2.

Выполняется n-1 шаг, при k = 1, 2, ..., n – 1. На последнем шаге две симмет-

ричные точки сливаются в одну, которая и принимается за точку минимума

xmin =x1n -1

. Погрешность вычисления точки минимума не превышает (b0–

a0)/(2Fn+2), т. е. за три вычисления функции (n=2) получают точку минимума

с погрешностью, не превышающей 1/6 первоначального интервала, пять вы-

числений (n=4) – 1/16, девять (n=8) – 1/110. Так как 2lim / (3 5) / 2,n nF F

n

то при достаточно больших n вычисления по методу Фибоначчи и золотого

сечения начинаются практически из одной и той же пары симметричных то-

чек.

Алгоритм метода.

1. Задаются a, b и число n.

2. Вычисляются d=( b-a )/Fn+2 и две симметричные точки:

x1=a+Fnd, x2=b-Fnd, f1=f(x1), f2=f(x2).

3. Если f1 > f2 , то a=x1, x1=x2, f1=f2, x2 = a+ Fn– k+1 d, f2 = f (x2),

иначе b=x2, x2= x1, f2= f1, x1 = a+ Fn– k d, f1 = f (x1).

4. Пункты 2 – 3 повторяется n-1 раз, при k=1, 2, ..., n-1.

5. Вычисляется min 1 min min, ( )x x f f x .

24.2.4. Метод последовательного перебора

Этот метод не требует предварительного определения местоположения

точки минимума. Идея метода состоит в том, что, спускаясь из точки x0 с за-

данным шагом h в направлении уменьшения функции, устанавливают интер-

вал длиной 2h, на котором находится минимум, который затем последова-

тельно уточняют, повторяя спуск с последней точки, уменьшив шаг и изме-

нив его знак, пока не будет достигнута заданная точность (некое подобие за-

тухающего маятника).

Алгоритм метода.

Задаются 0x , начальный шаг h, (h>0) и погрешность .

1. Вычисляем 0 0( )f f x

Page 167: НовыеЛекции ОАиП

167

2. Определяем направление убывания функции.

Если 0 0( ) ,f x f то .h h

3. Из точки 0x делается шаг 1 0x x h и вычисляется 1 1( )f f x .

4. Если 1 0f f , то 0 1 0 1, ,x x f f и повторить с п. 3.

5. В точке 1x функция оказалась большей, чем в 0x , следовательно, мы

перешагнули точку минимума. Организуем спуск в обратном направлении с

меньшим шагом, например h= - h/4 или h= - h/10.

6. Если h , то повторить с п. 3.

7. xmin=x0, fmin=f0.

Скорость сходимости данного метода существенно зависит от удачного вы-

бора начального приближения x0 и шага h. Шаг h следует выбирать как поло-

вину оценки расстояния от x0 до предполагаемого минимума xmin.

24.2.5. Метод квадратичной параболы

Для нахождения точки минимума с заданной точностью задают 3 точки

x1, x2, x3 для которых выполняются условия f(x2)<f(x1) и f(x2)<f(x3). На этом

интервале функцию аппроксимируют квадратичной параболой, минимум ко-

торой известен. Cуть метода в следующем.

Для заданных трех точек x1, x2, x3 вычисляются значения функции в них

f1, f2, f3. Через эти точки проводится квадратичная парабола

2 23 3( ) ( ) ,p x x q x x r pz qz r

3 1 1 3 2 2 3 3, , , ,z x x z x x z x x r f (24.3)

1 3 1 11 3 1 2 3 2

1 2

( ) / .( ) / ( ) /

, f f z pzf f z f f z

p qz z

Парабола имеет минимум в точке zm= - q/(2p). Следовательно, можно аппрок-

симировать положение минимума функции значением xm=x3+zm и, если точ-

ность не достигнута, следующий спуск производить, используя эту новую

точку и две предыдущие, отбросив одну наихудшую точку. Получается по-

следовательность xm1, xm2, xm3, … , сходящаяся к точке xmin.

Алгоритм метода.

1. Задается точки x1, x2, x3 и точность нахождения минимума .

2. Вычисляем f1=f(x1), f2=f(x2), f3=f(x3).

3. Вычисляем z1, z2, p, q, zm по вышеприведенным формулам (24.3).

4. Вычисляем точку минимума параболы xm=x3+zm, fm=f(xm).

5.Если |xm - x2|<ε, то xmin=xm, иначе переименовываем точки, отбрасывая

наихудшую точку: если xm<x2 то x3=x2, f3=f2, x2=xm, f2=fm,

иначе x1=x2, f1=f2, x2=xm, f2=fm

и повторяем с п. 3.

Данный метод сходится очень быстро и является одним из наилучших мето-

дов спуска. Следует, однако, отметить, что при очень малых расчет по при-

Page 168: НовыеЛекции ОАиП

168

веденным здесь формулам для p и q вблизи минимума может привести к по-

явлению большой погрешности из-за потери значащих цифр при вычитании

близких чисел. Поэтому разные авторы предлагают свои эквивалентные фор-

мулы, вычисления по которым более устойчивы. Кроме того, в алгоритм вно-

сятся некоторые поправки, позволяющие предусмотреть различные неприят-

ные ситуации – переполнение разрядной сетки, деление на нуль, уход от кор-

ня.

24.2.6. Метод кубической параболы

Данный метод аналогичен предыдущему, но за счет использования ап-

проксимации кубической параболой имеет более высокую сходимость, если

функция допускает простое вычисление производной. При его использовании

выбираются две точки x1 и x2 1 2( ( ) 0, ( ) 0),f x f x вычисляются значе-

ния функции f1, f2 и ее производной 1 1 2 2( ), ( )D f x D f x . Затем через

эти точки проводится кубическая парабола, коэффициенты которой опреде-

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

точках x1 и x2:

3 2 3 22 2 2( ) ( ) ( ) ( ),p x x q x x r x x s pz qz rz s P z

2 1 1 2, ,z x x z x x

1 1 1 1 2 2, .( ) , ( ) (0) , (0)P z f P z D P f P D

Как нетрудно убедиться, коэффициенты параболы вычисляются по следую-

щим формулам:

2 2,s f r D ,

21 2 1 2 1 1

1 2 1 13

( 2( ) / ) / ,

(( ) / ) / 2.p

p D D f f z z

q D D z z

Известно, что кубическая парабола имеет минимум в точке

2( 3 )/(3 ).mz q q pr p

Поэтому приближенное положение минимума можно получить по формуле

2m mx x z и, если, точность не достигнута, заменить одну из крайних точек

точкой xm и снова повторить процесс.

Алгоритм метода.

1. Задается точки x1, x2, ( f'(x1) < 0, f'(x2) > 0 ) и точность .

2. Вычисляем f1=f(x1), f2=f(x2), d1= f'(x1), d2= f'(x2), xp=(x1+x2)/2.

3. Вычисляем z1, p, q, r, zm, xm по вышеприведенным формулам.

4. Если | xm-xp |<ε , то xmin = xm.

В противном случае заменяем одну из крайних точек точкой xm:

если f'(xm) < 0, то x1=xm, f1=f(xm), d1= f'(xm),

иначе x2=xm, f2=f(xm), d2= f'(xm),

запоминаем полученную точку xp = xm и снова повторяем с п. 3.

Page 169: НовыеЛекции ОАиП

169

24.3. Методы нахождения безусловного минимума функции нескольких

переменных

24.3.1. Классификация методов

Сущность всех методов нахождения безусловного минимума функции n

переменных состоит в построении последовательности точек 0 1 2

, , ,..., ,...k

x x x x

монотонно уменьшающих значение целевой функции ( ) :f x 0 1 2

( ) ( ) ( ) ... ( ) ...k

f x f x f x f x

Такие методы называют методами спуска. Общая схема этих методов сле-

дующая.

Пусть на k-й итерации имеется точка k

x . Выбирается направление спус-

ка k

np R , длина шага вдоль этого направления k > 0 и находится минимум

kmin вдоль этого направления (рис 24.3). После чего вычисляют следующую

точку последовательности по формуле 1

min

k kk kx x p .

Примечание: Согласно последней формуле, величина продвижения из

точки k

x в 1k

x1 зависит как от k , так и от

k

p . Однако k традиционно назы-

вают длиной шага.

Рис. 24.3. Иллюстрация спуска по направлению

Формально различные методы спуска отличаются друг от друга способом

выбора шага k и вектора k

p . Различают методы с постоянным шагом, ко-

гда начальный шаг на k -й итерации k постоянен и равен 0 и методы с ав-

томатическим выбором шага, когда величина начального шага на (k+1)-й

Page 170: НовыеЛекции ОАиП

170

итерации выбирается с учетом величины продвижения на k-й итерации, на-

пример 1

min/ 2k k . Если для определения k и k

p требуется вычислять

только значения целевой функции, то соответствующие методы называются

методами нулевого порядка. Методы первого порядка требуют, кроме того,

вычисления первых производных целевой функции. Если же метод предпола-

гает использование и вторых производных, то его называют методом второ-

го порядка и т. д. С помощью методов нулевого порядка можно решать зада-

чи более широкого класса, чем с помощью методов первого или второго по-

рядков. Однако методы нулевого порядка, как правило, требуют большего

числа вычислений для достижения заданной точности, поскольку использо-

вание только значений целевой функции не позволяет достаточно точно оп-

ределять направление на точку минимума. Методы первого и второго поряд-

ков обладают, как правило, более высокой скоростью сходимости, однако не-

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

ние задачи оптимизации. В ряде случаев они не могут быть получены в виде

аналитических выражений, а вычисление производных численными методами

осуществляется с ошибками, которые могут ограничить применение таких

методов. Кроме того, на практике встречаются задачи, решение которых воз-

можно лишь с помощью методов нулевого порядка, например задачи мини-

мизации функций с разрывными первыми производными.

24.4. Методы нулевого порядка

24.4.1. Метод покоординатного спуска

В этом методе направление спуска выбирают параллельным координат-

ным осям. Задается начальная точка x0={x10, x2

0, ..., xn

0} в n–мерном простран-

стве. Фиксируются все координаты, кроме первой и решается задача одно-

мерной минимизации для координаты x1 одним из рассмотренных ранее ме-

тодов. В результате мы переходим к точке x1={x11, x2

0, ..., xn

0}, в которой

функция f(x) принимает наименьшее значение по координате x1 при фиксиро-

ванных остальных координатах. Затем фиксируются все координаты, кроме

второй и решается задача одномерной минимизации для координаты x2 и т. д.

После решения задачи минимизации для всех n переменных проверяется ус-

ловие

||xn–x 0|| < или | f(xn)–f(x0)| < ,

где и – некоторые положительные числа, характеризующие точность ре-

шения задачи минимизации. При невыполнении этого условия вновь прово-

дится цикл минимизаций для всех n переменных и т. д. Вычисления продол-

жаются до тех пор, пока не будет выполнено условие

||xnk+1

–x0k|| < или |f(xn

k+1)–f(x0

k)| < .

Page 171: НовыеЛекции ОАиП

171

24.4.2. Метод Хука – Дживса

Метод состоит из последовательности итераций, каждая из которых со-

держит перемещения двух типов : исследующий поиск вокруг базисной точ-

ки, за которым в случае успеха следует поиск по образцу.

1. Задается начальная точка x0 = (x10, x2

0, ..., xn

0), вектор приращений

для каждой координаты d = (d1, d2, ..., dn) и точность решения задачи

минимизации .

2. Вычисляется целевая функция f0=f(x0).

3. Запоминается базисная точка x1=x0, f1=f0.

4. Задаем m=0.

5. Для каждой k-й координаты по очереди вычисляется: xt=x1+dk k,

ft=f(xt), где k – единичный вектор в направлении оси xk. Если ft < f1,

то полагаем x1=xt, f1=ft, и переходим к следующей координате,

иначе вычисляется xt=x1-dk k, ft=f(xt). Если ft < f1, то полагаем x1=xt,

f1=ft, и переходим к следующей координате, иначе значение m уве-

личиваем на единицу и переходим к следующей координате. После

выполнения таких вычислений для всех координат (k=1,2,…,n), пе-

реходим к следующему пункту.

6. Если m=n, т. е. уменьшение функции не было достигнуто ни по од-

ной координате, то вектор приращений d уменьшают (например, в

два, четыре или десять раз) и повторяют вычисления с 4-го пункта.

Вычисления повторяются до тех пор, пока не будет достигнуто

уменьшение функции.

Примечание. Если все компоненты вектора приращений d станут мень-

ше (dk < , для всех k=1,2,…,n), а уменьшение функции не достигнуто, то

базисная точка x0 является точкой минимума целевой функции f(x) и вычис-

ления прекращаются.

7. При поиске по образцу используется информация, полученная в

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

точки x1 в направлении p=x1–x0, поскольку поиск в этом направле-

нии уже привел к уменьшению значения целевой функции. Поэтому

на этапе поиска по образцу решается задача одномерной минимиза-

ции целевой функции f(x1+ p) относительно шага одним из рас-

смотренных ранее методов. После получения значения min вычисля-

ется новая базисная точка x0=x1+ minp и вычисления повторяются со

2-го пункта.

24.4.3. Метод Нелдера – Мида

Метод Нелдера – Мида является развитием симплексного метода Спенд-

ли, Хекста и Химсворда. Геометрическая фигура, порожденная n+1 точкой в

n-мерном пространстве, называется симплексом, а сами точки называются

вершинами симплекса. Следовательно, в двумерном пространстве симплек-

Page 172: НовыеЛекции ОАиП

172

сом является треугольник, в трехмерном пространстве – тетраэдр. Если вер-

шины равноудалены друг от друга, симплекс называется правильным. Идея

метода состоит в сравнении значений целевой функции в n+1 вершине сим-

плекса и перемещении симплекса в направлении оптимальной точки с помо-

щью итерационной процедуры. В результате последовательных итераций

симплекс модифицируется, двигаясь к точке минимума и сжимаясь вокруг

неѐ. Симплекс преобразуется с помощью операций отражения, растяжения,

редукции и сжатия. При рассмотрении этих операций будем использовать

следующие обозначения:

fi - значение целевой функции в i-й вершине, т. е. i = (xi);

m - номер вершины, соответствующей наибольшему значению (х), т. е.

m = max { i }, i=1,2,...,n+1

s – номер, соответствующий второй по величине вершине после наи-

большей, т. е. s = max { i }, i=1,2,...,n+1; i m

l- номер вершины с наименьшим значением (х), т. е.

l = min { i }, i=1,2,...,n+1

x0 - центр тяжести симплекса, образованного всеми вершинами, кроме

x m:

10

1

1 ni

i

i m

x xn

Преобразование симплекса начинается с операции отражения.

Отражение. Так как xm – вершина, соответствующая максимальному

значению целевой функции, то представляется разумным сравнить значения

целевой функции в точках xm и x

r , где x

r получена из x

m отражением относи-

тельно противоположной грани гиперплоскости симплекса. Если r меньше

m, то строим новый симплекс, заменяя точку xm на x

r. Процесс отражения

проиллюстрирован на рис. 24.4 для двумерного симплекса. Отраженная точка

получается как xr = x

0+ (x

0 - x

m), где > 0 – коэффициент отражения. Точка

xr лежит на прямой проходящей через точки x

m и x

0 с другой стороны от x

0.

Вычисляется значение целевой функции в отраженной точке xr и сравнивает-

ся со значением целевой функции в точках xl, x

s, x

m. Возможны следующие

случаи, согласно которым далее следуют соответствующие операции:

l < r s – отражение в новом симплексе;

r < l – растяжение;

s < r < m – редукция;

r > m – сжатие;

В первом случае точка xr является лучшей точкой по сравнению с точками x

m

и xs, поэтому точка x

m отбрасывается и заменяется на x

r , строится новый

симплекс и операция отражения повторяется.

Page 173: НовыеЛекции ОАиП

173

Рис. 24.4. Процесс отражения

Растяжение. Если процедура отражения дает точку xr , для которой r< l

, т.е. минимальную точку, то можно ожидать, что значение функции умень-

шится еще более при движении по прямой, соединяющей точки x0 и x

r. Эта

гипотеза проверяется в процедуре растяжения в этом направлении xe = x

0 +

(xr - x

0), где >1 – коэффициент растяжения. Вычисляем e = (x

e). Если e <

r , то заменяем точку xm на

x

e, в противном случае, ( e > r ) растяжение ока-

залось неудачным и точку xm заменяем на x

r, после чего строится новый сим-

плекс и операция отражения повторяется.

Редукция. Если в процессе отражения получилась точка xr, такая, что

s < r < m, то отражение дает лишь незначительное улучшение. В этом

случае выполняют редукцию в направлении, соединяющем точки x0 и x

r, что-

бы проверить, не перешагнули ли лучшую точку. Для редукции рассчитываем

точку xc = x

0 + ( x

r – x

0 ), где - коэффициент редукции (0< <1). Вычисляем

с= (хс). Если с < r, то точку x

m заменяем на x

с в противном случае точка x

m

заменяется на xr. Строится новый симплекс и операция отражения повторяет-

ся.

Сжатие. К операции сжатия прибегают, когда отражение дает полностью

неудовлетворительный результат ( r > m). Остается предположить, что ми-

нимум, вероятно, лежит внутри симплекса. Поэтому симплекс сжимается в

два раза вокруг вершины с минимальным значением l путем пересчета всех

вершин по формулам xi =(x

i + x

l)/2, i=1,2,...,n+1, после чего операция отра-

жения повторяется. Вычисления прекращаются, если среднеквадратичное от-

клонение целевой функции в n+1 вершине текущего симплекса меньше за-

данного малого значения , т. е. 1/ 2

2n 1

срii 1

f f / n 1 , где n 1

ср ii 1

1f f

1 n

Если коэффициенты отражения, редукции и растяжения равны соответствен-

но =1, =0,5, =2, то симплексный метод носит название метода Нелдера –

Мида.

Page 174: НовыеЛекции ОАиП

174

24.5. Методы первого порядка

Как известно, направление градиента n1 2

g xdf df df

f ( ) , ,...,dx dx dx

яв-

ляется направлением наискорейшего возрастания функции. Следовательно,

противоположное направление g является направлением наискорейшего

убывания функции. Это свойство антиградиента лежит в основе градиентных

методов первого порядка. При этом направление наискорейшего убывания в

данной точке не всегда оказывается наилучшим для спуска к точке миниму-

ма, поэтому для повышения эффективности вводят различные поправки. При

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

функции из предыдущих спусков. Множество возможностей введения таких

поправок определяет многообразие различных методов первого порядка.

24.5.1. Метод наискорейшего спуска

В этом методе на каждой к-й итерации решается задача одномерной

минимизации целевой функции (хk+ pk) относительно величины шага в

направлении pk=- (xk). Новая точка вычисляется по формуле:

xk+1=хk+ minpk.

Процесс прекращается, когда выполняется одно из условий:

||xk+1 – xk|| < или ||pk+1|| < .

24.5.2. Метод сопряженных градиентов Флетчера – Ривса

Широкое распространение получили градиентные методы, основанные

на так называемых сопряженных направлениях. Общая схема рассматривае-

мого класса методов может быть представлена в следующем виде:

xk+1=хk+ k minpk, где pk=- (xk)+ kpk-1, k=1,2,…; p0=- (x0)

Здесь, как и ранее, на каждой к-й итерации решается задача одномерной ми-

нимизации целевой функции относительно величины шага , однако, направ-

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

Различные способы выбора параметра k приводят к различным модификаци-

ям градиентных методов. Очевидно, что при k=0 схема вырождается в метод

наискорейшего спуска. В частности, чтобы обеспечить хорошую сходимость

рассматриваемых методов, k необходимо выбирать таким образом, чтобы i

направляющих векторов (i n) на последующих шагах процесса минимиза-

ции были линейно независимыми. Этому условию удовлетворяют сопряжен-

ные направления. Два вектора v и u являются сопряженными относительно

положительно определенной матрицы А, если имеет место соотношение

vTAu=0. Всегда имеется хотя бы одно взаимно независимое множество со-

пряженных векторов, ибо такое множество образуют собственные векторы

матрицы А. Метод сопряженных направлений заключается в выборе соответ-

ствующим образом k и образования такой последовательности направляю-

Page 175: НовыеЛекции ОАиП

175

щих векторов p0, p1,…, pn-1, чтобы эти векторы были сопряженными относи-

тельно матрицы Гессе. В методе Флетчера–Ривса к вычисляется по формуле: 22

T k k n n

k k k 1T k 1 k 1i 1 i 1i i

g ( x ) g ( x ) d f d f

d x d xg ( x ) g ( x )

Алгоритм метода.

1. Задается начальная точка х0 и точность решения задачи минимизации .

2. Вычисляется градиент целевой функции g0= (x0).

3. Вычисляется вектор направления поиска p0= -g0.

4. Решается задача одномерной минимизации целевой функции f(х0+ p0)

относительно шага одним из ранее рассмотренных методов.

5. Вычисляется новая точка х1=х0+ minp0. Для к=1,2,…, n -1 последователь-

но повторяются пп. 6 – 10.

6. Вычисляется градиент целевой функции gk= f(xk).

7. Вычисляется параметр k Tk k

k Tk 1 k 1

g g

g g

8. Вычисляется вектор направления поиска pk=-gk+ kpk-1

9. Решается задача одномерной минимизации целевой функции (хk+ pk)

относительно .

10. Вычисляется новая точка хk+1=хk+ k minpk

11. Проверяется условие сходимости ||xn–x0|| < или ||gn|| < .

12. Если заданная точность решения не достигнута, то переходим к п. 2, с за-

меной x0 на xn.

24.6. Методы второго порядка

24.6.1. Обобщенный метод Ньютона – Рафсона

Эти методы основаны на квадратичной аппроксимации целевой функции

и как следствие для своей реализации требуют вычисления производных пер-

вого и второго порядков. Одним из таких методов является обобщенный ме-

тод Ньютона – Рафсона, в котором на каждой к-й итерации производится од-

номерный поиск минимума целевой функции (хk+ pk) относительно шага

в направлении pk= -Hk-1gk, где Нk-1 – матрица, обратная матрице Гессе (матри-

цы вторых производных) в точке хk, а gk – градиент целевой функции в той же

точке. Одним из преимуществ этого метода по сравнению с градиентными

методами состоит в том, что он не реагирует на «овражный» характер мини-

мизируемой функции. Градиентные методы, по существу, используют линей-

ную аппроксимацию целевой функции и поэтому менее точно определяют

направление на точку минимума. Поэтому метод Ньютона – Рафсона позво-

ляет достичь заданной точности за меньшее число итераций, чем градиентные

Page 176: НовыеЛекции ОАиП

176

методы. Однако каждая итерация метода Ньютона – Рафсона связана с вы-

числением матрицы вторых производных Нk и последующим еѐ обращением,

что требует большего объема вычислений по сравнению с одной итерацией

градиентного метода. Кроме того, в ряде случаев производные не могут быть

получены в виде аналитических выражений, а вычисление их численными

методами осуществляется с ошибками, которые зачастую сводят на нет пре-

имущества этого метода. Поэтому широкое распространение получила группа

методов называемая методами переменной метрики или квазиньютоновски-

ми, базирующихся на аппроксимации обратной матрицы Гессе на основе

только первых производных. В этих методах вектор направления рk рассчи-

тывается по формуле рk=-Аkgk, где матрица Аk называемая иногда матрицей

направлений, представляет собой аппроксимацию матрицы Нk-1. Один из ме-

тодов переменной метрики, полученный Дэвидоном и модифицированный

Флэтчером и Пауэллом, получил название метода Дэвидона – Флэтчера –

Пауэлла (ДФП).

24.7. Методы переменной метрики

24.7.1. Метод Дэвидона – Флэтчера – Пауэлла

Основной трудностью реализации обобщенного метода Ньютона – Раф-

сона является необходимость вычисления матрицы вторых производных Н

(матрицы Гессе) и ее обращения на каждой итерации. В методе ДФП эта

трудность преодолевается благодаря использованию определенного прибли-

жения Ак для матрицы, обратной гессиану Н. Матрица Ак – положительно оп-

ределенная симметричная матрица, которая обновляется на каждой итерации.

В пределе матрица Ак становится равной обратному гессиану Нк-1

. Начальное

значение матрицы А0 принимается равным единичной матрице Е. На каждой

итерации текущее значение матрицы направлений пересчитывается в соот-

ветствии с рекуррентным соотношением: Tk T

k k k kk kk 1 k T T

k k k k k

A u u Av vA A

v u u A u

где vk= kpk, uk=gk+1 – gk.

Алгоритм метода.

1. Задается начальная точка х0 и погрешность .

2. Задается начальное значение матрицы А0=Е (единичная матрица).

На каждой к-й итерации (к=0, 1, 2, …) вычисляется:

3. Градиент целевой функции

kk k k k

n1 2

df df dfg f (x ) , , ...,

dx dx dx

4. Вектор направления поиска рk=-Аkgk.

Page 177: НовыеЛекции ОАиП

177

5. Находится k в результате решения задачи одномерной минимизации

целевой функции (хk+ pk) одним из ранее рассмотренных методов.

6. Вычисляется вектор перемещения в пространстве n переменных

vk= kpk.

7. Вычисляется новая точка xk+1=xk+vk.

8. Вычисляется целевая функция k+1= (хк + 1) и градиент gk+1= (xk+1) во

вновь полученной точке xk+1.

9. Завершается процедура поиска, если ||gk+1|| < или ||vk|| < .

В противном случае:

10. Вычисляется uk=gk+1–gk.

11. Пересчитывается матрица Аk k T T

k k k k k kk 1 k T T

k k k k k

v v A u u AA A

v u u A u

12. к увеличивается на единицу и возвращаются к п. 3.

24.8. Методы условной минимизации функций

24.8.1. Метод штрафных функций

Если допустимое множество решений задачи (24.1) задано в виде:

X={x Rn | gj(x) 0 , j=1, 2, …, k; hj(x)=0 , j=1, 2, …, m }

{ примечание: неравенство вида b(x) 0 всегда можно свести к неравенству

вида g(x) 0 заменой - b(x) 0 }, то исходную задачу минимизации с ограниче-

ниями (как в форме неравенств, так и в форме равенств) можно свести к по-

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

методы безусловной минимизации функций. Для этого вводят функцию Ф(х),

определенную и непрерывную на Rn таким образом, чтобы выполнялись сле-

дующие условия:

1. Ф(х)=0 для всех х Х.

2. Ф(х) > 0 для всех х вне допустимой области Х.

Образно говоря, функция Ф(х) назначает положительный штраф за выход за

пределы допустимой области Х. Указанными свойствами обладает, например,

функция вида:

Ф(х)=k m

p pj j

j 1 j 1

x x( max {g ( ); 0} ) h ( ) ,

где p–произвольное натуральное число или функция: k m

2 2j j j j j

j 1 j 1

x x x x x(x) ( ) g ( ) 1 signg ( ) ( ) h ( ),

где j > 0, j > 0 – весовые функции штрафа, которые в простейшем случае

могут быть константами. После чего от задачи

min f(x)

x X

Page 178: НовыеЛекции ОАиП

178

переходят к задаче:

min F(x), где F(x)=f(x)+r (x), r > 0 – весовой коэффициент.

x Rn

Выбор весовых коэффициентов r, j, j весьма важен с вычислительной точки

зрения. При больших значениях весовых коэффициентов при нарушении ог-

раничений целевая функция F(x) приобретает ярко выраженный «овражный»

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

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

тимой области. На практике проводят несколько циклов минимизации при

последовательно изменяющихся значениях весового коэффициента r (напри-

мер, rk=k или rk=10k, k=1,2,…).

Page 179: НовыеЛекции ОАиП

179

ПРИЛОЖЕНИЕ 1. ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ

ПРЕОБРАЗОВАНИЯ СТРОКОВОГО ПРЕДСТАВЛЕНИЯ

ЧИСЕЛ

Для работы со строками применяются следующие процедуры и функ-

ции (в квадратных скобках указываются необязательные параметры).

ПОДПРОГРАММЫ ПРЕОБРАЗОВАНИЯ СТРОК В ДРУГИЕ ТИПЫ Function StrToFloat(S: String): Extended;

Преобразует символы строки S в вещественное число. Строка не должна содержать ведущих или ведомых пробелов

Function StrToInt(S: String): Integer;

Преобразует символы строки S в целое число. Строка не должна содержать ведущих или ведомых пробелов

Procedure Val(S: String; var X, Code: Integer);

Преобразует строку символов S во внутреннее представление целой или вещественной перемен-ной X, которое определяется типом этой перемен-ной. Параметр Code содержит нуль, если преобра-зование прошло успешно

Подпрограммы обратного преобразования Function FloatToStr( Value: Extended): String;

Преобразует вещественное значение Value в строку символов

Function FloatToStrF(Value: Extended; Format: TFloat-Format; Precision, Digits: In-teger) : String;

Преобразует вещественное значение Value в строку символов с учетом параметров Precision и Digits (см. пояснения ниже)

Procedure Str(X [:width [:Decimals]]; var S: String);

Преобразует число Х любого вещественного или целого типа в строку символов S; параметры Width и Decimals, если они присутствуют, задают формат преобразования

Правила использования параметров функции FloatToStrF

Значение Format Описание ffExponent Научная форма представления с множителем еХХ. Precision

задает общее количество десятичных цифр мантиссы. Digits – количество цифр в десятичном порядке XX.

ffFixed Формат с фиксированным положением разделителя целой и дробной частей. Precision задает общее количество десятич-ных цифр в представлении числа. Digits – количество цифр в дробной части. Число округляется с учетом первой отбрасы-ваемой цифры: 3,14

ffGeneral Универсальный формат, использующий наиболее удобную для чтения форму представления вещественного числа. Соот-ветствует формату ffFixed, если количество цифр в целой части меньше или равно Precision, а само число – больше или равно 0,00001, в противном случае соответствует формату ffExponent: 3,1416

Page 180: НовыеЛекции ОАиП

180

ffNumber Отличается от ffFixed использованием символа - разделителя тысяч при выводе больших чисел (для русифицированной версии Windows таким разделителем является пробел)

ffCurrency Денежный формат. Соответствует ffNumber, но в конце строки ставится символ денежной единицы (для русифицированной версии Windows – символы «р.»). Для Value = *1000 полу-чим: 3 141,60р

Page 181: НовыеЛекции ОАиП

181

ПРИЛОЖЕНИЕ 2. МАТЕМАТИЧЕСКИЕ ФОРМУЛЫ

Язык Object Pascal имеет ограниченное количество встроенных матема-

тических функций. Поэтому при необходимости использовать другие функ-

ции следует применять известные соотношения или модуль Math. В таблице

приведены выражения наиболее часто встречающихся функций.

Функция Соотношение Модуль Math

)(xLog a )(

)(

aLn

xLn

LogN(a, x)

ax )(xLnae Power(x,a)

)(xTg )(

)(

xCos

xSin

Tan(x)

)(xCtg )(

)(

xSin

xCos

CoTan(x)

)(xArcSin 21

xArcTg

x

ArcSin(x)

)(xArcCos )(xArcSin

2

ArcCos(x)

)(xArcCtg )(xArcTg

2

)(xSh

2

ee xx

Sinh(x)

)(xCh

2

ee xx

Cosh(x)

( )Sign x

1, если x>0; 0, если x=0; -1, если x<0

( )Sign x

Page 182: НовыеЛекции ОАиП

182

ПРИЛОЖЕНИЕ 3. ТАБЛИЦЫ СИМВОЛОВ ASCII

Стандартная часть таблицы символов ASCII

КС С КС С КС С КС С КС С КС С КС С КС С

0 16 ╸ 32 48 0 64 @ 80 P 96 ` 112 p

1 ╾ 17 ╺ 33 ! 49 1 65 A 81 Q 97 a 113 q

2 ╿ 18 ↕ 34 " 50 2 66 B 82 R 98 b 114 r

3 ▅ 19 ‼ 35 # 51 3 67 C 83 S 99 c 115 s

4 ▆ 20 ¶ 36 $ 52 4 68 D 84 T 100 d 116 t

5 ▄ 21 § 37 % 53 5 69 E 85 U 101 e 117 u

6 ▃ 22 ╶ 38 & 54 6 70 F 86 V 102 f 118 v

7 • 23 ↖ 39 ' 55 7 71 G 87 W 103 g 119 w

8 ╼ 24 ↑ 40 ( 56 8 72 H 88 X 104 h 120 x

9 ╻ 25 ↓ 41 ) 57 9 73 I 89 Y 105 i 121 y

10 ╽ 26 → 42 * 58 : 74 J 90 Z 106 j 122 z

11 ▂ 27 ← 43 + 59 ; 75 K 91 [ 107 k 123 {

12 ▁ 28 ↗ 44 , 60 < 76 L 92 \ 108 l 124 |

13 ▇ 29 ↔ 45 - 61 = 77 M 93 ] 109 m 125 }

14 █ 30 ╷ 46 . 62 > 78 N 94 ^ 110 n 126 ~

15 ▀ 31 ╹ 47 / 63 ? 79 O 95 _ 111 o 127 ⌂

Некоторые из вышеперечисленных символов имеют особый смысл.

Так, например, символ с кодом 9 обозначает символ горизонтальной табу-

ляции, символ с кодом 10 – символ перевода строки, символ с кодом 13 –

символ возврата каретки.

Дополнительная часть таблицы символов

КС С КС С КС С КС С КС С КС С КС С КС С

128 А 144 Р 160 а 176 ╲ 192 └ 208 ╨ 224 р 240 Ё

129 Б 145 С 161 б 177 ╳ 193 ┴ 209 ╤ 225 с 241 ѐ

130 В 146 Т 162 в 178 ╴ 194 ┬ 210 ╥ 226 т 242 Є

131 Г 147 У 163 г 179 │ 195 ├ 211 ╙ 227 у 243 є

132 Д 148 Ф 164 д 180 ┤ 196 ─ 212 ╘ 228 ф 244 Ї

133 Е 149 Х 165 е 181 ╡ 197 ┼ 213 ╒ 229 х 245 ї

134 Ж 150 Ц 166 ж 182 ╢ 198 ╞ 214 ╓ 230 ц 246 Ў

135 З 151 Ч 167 з 183 ╖ 199 ╟ 215 ╫ 231 ч 247 ў

136 И 152 Ш 168 и 184 ╕ 200 ╚ 216 ╪ 232 ш 248 °

137 Й 153 Щ 169 й 185 ╣ 201 ╔ 217 ┘ 233 щ 249 ∙

138 К 154 Ъ 170 к 186 ║ 202 ╩ 218 ┌ 234 ъ 250 ∙

139 Л 155 Ы 171 л 187 ╗ 203 ╦ 219 ╯ 235 ы 251 √

140 М 156 Ь 172 м 188 ╝ 204 ╠ 220 ╮ 236 ь 252 №

Page 183: НовыеЛекции ОАиП

183

141 Н 157 Э 173 н 189 ╜ 205 ═ 221 ╰ 237 э 253 ¤

142 О 158 Ю 174 о 190 ╛ 206 ╬ 222 ╱ 238 ю 254 ╵

143 П 159 Я 175 п 191 ┐ 207 ╧ 223 ╭ 239 я 255

В таблицах обозначение КС означает "код символа", а С – "символ".

Page 184: НовыеЛекции ОАиП

184

ЛИТЕРАТУРА

1. Архангельский А. Я. Программирование в Delphi 7 / А. Я. Архангель-

ский. – М. : ЗАО «Издательство БИНОМ», 2003.

2. Фаронов В. В. Delphi 6: Учебный курс. / В. В. Фаронов. – М.: Издатель

Молгачева С.В., 2001.

3. Дж. Гленн Брукшир. Введение в компьютерные науки / Дж. Гленн

Брукшир. – «Вильямс» М, С-П, Киев. 2001.

4. А. К. Синицын, С. В. Колосов, А. А. Навроцкий и др. Программирова-

ние алгоритмов в среде Delphi. Лаб. практикум. Ч. 1. – Мн., БГУИР,

2004.

5. Колосов С. В. Программирование в Delphi. Учеб. пособие – Мн.,

БГУИР, 2005.

6. Калиткин, Н. Н. Численные методы / Н. Н. Калиткин. – М. : Наука,

1978.

7. Бахвалов, Н. С. Численные методы / Н. С. Бахвалов – М. : Наука, 1975.

8. Численные методы анализа / В. П. Демидович [и др.]. – М. : Физматгиз,

1963.

9. Волков, Е. А. Численные методы / Е. А. Волков – М. : Наука, 1982.

10. Вычислительные методы высшей математики / В. И. Крылов [и др.]. –

Мн. : Вышэйшая школа, 1972. – Т.1.

11. Вычислительные методы высшей математики / В. И. Крылов [и др.]. –

Мн. : Вышэйшая школа, 1975. – Т.2.

12. Машинные методы математических вычислений / Дж. Форсайт [и др.].

– М. : Мир, 1980.

13. Шуп Т. Решение инженерных задач на ЭВМ / Т. Шуп – М. : Мир, 1982.

14. Самарский, А. А. Введение в численные методы / А. А. Самарский. –

М. : Наука, 1982.

15. Березин, И. С. Методы вычислений / И. С. Березин, Н. П. Жидков – М.

: Физматгиз, 1962. – Т.1.

16. Березин, И. С. Методы вычислений / И. С. Березин, Н. П. Жидков – М.

: Физматгиз, 1970. – Т.2.

17. Банди, Б. Методы оптимизации: Вводный курс / Б. Банди. – М. : Мир,

1989.

18. Копченова, Н. В. Вычислительная математика в примерах и задачах /

Н. В. Копченова, И. А. Марон – М. : Наука, 1972.

19. Мак-Кракен, Д. Численные методы и программирование на Фортране /

Д. Мак-Кракен, У. Дорн – М. : Мир, 1972.

20. Дьяконов, В. П. Справочник по алгоритмам и программам на языке

Бейсик для ПЭВМ / В. П. Дьяконов – М. : Наука, 1989.