/
Author: Васильев А.Н.
Tags: самоучитель численные методы компьютерные технологии язык программирования matlab
Year: 2015
Text
Наука и Техника
Санкт-Петербург
2015
Васильев А. Н.
Matlab
САМОУЧИТЕЛЬ
ПРАКТИЧЕСКИЙ
ПОДХОД
(2-Е ИЗДАНИЕ)
Контактные телефоны издательства:
(812) 412 70 25, (812) 412 70 26, (044) 516 38 66
Официальный сайт: www.nit.com.ru
© Васильев А. Н ., 2015
© Наука и техника (оригинал-макет), 2015
© Прокди, 2015
Данная книга представляет собой 2-е издание отличного самоучителя по работе
с Matlab и проведению в нем различных вычислений, расчетов, обработок данных
и исследований. С одной стороны, отличается хорошим справочным аппаратом
и общим описанием различных аспектов работы в Matlab, а с другой — большим
количеством наглядных примеров и пошаговых действий. Весь теоретический
материал поддержан реальными практическими примерами.
Книга отличается доступным языком изложения, охватом всех основных приемов
работы, богатым иллюстративным материалом. Основывается на последних
версиях Matlab, доступных в 2014 г. Лучший выбор для всех, кто хочет освоить
Matlab и научиться эффективно им пользоваться.
Васильев А. Н.
MATLAB. САМОУЧИТЕЛЬ. ПРАКТИЧЕСКИЙ ПОДХОД. 2-Е ИЗДАНИЕ. — СПб.: Наука
и Техника, 2015. — 448 с.: ил.
Серия “Самоучитель“
5
Оглавление
ВСТУПЛЕНИЕ О КНИГЕ И ПАКЕТЕ MATLAB................................. 11
Ãëàâà 1. ПРИНЦИПЫ РАБОТЫ MATLAB
И ОСНОВЫ ВЫЧИСЛЕНИЙ ...................................... 15
Ãëàâà 2. ГРАФИКА В MATLAB............................................... 42
Ãëàâà 3. ЭЛЕМЕНТЫ ПРОГРАММИРОВАНИЯ .........................104
Ãëàâà 4. ЭЛЕМЕНТЫ МАТРИЧНОЙ АЛГЕБРЫ .........................149
Ãëàâà 5. РЕШЕНИЕ УРАВНЕНИЙ И ОПТИМИЗАЦИЯ .................199
Ãëàâà 6. ИНТЕГРИРОВАНИЕ И ДИФФЕРЕНЦИАЛЬНЫЕ
УРАВНЕНИЯ ........................................................236
Ãëàâà 7. УРАВНЕНИЯ МАТЕМАТИЧЕСКОЙ ФИЗИКИ ................273
Ãëàâà 8. ОБРАБОТКА ДАННЫХ ...........................................311
Ãëàâà 9. СИМВОЛЬНЫЕ ВЫЧИСЛЕНИЯ ................................348
ПРИЛОЖЕНИЕ А. ФАЙЛОВЫЙ ВВОД/ВЫВОД ...........................418
ПРИЛОЖЕНИЕ Б. СТРУКТУРЫ И ЯЧЕЙКИ .................................423
ПРИЛОЖЕНИЕ В. НАДСТРОЙКА ДЛЯ РАБОТЫ С EXCEL ..............429
6
Содержание
ВСТУПЛЕНИЕ
О КНИГЕ И ПАКЕТЕ MATLAB ......................................... 11
ЕЩЕ НЕМНОГО О ПАКЕТЕ .............................................................................................. 12
СТРУКТУРА КНИГИ ....................................................................................................... 13
ОБРАТНАЯ СВЯЗЬ ........................................................................................................ 14
Ãëàâà 1. ПРИНЦИПЫ РАБОТЫ MATLAB
И ОСНОВЫ ВЫЧИСЛЕНИЙ ...................................... 15
ПРОСТЫЕ ВЫЧИСЛЕНИЯ............................................................................................... 15
АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ ...................................................................................... 22
ЛОГИЧЕСКИЕ ОПЕРАТОРЫ И ОПЕРАТОРЫ СРАВНЕНИЯ ....................................................... 26
КОМПЛЕКСНЫЕ ЧИСЛА................................................................................................. 27
ОПЕРАТОР СОЗДАНИЯ ИНТЕРВАЛА ЗНАЧЕНИЙ ................................................................. 29
ВСТРОЕННЫЕ МАТЕМАТИЧЕСКИЕ ФУНКЦИИ .................................................................... 31
ФОРМАТ ВЫВОДА ЧИСЛОВЫХ ДАННЫХ .......................................................................... 38
Ãëàâà 2. ГРАФИКА В MATLAB............................................... 42
СОЗДАНИЕ ГРАФИКА ФУНКЦИИ ..................................................................................... 42
ОТОБРАЖЕНИЕ НЕСКОЛЬКИХ КРИВЫХ НА ОДНОМ ГРАФИКЕ............................................... 47
НАСТРОЙКИ ВИДА ГРАФИКА .......................................................................................... 51
ГРАФИК В ПОЛЯРНЫХ КООРДИНАТАХ ............................................................................. 64
КОНТУРНЫЕ ГРАФИКИ .................................................................................................. 71
Содержание
7
СОЗДАНИЕ ТРЕХМЕРНЫХ ГРАФИКОВ.............................................................................. 79
ПАРАМЕТРИЧЕСКИЕ КРИВЫЕ И ПОВЕРХНОСТИ ................................................................ 83
ПАРАМЕТРЫ ТРЕХМЕРНОЙ ГРАФИКИ .............................................................................. 86
АНИМАЦИЯ................................................................................................................. 89
ИСПОЛЬЗОВАНИЕ ИЗОБРАЖЕНИЙ ................................................................................. 98
Ãëàâà 3. ЭЛЕМЕНТЫ ПРОГРАММИРОВАНИЯ .........................104
СОЗДАНИЕ СЦЕНАРИЕВ ...............................................................................................104
ФУНКЦИИ ПОЛЬЗОВАТЕЛЯ...........................................................................................109
УПРАВЛЯЮЩИЕ ИНСТРУКЦИИ ......................................................................................119
ЛОГИЧЕСКИЕ ЗНАЧЕНИЯ И ЛОГИЧЕСКИЕ ОПЕРАТОРЫ ......................................................130
ОБРАБОТКА ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ ...................................................................133
ФУНКЦИИ С ПЕРЕМЕННЫМ ЧИСЛОМ АРГУМЕНТОВ ..........................................................139
ФУНКЦИИ EVAL () И FEVAL () ..........................................................................................145
Ãëàâà 4. ЭЛЕМЕНТЫ МАТРИЧНОЙ АЛГЕБРЫ .........................149
ВЕКТОРЫ И ОПЕРАЦИИ С НИМИ ....................................................................................149
ОПЕРАЦИИ С МАТРИЦАМИ ...........................................................................................155
ПРЕОБРАЗОВАНИЕ МАТРИЦ .........................................................................................169
НЕКОТОРЫЕ ПРИМЕРЫ................................................................................................178
Ãëàâà 5. РЕШЕНИЕ УРАВНЕНИЙ И ОПТИМИЗАЦИЯ .................199
ВСТРОЕННЫЕ ФУНКЦИИ ДЛЯ РЕШЕНИЯ УРАВНЕНИЙ........................................................199
ВЫЧИСЛЕНИЕ КОРНЕЙ УРАВНЕНИЙ
В ЯВНОМ ВИДЕ............................................................................................209
ОПТИМИЗАЦИЯ ..........................................................................................................232
Ãëàâà 6. ИНТЕГРИРОВАНИЕ И ДИФФЕРЕНЦИАЛЬНЫЕ
УРАВНЕНИЯ ........................................................236
ВЫЧИСЛЕНИЕ ОПРЕДЕЛЕННЫХ ИНТЕГРАЛОВ .................................................................236
Содержание
8
ДИФФЕРЕНЦИАЛЬНЫЕ УРАВНЕНИЯ ..............................................................................244
РЕШЕНИЕ СИСТЕМЫ ДИФФЕРЕНЦИАЛЬНЫХ УРАВНЕНИЙ .................................................249
УРАВНЕНИЯ ВЫСОКИХ ПОРЯДКОВ ................................................................................251
СНОВА ОБ ИНТЕГРАЛАХ ...............................................................................................254
РЕШЕНИЕ НЕЯВНЫХ УРАВНЕНИЙ ..................................................................................260
КРАЕВЫЕ ЗАДАЧИ.......................................................................................................262
ЗАВЕРШАЮЩИЙ ПРИМЕР............................................................................................270
Ãëàâà 7. УРАВНЕНИЯ МАТЕМАТИЧЕСКОЙ ФИЗИКИ ................273
ОДНОМЕРНЫЙ СЛУЧАЙ ...............................................................................................274
ЗНАКОМСТВО СО СРЕДОЙ PDETOOL ..............................................................................284
ОБРАБОТКА АНАЛИТИЧЕСКИХ РЕЗУЛЬТАТОВ...................................................................300
Ãëàâà 8. ОБРАБОТКА ДАННЫХ ...........................................311
ИНТЕРПОЛЯЦИОННЫЕ ПОЛИНОМЫ...............................................................................311
АППРОКСИМАЦИЯ ......................................................................................................320
ГЕНЕРИРОВАНИЕ СЛУЧАЙНЫХ ЧИСЕЛ............................................................................335
СТАТИСТИЧЕСКИЕ ВЫЧИСЛЕНИЯ ..................................................................................344
Ãëàâà 9. СИМВОЛЬНЫЕ ВЫЧИСЛЕНИЯ ................................348
ИСПОЛЬЗОВАНИЕ СИМВОЛЬНЫХ ПЕРЕМЕННЫХ .............................................................348
ОСНОВНЫЕ СИМВОЛЬНЫЕ ОПЕРАЦИИ...........................................................................354
СРЕДА MUPAD ............................................................................................................364
ОПРЕДЕЛЕНИЕ ФУНКЦИИ ............................................................................................370
ВЫЧИСЛЕНИЕ ПРОИЗВОДНЫХ .....................................................................................373
ВЫЧИСЛЕНИЕ ИНТЕГРАЛОВ .........................................................................................378
РЕШЕНИЕ АЛГЕБРАИЧЕСКИХ УРАВНЕНИЙ И НЕРАВЕНСТВ .................................................380
РЕШЕНИЕ ДИФФЕРЕНЦИАЛЬНЫХ УРАВНЕНИЙ ................................................................382
Содержание
9
ЭЛЕМЕНТЫ ПРОГРАММИРОВАНИЯ ................................................................................384
РЕДАКТОР КОДОВ.......................................................................................................403
СОЗДАНИЕ АНИМАЦИИ................................................................................................409
НЕСКОЛЬКО ЗАМЕЧАНИЙ О СОЗДАНИИ ГРАФИКИ............................................................415
ПРИЛОЖЕНИЕ А. ФАЙЛОВЫЙ ВВОД/ВЫВОД ...........................418
ПРИЛОЖЕНИЕ Б. СТРУКТУРЫ И ЯЧЕЙКИ .................................423
ПРИЛОЖЕНИЕ В. НАДСТРОЙКА ДЛЯ РАБОТЫ С EXCEL ..............429
СПИСОК ЛИТЕРАТУРЫ
ПОЛЕЗНЫЕ И НЕ ОЧЕНЬ ССЫЛКИ................................441
БАЗОВЫЕ МЕТОДЫ РАБОТЫ С MATLAB...........................................................................441
ПРИКЛАДНЫЕ ВЫЧИСЛЕНИЯ В MATLAB..........................................................................441
СМЕЖНЫЕ ВОПРОСЫ РАБОТЫ С MATLAB........................................................................442
МАТЕМАТИКА И ЧИСЛЕННЫЕ МЕТОДЫ ...........................................................................442
11
Вступление
О книге и пакете Matlab
Дайте, я скажу то, что сказал.
М. Горбачев
Как в свое время утверждал классик в своих законах диалектики – коли-
чественные изменения переходят в качественные. Сложно сказать, когда
точно на рынке программных продуктов произошел качественный скачок,
но смело можно утверждать, что на сегодня существует ряд пакетов, кото-
рые в корне меняют наше устоявшееся представление о программирова-
нии и методах использования компьютера при решении прикладных задач.
В данном случае речь идет о математических пакетах.
Среди наиболее популярных на сегодня пакетов можно выделить четыре
основных, которые в определенном смысле являются законодателями моды.
Это Maple, Mathematica, Mathcad и Matlab. Пакеты Maple и Mathematica
предназначены, в первую очередь, для символьных расчетов, для числовых
же используют в основном Mathcad и Matlab. Причем если пакет Mathcad
играет роль "легкой кавалерии" (он прост в обращении и эффективен при
выполнении не очень сложных расчетов), то пакет Matlab в полной мере
соответствует представлениям о фундаментальном, качественном и много-
функциональном средстве для выполнения числовых расчетов. Описаниям
возможностей пакета Matlab для решения базовых прикладных математи-
ческих и физических задач уделяется основное внимание в этой книге. Вме-
сте с тем следует понимать, что даже в самой большой книге невозможно
полностью описать все (или почти все) возможности приложения. Предла-
гаемая вниманию читателя книга в некотором смысле отличается от других
книг, посвященных Matlab. Книга принципиально задумывалась как не-
большая (хотя такое понятие, как небольшая, является очень относитель-
ным). Вместе с тем была предпринята попытка написать книгу информа-
тивную. Во многом эти задачи являются взаимоисключающими. Поэтому
нередко приходилось чем-то жертвовать. С другой стороны, главная зада-
ча состояла в том, чтобы показать красоту и эффективность приложения
Matlab при решении прикладных задач. Многие, кто осваивал работу с ма-
тематическими пакетами, на своем опыте знают, что в этом случае важно
понять "идеологию" пакета, поскольку именно такое понимание является
теми вратами, через которые можно выйти на широкий и перспективный
путь использования пакета. В противном случае придется пробираться бо-
лее тернистым путем – не таким широким и более извилистым.
Самоучитель Matlab
12
Еще немного о пакете
Что же это получается?
Чудеса за наличный расчет?!
К/ф "Чародеи"
Название пакета Matlab является сокращением от английского Matrix
Laboratory (что означает матричная лаборатория). Этим же термином
(то есть Matlab) называют и язык программирования, используемый для
составления программных кодов. Как известно, программный код мо-
жет компилироваться или интерпретироваться. В первом случае по-
лучаем исполнительный (машинный) код, который выполняется цен-
тральным процессором. При интерпретации происходит преобразование
в промежуточный код, который выполняется непосредственно системой-
интерпретатором. Скомпилированный код обычно выполняется быстрее,
чем интерпретируемый код. Вместе с тем интерпретируемые языки про-
граммирования, как правило, более демократичны в плане синтаксиса. Про-
граммный код Matlab интерпретируется. Однако это никак не ставит под
сомнение вычислительные возможности Matlab. Основой для реализации
разных типов данных в Matlab являются матрицы, что объясняет многие
особенности среды (и языка программирования) Matlab. К матрицам мы
будем достаточно часто апеллировать по ходу изложения материала книги.
Значительная часть функциональных возможностей приложения Matlab
реализована через пакеты инструментов (английский термин toolbox). Это
коллекции функций и других утилит, предназначенных для решения узко-
специальных задач. В книге, за редкими исключениями, пакеты инструмен-
тов не описываются. Основное внимание уделяется функциям стандартной
библиотеки. Причина простая и прозаичная – каждый отдельный пакет
инструментов может быть темой отдельной книги. Но проблема даже не
в этом, а скорее в том, что большинство пакетов имеют узкую, специфиче-
скую направленность, и это обстоятельство контрастирует с базовым под-
ходом, реализованном в книге – максимум универсальности при разумном
объеме текста.
Как уже отмечалось, приложение Matlab предназначено (в первую очередь)
для выполнения числовых расчетов и визуализации получаемых результа-
тов. Пакет содержит огромное число утилит для выполнения самых разных
операций и позволяет создавать собственные полнофункциональные про-
граммные коды. Вместе с тем в Matlab могут выполняться и символьные
расчеты. Этой цели служит встроенная в Matlab среда MuPAD. Таким об-
разом, пользователю Matlab предоставляются широкие возможности не
только в области числовых, но и символьных расчетов (сразу отметим, что
методы символьных вычислений в Matlab описываются в последней главе
Вступление. О книге и пакете Matlab
13
книги). В этом отношении можно говорить о значительной универсально-
сти приложения Matlab. Именно показать эту универсальность мы попыта-
лись в книге.
Структура книги
Видите ли, при моей работе нужно
повторять некоторые вещи снова,
снова и снова...
Дж. Буш (младший)
Книга состоит из девяти глав и приложений. В основных главах книги опи-
саны базовые принципы работы с приложением Matlab. В частности, чита-
тель найдет для себя полезную информацию в области:
• алгебраических вычислений (глава 1),
• создания графики и анимации (глава 2),
• принципов программирования (глава 3),
• матричной алгебры (глава 4),
• решения алгебраических уравнений и систем (глава 5),
• интегрирования и решения обыкновенных дифференциальных уравне-
ний (глава 6),
• решения уравнений в частных производных (глава 7),
• обработки статистических данных (глава 8),
• символьных вычислений (глава 9).
Часть полезной информации вынесена в приложения. Наибольший ин-
терес, возможно, у читателя вызовет краткое описание надстройки, по-
зволяющей получать доступ к вычислительным возможностям Matlab из
приложения Microsoft Excel. Эта тема, безусловно, предназначена в первую
очередь для тех, кто много работает с электронными таблицами.
Некоторые моменты в книге, которые имеют важное значение для понима-
ния излагаемого в книге материала, выделены специальным образом.
На заметку
В качестве основной версии Matlab, которая использовалась при описании при-
меров в книге, стала версия R2010b. Именно на этой версии приложения тестиро-
вались примеры из книги. Вместе с тем коды достаточно универсальные, поэто-
му есть основания полагать, что они будут работать и с последующими версиями
продукта (чего, к сожалению, нельзя сказать о более ранних версиях Matlab).
Самоучитель Matlab
14
Обратная связь
Теперь я пойду с ещё большим забралом.
М. Горбачев
Некоторую полезную информацию читатели смогут найти на персональной
странице автора по адресу www.vasilev.kiev.ua. Задать вопросы или
высказать свои пожелания можно по электронной почте alex@vasilev.
kiev.ua.
15
Глава 1
Принципы работы Matlab и основы
вычислений
Я считаю своим долгом поведать, наконец,
как все было на самом деле.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Приложение Matlab предназначено для выполнения сложных (и не очень)
профессиональных расчетов в самых различных областях естествознания.
Тем не менее, памятуя о том, что все большое начинается с малого, изучение
методов работы с приложением Matlab начнем с азов – рассмотрим поша-
говые вычисления.
Простые вычисления
Всю весну и все лето и так, и эдак прики-
дывал Крот. И, наконец, осенью решил же-
ниться.
М/ф "Дюймовочка"
Под простыми, или пошаговыми, подразумевают вычисления, обычно вы-
полняемые в командном окне приложения Matlab. Соответствующая ин-
струкция или команда вводится в командном окне и затем выполняется. На
рис. 1.1 показано, как может выглядеть рабочее окно приложения Matlab
при запуске.
Интерес в данном случае представляет внутреннее окно (обычно в центре
рабочего окна приложения) с названием Command Window – командное
окно. В этом окне можно заметить индикатор строки ввода (в виде двой-
ной стрелки >>). Для ввода команды курсор необходимо переместить после
индикатора строки ввода и ввести инструкцию для выполнения. Другими
словами, в строку ввода командного окна необходимо ввести выражение и,
нажав клавишу <Enter>, запустить процесс вычисления этого выражения.
Результат вычислений отображается внизу, под выполняемой командой. По
умолчанию результат заносится в системную переменную ans. На рис. 1.2
приведен пример вычисления нескольких арифметических выражений.
В данном случае приведены результаты вычисления выражений 1+2*3
и (5^2-4)/7 соответственно. В первом случае, как и ожидалось, получаем
в качестве результата значение 7, во втором – значение 3.
Самоучитель Matlab
16
Рис. 1.1. Рабочее окно приложения Matlab
Рис. 1.2 . Простые арифметические вычисления
Глава 1. Принципы работы Matlab и основы вычислений
17
На заметку
Чтобы "отделить" командное окно от структуры рабочего окна приложения Mat-
lab, достаточно щелкнуть на пиктограмме с витой стрелкой в строке названия
окна. В левой нижней части командного окна отображается пиктограмма ути-
литы подбора функций. Убирается и отображается эта пиктограмма с помощью
контекстного меню. Вообще же, здесь и далее материал книги излагается с тем
расчетом, что базовые манипуляции с элементами графического интерфейса
приложения Matlab читатель сможет выполнять самостоятельно. Если все же
проблемы в этом плане возникнут, можно обратиться к литературе, специально
посвященной вопросу правильного нажимания кнопок.
Что касается непосредственно вычислений, то, например, для вычисления вы-
ражения 1+2*3 соответствующую инструкцию вводим в командную строку, по-
сле чего нажимаем клавишу <Enter>. Выражение вычисляется, результат ото-
бражается под строкой ввода в формате
ans=
результат
Далее отображается индикатор строки ввода для вычисления следующего вы-
ражения. Следует также иметь в виду, что редактировать команду ввода можно,
только пока она не выполнена.
В качестве основных арифметических операторов в Matlab используются:
оператор + для вычисления суммы, оператор – для вычисления разности,
оператор * для вычисления произведения, оператор / для вычисления част-
ного и оператор ^ для возведения в степень. Это далеко не все арифмети-
ческие операторы. Арифметическим операторам Matlab посвящен отдель-
ный раздел этой главы. Пока же ограничимся тем, что будем использовать
перечисленные выше операторы для работы со скалярными величинами.
Однако совершенно очевидно, что ценность приложения Matlab была бы
невелика, если бы возможности Matlab ограничивались арифметическими
вычислениями, подобными тем, что приведены выше. Для более сложных
вычислений обычно приходится вводить переменные.
В общем смысле переменная – это область памяти, к которой можно об-
ращаться по имени для получения значения, записанного в этой области,
а также его изменения. В строго типизированных языках программирова-
ния (таких, как С++, Java или Pascal) для использования переменной не-
обходимо предварительно ее объявить, указав при этом, к какому типу она
относится. В Matlab ничего подобного делать не нужно. Переменной сразу
можно присваивать значение. В качестве оператора присваивания исполь-
зуется знак равенства =. Имя переменной, которой присваивается значение,
указывается слева от оператора присваивания, а присваиваемое перемен-
ной значение – справа от оператора присваивания. Значение, присваивае-
мое переменной, если речь идет о скалярных величинах, может быть числом
Самоучитель Matlab
18
или выражением, содержащим другие переменные. При этом необходимо,
чтобы этим переменным ранее уже было присвоено значение. Пример ис-
пользования скалярных переменных в пошаговых вычислениях приведен
в рабочем документе на рис. 1.3.
Рис. 1.3. Использование в вычислениях переменных
Первой командой x=0.5*sin(0.1) присваивается значение переменной
x. При этом использована встроенная функция Matlab sin() для вычисле-
ния синуса. Присвоенное в результате этой переменной значение отобража-
ется внизу под строкой ввода в формате
переменная=
значение
Аналогично следующей командой y=0.3*cos(0.2) значение присваи-
вается переменной y. Здесь cos() – встроенная функция Matlab для вы-
числения косинуса. Обращаем также внимание читателя, что в качестве
десятичного разделителя при вводе действительных чисел с дробной деся-
тичной частью используется точка.
Наконец, командой z=(x^2+y^2)^(1/3) значение присваивается пере-
менной z. В выражение, определяющее значение переменной z, входят пе-
ременные x и y. Однако поскольку предварительно этим переменным были
присвоены значения, ошибки не возникает и значение переменной z при-
сваивается корректно.
Есть две базовые операции, которые достаточно полезны, особенно при
большем объеме вычислений. Во-первых, в некоторых случаях нужно
Глава 1. Принципы работы Matlab и основы вычислений
19
узнать, какие переменные рабочего пространства уже используются, и,
во-вторых, иногда приходится, образно выражаясь, "удалять переменные
с игрового поля" – то есть освобождать память, выделенную под эти пере-
менные. Первая операция выполняется с помощью инструкции whos. Если
ввести в командную строку эту инструкцию и нажать клавишу <Enter>, бу-
дет выведен список доступных в рабочем пространстве переменных с опи-
санием их некоторых атрибутов. Пример использования инструкции whos
приведен в документе на рис. 1.4.
Рис. 1.4. Список переменных рабочего пространства
В данном случае список состоит из четырех переменных: трех объявленных
переменных пользователя x, y и z, и системной переменной ans.
Очистка пространства переменных осуществляется с помощью инструк-
ции clear, после которой, через пробел, указываются имена удаляемых
переменных. На рис. 1.5 представлен результат выполнения команды
clear x y, после которой выполнена команда whos для проверки списка
переменных рабочего пространства.
Рис. 1.5 . Очистка пространства переменных
Поскольку командой clear x y переменные x и y из рабочего простран-
ства удалены, в списке переменных остались только переменная z и систем-
ная переменная ans.
Самоучитель Matlab
20
На заметку
Хотя значение переменной z присваивается на основе значений переменных
x и y, их удаление из рабочего пространства (или изменение их значения) на
значение переменной z никак не влияет.
Для удаления из рабочего пространства всех переменных используют инструк-
цию clear без указания переменных.
В предыдущих примерах использовались скалярные величины. С точки
зрения основополагающей идеологии и технической реализации, скаляры
в Matlab являются скорее экзотикой, чем обычным явлением. Дело в том,
что в Matlab базовым типом данных являются матрицы (или массивы).
В этом отношении скаляр "с точки зрения Matlab" (если можно так выра-
зиться) является матрицей размера 1×1.
Как известно, массивы можно индексировать, то есть для доступа к элемен-
ту массива указывается имя массива и его индекс (или индексы). Индексы
указываются после имени матрицы (массива) в круглых скобках и разделя-
ются запятыми. К скалярной переменной можно обращаться как по имени,
так и указав индексы – в данном случае это (1,1). Пример обращения к ска-
лярной величине в обычном режиме и с помощью пары единичных индек-
сов показан в документе на рис. 1.6.
Рис. 1.6. Обращение к скаляру как к элементу матрицы
Командой MyVar=10 переменной MyVar присваивается значение 10. Об-
ращаться к переменной можно как по имени MyVar, так и в режиме обраще-
Глава 1. Принципы работы Matlab и основы вычислений
21
ния к элементу матрицы MyVar(1,1). В обоих случаях в качестве резуль-
тата возвращается значение скалярной переменной MyVar.
Поскольку все переменные в Matlab априори рассматриваются как матри-
цы, никаких особых инструкций при объявлении матриц выполнять не
нужно, за исключением того, что для матрицы необходимо задать значе-
ния ее элементов. Делается это достаточно просто. Список элементов ма-
трицы заключается в квадратные скобки, списки значений элементов стро-
ки разделяются запятыми или пробелами, а списки значений разных столб-
цов разделяются точкой с запятой. Например, командой A=[1 2 3] зада-
ется вектор-строка (матрица размеров 1×3) с элементами 1, 2 и 3 соответ-
ственно. Командой B=[4;5;6] задается вектор-столбец (матрица размеров
3×1) с элементами 4, 5 и 6. Наконец, командой C=[1,2;3,4;5,6] задается
матрица размерами 3×2 (3 строки и 2 столбца). Примеры выполнения этих
команд приведены в документе на рис. 1.7.
Рис. 1.7. Определение матричных переменных
К элементам матрицы можно обращаться в обычном режиме, указав два ин-
декса (номер строки и номер столбца, на пересечении которых находится
элемент). Существует также способ обращения по обобщенному индексу.
Обобщенный индекс элемента матрицы определяется как его порядковый
номер, если отсчет начинать с верхнего левого элемента сверху вниз и от
левого столбика к правому. Так, если матрица X имеет размеры n на m, то
Самоучитель Matlab
22
к элементу с индексами i и j можно обратиться либо как X(i,j), либо
как X(n*(j-1)+i). Хотя второй способ индексирования элементов может
показаться несколько запутанным, он соответствует техническому способу
индексации элементов матрицы в памяти, поэтому вычисления в таком слу-
чае выполняются быстрее. На рис. 1.8 приведен фрагмент документа, в ко-
тором в различном режиме выполняется обращение к элементам матрицы
C., определенной ранее (см. рис. 1.8).
Рис. 1.8. Способы обращения к элементам матрицы
В частности, командой C(1) получаем значение элемента C(1,1) (значе-
ние 1). Инструкция C(5) является ссылкой на элемент C(2,2), значение
которого равно 4.
Арифметические операции
-
Чем хотите пока заняться,
Состоятельные Кроты?
-
А что, если нам посчитать?!
-
И то дело!
М/ф "Дюймовочка"
Основные арифметические операторы Matlab позволяют выполнять опера-
ции не только со скалярными величинами, но и с матрицами. Более того,
можно утверждать, что основная часть операторов ориентирована на вы-
полнение матричных операций. В табл. 1.1 перечислены основные арифме-
тические операторы Matlab с кратким описанием результата их примене-
ния к операндам разного типа (если такие допустимы).
Глава 1. Принципы работы Matlab и основы вычислений
23
Табл. 1.1. Основные арифметические операторы Matlab
Оператор
Описание
+
Оператор сложения. Оператор бинарный. Операндами могут быть как
скалярные величины, так и матричные. Для двух скалярных операторов
выполняется сложение. Для двух матричных операндов (матрицы оди-
наковых размеров) выполняется поэлементное сложение: результатом
является матрица той же размерности, что и матрицы-операнды, а ее
элементы равны сумме соответствующих элементов складываемых
матриц. Если один операнд - скаляр, а другой – матрица, то результа-
том является матрица, каждый элемент которой равен сумме скаляра
и соответствующего элемента матрицы-операнда.
-
Оператор вычитания. Бинарный оператор. Операндами могут быт ска-
ляры, матрицы одинаковых размеров или матрица и скаляр. Для ска-
ляров вычисляется разность. Для операндов-матриц вычисляется ма-
трица, элементы которой равны разности соответствующих элементов
матриц-операндов. Если один операнд – матрица, а другой – скаляр,
то результатом является матрица, элементы которой вычисляются как
разность соответствующего элемента матрицы-операнда и скаляра
(с учетом порядка операндов). Можно вычитать скаляр из матрицы
и матрицу из скаляра
*
Оператор умножения. Бинарный оператор. Если операндами явля-
ются скаляры, вычисляется произведение скалярных величин. Для
операндов-матриц вычисляется матричное произведение. Если один
операнд – матрица, а другой - скаляр, результатом является матрица,
элементы которой вычисляются как произведение соответствующего
элемента матрицы-операнда и скаляра.
/
Оператор деления. Бинарный оператор. Если оба операнда – скаляры,
то в качестве результата возвращается частное от деления скаляра на
скаляр. Если первый операнд – матрица, а второй – скаляр, в качестве
результата возвращается матрица, каждый элемент которой получа-
ется поэлементным делением матрицы-операнда на скаляр. В случае
если оба операнда – квадратные матрицы одного ранга, в качестве ре-
зультата возвращается произведение матрицы - первого операнда на
матрицу, обратную к матрице - второму операнду.
^
Оператор возведения в степень. Бинарный оператор. Первым опе-
рандом может быть скаляр или квадратная матрица. Если первый опе-
ранд – скаляр, то второй может быть любым действительным скаляром.
В качестве результата возвращается первый операнд, возведенный
в степень, определяемую вторым операндом. Если первый операнд –
квадратная матрица, то второй операнд должен быть целочисленным
(может быть отрицательным). Результатом является матрица, вычис-
ляемая возведением матрицы-операнда в целочисленную степень,
определяемую вторым операндом.
\
Оператор левостороннего деления. Бинарный оператор. Операндами
являются квадратные матрицы одного ранга. Результатом является ма-
трица, равная произведению матрицы, обратной к первому операнду-
матрице, на второй операнд-матрицу.
Самоучитель Matlab
24
Оператор
Описание
.*
Оператор поэлементного умножения. Бинарный оператор. Операн-
дами являются матрицы одинакового размера. Результатом является
матрица, элементы которой равны произведению соответствующих
элементов матриц-операндов.
./
Оператор поэлементного деления. Бинарный оператор. Операндами
являются матрицы одинакового размера. Результатом является матри-
ца, элементы которой вычисляются как частное от деления элементов
матрицы - первого аргумента на соответствующие элементы матрицы
- второго аргумента
.\
Оператор поэлементного левостороннего деления. Бинарный опера-
тор. Операндами являются матрицы одинакового размера. Резуль-
татом является матрица того же размера. Выполняется деление эле-
ментов матрицы - второго операнда на соответствующие элементы
матрицы - первого операнда.
'
Оператор вычисления сопряженной матрицы. Унарный оператор. Ре-
зультатом является матрица, сопряженная к матрице-оператору.
.'
Оператор транспонирования. Унарный оператор. Результатом являет-
ся матрица, транспонированная к матрице-операнду.
.^
Оператор поэлементного возведения в степень. Бинарный оператор.
Операндами могут быть скаляры или матрицы (в разной комбинации).
Если первый аргумент – матрица, а второй – скаляр или матрица той же
размерности, то в качестве результата возвращается матрица, элементы
которой получаются возведением элементов первой матрицы в степень,
определяемую вторым операндом-скаляром или соответствующими
элементами второго операнда-матрицы. Если первый операнд скаляр-
ный, а второй является матрицей, то результатом будет матрица того же
размера, что матрица-операнд (второй). Элементы матрицы-результата
получаются возведением скаляра (первый операнд) в степень, опреде-
ляемую соответствующим элементом второго (матричного) операнда.
Приведенные операторы практически полностью перекрывают весь спектр
возможных операций, которые приходится выполнять с матрицами. Неко-
торые примеры использования арифметических операторов с матричными
операндами приведены в табл. 1.2. Матрицы A и B при этом инициализи-
рованы в документе следующими командами (жирным шрифтом выделен
ввод пользователя):
>> A=[1,3;-2,4]
A=
13
-24
>> B=[-1,1;3,-2]
B=
-1
1
3-2
Глава 1. Принципы работы Matlab и основы вычислений
25
Табл. 1.2. Примеры выполнения арифметических операций с матрицами
Команды
Описание
>> A*B
ans =
8-5
14 -10
Произведение матриц.
Вычисляется по правилам вычисления матриц
в линейной алгебре
>> A/B
ans =
114
82
Деление матриц.
Матрица A умножается на матрицу, обратную
к матрице B
>> A\B
ans =
-1.3000 1.0000
0.1000
0
Левостороннее умножение матриц.
Матрица, обратная к матрице A, умножается на
матрицу B
>> A./B
ans =
-1.0000 3.0000
-0.6667 -2.0000
Поэлементное деление матриц.
Элементы матрицы A делятся на соответствую-
щие элементы матрицы B
>> A.\B
ans =
-1.0000 0.3333
-1.5000 -0.5000
Левостороннее поэлементное деление.
Элементы матрицы B делятся на соответствую-
щие элементы матрицы A
>> A.*B
ans =
-13
-6
-8
Поэлементное умножение матриц.
Элементы матрицы A умножаются на соответ-
ствующие элементы матрицы B
>> A+B
ans =
0
4
1
2
Сумма матриц.
Вычисляется по правилам вычисления суммы
матриц в линейной алгебре (складываются со-
ответствующие элементы матриц A и B)
>> A-B
ans =
2
2
-5
6
Разность матриц.
Вычисляется по правилам расчета разности
двух матриц (от элементов матрицы A вычита-
ются соответствующие элементы матрицы B)
>> A.'
ans =
1-2
3
4
Транспонирование матрицы.
Результатом является матрица, транспониро-
ванная к матрице A
Однако арифметические операторы далеко не единственные операторы, ис-
пользуемые при вычислениях.
Самоучитель Matlab
26
Логические операторы и операторы
сравнения
Я всегда завидовал Вашему умению выстра-
ивать точную логическую направленность.
К/ф "Семнадцать мгновений весны"
Важную группу операторов составляют логические операторы и операторы
сравнения. Операндами в этом случае могут быть как скаляры, так и ма-
трицы. Прежде, чем приступить к рассмотрению этих операторов, отметим
некоторые особенности работы с логическими значениями.
Обычно под логическими значениями подразумевают тип данных, пере-
менные которого могут принимать два значения – истина и ложь (true
и false соответственно). В Matlab любое числовое значение, отличное от
нуля, интерпретируется как истина (или true), а ненулевые значения ин-
терпретируются как ложь (или false). Фактически, это есть правило пере-
вода числовых значений в логические значения. Обратное преобразование
выполняется по следующему правилу: логическое значение истина (или
true) преобразуется в числовое значение 1, а логическое значение ложь
(или false) преобразуется в числовое значение 0.
На заметку
Если некоторой переменной присвоить в качестве значения true или false,
отображаемым будет соответственно значение 1 или 0.
Операндами для операторов сравнения выступают числовые значения. Это
бинарные операторы. Если оба операнда – скаляры, сравнение выполня-
ется по правилам сравнения чисел. При истинном соотношении возвра-
щается значение 1, при ложном – значение 0. Если операндами являются
матрицы одинаковых рангов, сравниваются соответствующие элементы ма-
триц (по правилам сравнения числовых значений). Результатом является
"логическая матрица": ее элементы равны 1 или 0 в зависимости от резуль-
тата сравнения соответствующих элементов исходных матриц. Если одним
операндом является скаляр, а другим – матрица, то выполняется сравнение
каждого элемента матрицы со скаляром. Операторы сравнения перечисле-
ны в табл. 1.3.
Табл. 1.3. Операторы сравнения Matlab
Оператор
Описание
==
Оператор проверки на предмет равенства
~=
Оператор проверки значений операндов на предмет неравенства
Глава 1. Принципы работы Matlab и основы вычислений
27
Оператор
Описание
>
Оператор проверки того, что значение первого операнда больше значе-
ния второго операнда
<
Оператор проверки того, что значение первого операнда меньше значе-
ния второго операнда
>=
Оператор проверки того, что значение первого операнда не меньше
значения второго операнда
<=
Оператор проверки того, что значение первого операнда не больше
значения второго операнда
Как и в случае операторов сравнения, операндами логических операторов
могут выступать как скаляры, так и матрица (одновременно оба или только
один). Если операндами являются скаляры, соответствующие логические
операции выполняются по описанным выше правилам преобразования чис-
ловых и логических значений. Если оба операнда – матрицы одинаковых
размеров, логические операции выполняются поэлементно. При условии,
что один операнд – матрица, а второй – скаляр, логическая операция вы-
полняется для каждого элемента матрицы и скаляра. Логические операто-
ры Matlab представлены в табл. 1.4.
Табл. 1.4. Логические операторы Matlab
Оператор
Описание
&
Логическая операция и. Результатом является истина (значение 1),
если оба операнда истинны. В противном случае возвращается 0
|
Логическая операция или. Результатом является истина (значение 1),
если хотя бы один операнд истинен. В противном случае возвращается 0
~
Логическая операция отрицания. Для истинного операнда возвраща-
ется значение 0, а для ложного – значение 1
Еще раз отметим, что как в операциях сравнения, так и в логических опера-
циях для элементов матриц или скаляров (в зависимости от типа операн-
дов) возвращаются значения 0 (ложь) и 1 (истина).
Комплексные числа
Жизнь сложена из банальных обстоя-
тельств, и потому скучна.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В Matlab можно использовать не только действительные, но и комплексные
числа. Ввод комплексных чисел в рабочей области выполняется в соответ-
Самоучитель Matlab
28
ствии с правилами представления комплексных чисел. В качестве мнимой
единицы можно использовать, на выбор, переменные i или j, без какого бы
то ни было предварительного объявления. Однако если переменной i или
j присвоить числовое значение, соответствующую переменную в качестве
мнимой единицы задействовать не получится.
На заметку
Если быть более точным, то в случае, когда, например, переменной i при-
своено числовое значение, использовать эту переменную как мнимую едини-
цу нужно "правильно". Например, командой i=3 создаем "проблему" в виде
числового значения переменной i. Если после этого выполнить команду a=i,
переменная a получит значение 3. Но если воспользоваться командой a=1i,
то результат будет иным – значение переменной a будет комплексным и равно
мнимой единице.
Ниже приведены примеры использования комплексных значений (жир-
ным шрифтом выделен ввод пользователя):
>> z=1+2i
z=
1.0000 + 2.0000i
>> z+j
ans =
1.0000 + 3.0000i
>> (2-4i)*(1+z)
ans =
12.0000
-
4.0000i
>> i*z
ans =
- 2.0000 + 1.0000i
При вводе комплексного значения между мнимой частью и мнимой едини-
цей оператор умножения можно не ставить. По умолчанию для отображе-
ния мнимой единицы используется символ i (хотя может вводиться как j).
Существует ряд функций, облегчающих работу с комплексными числами.
Среди них имеет смысл выделить функции real() и imag() для вычисле-
ния действительной и мнимой частей комплексного числа соответственно,
функцию conj() для вычисления комплексно сопряженного числа, а так-
же функцию complex(), принимающую два аргумента (действительная
и мнимая части), на основании которых создается комплексное число. При-
меры использования этих функций приведены далее:
>> complex(3,-2)
ans =
3.0000
-
2.0000i
Глава 1. Принципы работы Matlab и основы вычислений
29
>> conj(ans)
ans =
3.0000 + 2.0000i
>> real(ans)
ans =
3
>> imag(2-4i)
ans =
-4
Как и в предыдущих случаях, жирным шрифтом выделены команды, вводи-
мые пользователем.
На заметку
Обращаем внимание, что системную переменную ans можно использовать
в вычислениях, что и было сделано выше.
Разумеется, комплексными могут быть не только скалярные величины, но
и матрицы.
Оператор создания интервала значений
Здесь явно не хватает двух точек.
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Кровавая надпись"
Достаточно популярным и часто используемым в Matlab является оператор
"двоеточие", то есть :. Существует несколько вариантов его использования.
Рассмотрим самые общие.
Для создания вектора-строки со значениями, равнораспределенными в не-
котором интервале, оператор используют в следующем формате: нижняя
граница диапазона, оператор (то есть :) и верхняя граница диапазона –
например, x=a:b. При этом создается вектор-строка (для приведенной
команды вектор записывается в переменную x). Первый элемент вектора
равен нижней границе указанного диапазона (значение a). Шаг дискрет-
ности изменения значений элементов вектора равен единице. Значение
последнего элемента определяется верхней границей указанного диапазо-
на (в данном случае b). Так, командой x=1:10 создается вектор-строка со
значениями 1, 2, 3 и т.д. до 10 включительно (жирным шрифтом выделен
ввод пользователя):
>> x=1:10
x=
1
2
3
4
5
6
7
8
9
10
Самоучитель Matlab
30
Если нужно создать вектор-строку с последовательностью значений и ша-
гом дискретности, отличным от единицы, используют тот же оператор "дво-
еточие" (то есть :), но в несколько ином формате: указывается нижняя гра-
ница диапазона значений, оператор "двоеточие", шаг дискретности, снова
оператор "двоеточие", и верхняя граница диапазона – например, y=a:m:b.
Формируется вектор-строка с первым значением – нижней границей диа-
пазона (для приведенной команды это a). Каждый следующий элемент по-
лучается прибавлением к предыдущему величины, указанной в качестве
шага дискретности (в данном случае m). Значения элементов сформирован-
ного массива не превышают верхнюю границу диапазона (то есть b). При-
мер такого использования оператора "двоеточие" приведен ниже (отрывок
кода из рабочей области, жирным выделен ввод пользователя):
>> y=1:0.7:10
y=
Columns 1 through 8
1.0000 1.7000 2.4000 3.1000 3.8000 4.5000 5.2000 5.9000
Columns 9 through 13
6.6000 7.3000 8.0000 8.7000 9.4000
В данном случае создается вектор-строка y со значениями от 1 до 10 с ша-
гом дискретности 0.7 – значения 1.0, 1.7, 2.4 и т.д. до 9.4 включительно
(следующее гипотетическое значение в последовательности 10.1 превы-
шает верхнюю границу диапазона 10, поэтому в формируемый вектор оно
не входит).
На заметку
Сообщения Columns 1 through 8 и Columns 9 through 13 появ-
ляются автоматически как следствие того, что результат выполнения команды
y=1:0.7:10 в одну строку не помещается, поэтому выполняется перенос ча-
сти вектора-результата в следующую строку. Данные сообщения призваны об-
легчить процесс индексной идентификации элементов.
Второй способ использования оператора "двоеточие" – при индексирова-
нии элементов. Как и в предыдущем случае, существует несколько форма-
тов, или правил, использования оператора "двоеточие" в индексах.
Например, если оператор "двоеточие" используется в формате A(i:j,k),
то в качестве результата возвращается вектор-столбец, который формиру-
ется из элементов матрицы A, находящихся в k-м столбце с i-й по j-ю стро-
ку включительно. Ссылка в формате A(:,k) возвращает в качестве значе-
ния весь k-й столбец матрицы A.
Можно использовать оператор "двоеточие" при указании сразу двух ин-
дексов. Например, командой A(i:j,m:n) возвращается подматрица,
Глава 1. Принципы работы Matlab и основы вычислений
31
состоящая их строк с i-й по j-ю и одновременно столбцов с m-го по n-й.
Рассмотрим некоторые примеры использования оператора "двоеточие".
В частности, исходная матрица A вводится командой
A=[1234;5678;9101112;13141516]
A=
1
2
3
4
5
6
7
8
9101112
13141516
Как и ранее, здесь и далее жирным шрифтом выделен ввод пользователя.
В следующих командах оператор "двоеточие" используется для извлечения
подматриц из исходной матрицы A:
>> A(1:3,2)
ans =
2
6
10
>> A(3,2:4)
ans =
101112
>> A(3:4,1:2)
ans =
910
13 14
Например, командой A(1:3,2) возвращается вектор-столбец, составлен-
ный из элементов с первой по третью строку во втором столбце матрицы
A. Командой A(3,2:4) возвращается вектор-строка, который составлен из
элементов третьей строки со второго по четвертый столбец включительно
матрицы A. Наконец, командой A(3:4,1:2) возвращается подматрица ма-
трицы A, верхний левый элемент которой имеет индексы (3,1), а правый
нижний элемент имеет индексы (4,2).
Встроенные математические функции
Ну зачем такие сложности?
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Собака Баскервилей"
В Matlab по умолчанию доступно достаточно большое количество встро-
енных функций. Ядро их составляют математические функции, которые на
практике используются сравнительно часто. Некоторые из них перечисле-
ны в табл. 1.5.
Самоучитель Matlab
32
Табл. 1.5. Некоторые математические функции Matlab
Функция
Описание
abs()
Модуль числа (в том числе и комплексного), указанного аргумен-
том функции
acos()
Арккосинус для числа, указанного аргументом функции
acosd()
Арккосинус аргумента функции. Результат представлен в граду-
сах
acot()
Арккотангенс числа, указанного аргументом функции
acotd()
Арккотангенс аргумента функции. Результат представлен в гра-
дусах
acsc()
Арккосеканс числа, указанного аргументом функции
acscd()
Арккосеканс аргумента функции. Результат представлен в гра-
дусах
asec()
Арксеканс числа, указанного аргументом функции
asecd()
Арксеканс аргумента функции. Результат представлен в градусах
asech()
Арксеканс гиперболический от числа, указанного аргументом
функции
asin()
Арксинус от числа, указанного аргументом функции
asind()
Арксинус аргумента функции. Результат представлен в градусах
asinh()
Арксинус гиперболический от числа, указанного аргументом
функции
atan()
Арктангенс от числа, переданного аргументом функции
atan2()
У функции два аргумента (например, atan(y,x)). В качестве
результата возвращается направление (угол в диапазоне зна-
чений от -π до π) на точку с соответствующими координатами
(в данном случае, точка с координатами (y,x)). Если аргументы
комплексные, их мнимые части игнорируются
atand()
Арктангенс аргумента функции. Результат представлен в градусах
atanh()
Арктангенс гиперболический от числа, переданного аргументом
функции
ceil()
Функция округления аргумента в направлении плюс бесконеч-
ности – округление выполняется до целого значения, которое не
меньше, чем аргумент
cos()
Косинус от числа, переданного аргументом функции
cosd()
Косинус аргумента функции, указанного в градусах
cosh()
Косинус гиперболический от числа, переданного аргументом
функции
cot()
Котангенс от числа, переданного аргументом функции
cotd()
Котангенс аргумента функции, указанного в градусах
coth()
Котангенс гиперболический от числа, переданного аргументом
функции
csc()
Косеканс от числа, переданного аргументом функции
Глава 1. Принципы работы Matlab и основы вычислений
33
Функция
Описание
cscd()
Косеканс аргумента функции, указанного в градусах
csch()
Косеканс гиперболический от числа, переданного аргументом
функции
exp()
Экспонента: показательная функция с основанием-константой Эй-
лера и показателем степени, определяемым аргументом функции
expm1()
Командой вида expm1(x) с повышенной точностью вычисляет-
ся значение exp(x)-1
factor() Функцией возвращается вектор-строка с простыми множителями
числа (с учетом их кратности), указанного аргументом функции
factorial() Функция для вычисления факториала числа, указанного аргумен-
том функции
fix()
Функция округления в направлении нуля. Результатом является
число, получающееся округлением аргумента функции до бли-
жайшего целого значения в направлении нуля
floor()
Функция округления аргумента до ближайшего целого значения,
которое не превышает аргумент, – округление в направлении ми-
нус бесконечности
gcd()
Функцией возвращается наибольший общий делитель целых чи-
сел или целочисленных массивов – аргументов функции
hypot()
Корень квадратный из суммы квадратов модулей аргументов,
переданных функции
idivide()
У функции два аргумента. Результатом является целая часть от
деления первого аргумента на второй. Можно также указать оп-
цию – в одинарных скобках имя функции, с помощью которой вы-
полняется округление
lcm()
Функцией в качестве результата возвращается наименьшее об-
щее кратное для целых чисел или целочисленных массивов – ар-
гументов функции
log()
Натуральный логарифм от числа, указанного аргументом функции
log10()
Логарифм по основанию 10 от числа, указанного аргументом
функции
log1p()
Командой вида log1p(x) с повышенной точностью вычисляет-
ся значение log(1+x)
log2()
Логарифм по основанию 2 от числа, указанного аргументом
функции
mod()
Функцией возвращается остаток от деления значения первого ар-
гумента функции на значение второго аргумента. Целая часть от
деления определяется функцией froor()
nchoosek()
Функцией в качестве значения возвращаются биномиальные коэф-
фициенты. Если функция вызвана в формате nchoosek(n,k),
то в качестве результата возвращается значение
!
!(
)!
k
n
n
C
knk
=
−
Самоучитель Matlab
34
Функция
Описание
nextpow2()
Функцией в качестве значения возвращается ближайшее целое
число – степень двойки, которое не меньше модуля аргумента
функции
nthroot()
Командой nthroot(x,n) в качестве значения возвращается
корень порядка n (второй аргумент) из действительного числа
или элементов действительного массива x (первый аргумент )
pow2()
Функция может вызываться с одним или двумя аргументами. Если
у функции один аргумент (массив) и функция вызывается в фор-
мате pow2(x), то в качестве результата возвращается массив
степеней двойки, показатели степени определяются массивом
x. Если функция вызывается с двумя аргументами в формате
pow2(x,y), то результатом является x.*2.^y
power()
У функции два аргумента. Если аргументы скалярные, в каче-
стве результата возвращается значение первого аргумента, воз-
веденное в степень, определяемую вторым аргументом. В бо-
лее общем случае в качестве результата выполнения команды
power(A,B) возвращается 'A.^B'
primes() Функцией генерируется список простых чисел. Количество чисел
указывается аргументом функции
rem()
Функцией возвращается остаток от деления значения первого ар-
гумента функции на значение второго аргумента. Целая часть от
деления определяется функцией fix()
round()
Функция округления аргумента до ближайшего целого значения
sec()
Секанс от числа, указанного аргументом функции
secd()
Секанс аргумента функции, указанного в градусах
sign()
Знак числа, указанного аргументом функции (для положительных
чисел – единица, для отрицательных чисел – минус единица, для
нуля - ноль)
sin()
Синус от числа, указанного аргументом функции
sind()
Синус аргумента функции, указанного в градусах
sqrt()
Корень квадратный из числа, указанного аргументом функции
tan()
Тангенс от числа, указанного аргументом функции
tand()
Тангенс аргумента функции, указанного в градусах
Хотя большинство из представленных выше функций с математической
точки зрения определены для скалярных величин, обычно они могут при-
меняться и для аргументов-матриц. В этом случае действие функциональ-
ного оператора применяется к каждому из элементов матрицы. Например,
если переменная A является матрицей с элементами A(i,j), то в результате
выполнения команды exp(A) получим матрицу того же ранга, а ее элемен-
ты вычисляются как exp(A(i,j)). В некоторых случаях такой подход не-
приемлем. Существуют так называемые матричные функции, аргументами
которых по определению являются матрицы (в основном квадратные). Ре-
зультат этих функций вычисляется по алгоритмам, разработанным специ-
Глава 1. Принципы работы Matlab и основы вычислений
35
ально для матриц. Так, в Matlab есть встроенные матричные функции для
экспоненты, логарифма и квадратного корня. Это соответственно функции
expm(), logm() и sqrtm(). Например, если A – квадратная матрица, то
функцией expm(A) вычисляется матричная экспонента. По определению
это ряд
0
exp( )
!
n
n
A
A
n
∞
=
=
∑ . Результатом является матрица, которая вычис-
ляется, как правило, на основе собственных чисел и собственных векторов
матрицы A. Матричный логарифм для аргумента-матрицы A, вычисляемый
инструкцией logm(A), представляет собой матрицу такую, что матричная
экспонента от нее равна матрице A. Другими словами, по определению если
B=logm(A), то expm(B)=A, и функция logm() является обратной к функ-
ции expm(). Аналогично, в результате извлечения квадратного корня из
матрицы A с помощью функции sqrtm() получаем матрицу, которая, бу-
дучи возведенной в квадрат, дает матрицу A. Например, если B=sqrtm(A),
то B*B=A.
В Matlab также широко представлены специальные функции, некоторые
их них приведены в табл. 1.6.
Табл. 1.6. Некоторые специальные математические функции Matlab
Функция
Описание
airy()
Функция Эйри. Командой airy(x) в качестве результата
возвращается функция ()
yx , являющаяся одним из реше-
ний уравнения
2
2
()()0
dyx
xyx
dx
−=
, а именно возвращается
функция Эйри первого рода
()
32
13
12
() 33
x
Aix
K
x
π
=
, где
()
Kz
ν
-
модифицированная функция Бесселя второго рода
индекса ν . Функция также может вызываться с двумя аргу-
ментами в формате airy(k,x). В этом случае для k=0
возвращается функция ()
Ai x , для k=1 возвращается произ-
водная
()
Aix
′
, для k=2 возвращается независимое решение
()()
()
32
32
13
13
22
()333
x
Bix
I
x
I
x
−
=+
,где()
Iz
ν
-
моди-
фицированная функция Бесселя первого рода индекса ν , для
k=3 возвращается производная
()
Bix
′
besselh()
Функция Бесселя третьего рода (функция Ханкеля).
При вызове функции с тремя аргументами в форма-
те besselh(n,k,x) возвращается функция Ханкеля
()
1
() ()(1) ()
kk
nn
n
Hx Jx
i
Yx
+
=+
−
, где
1,2
k=
,а
()
n
Jxи
()
n
Yx- функции Бесселя индекса n первого и второго рода со-
ответственно
Самоучитель Matlab
36
Функция
Описание
besseli()
Командой besseli(n,x)
возвращается
модифи-
цированная функция Бесселя первого рода (индекса n)
() ()2
0
2
() 2!
(1
)
k
n
n
k
x
x
Ix
knk
∞
=
=
Γ++
∑
(где ()
z
Γ - гамма-функция
Эйлера), которая является одним из решений модифицированно-
го уравнения Бесселя
22
2
() ()( )()0
xyx xyx
x nyx
′′
′
+−
+=
besselj()
Командой besselj(n,x) возвращается функция Бесселя
первого рода (индекса n)
() ()2
0
(1) 2
() 2!
(1
)
k
k
n
n
k
x
x
Jx
knk
∞
=
−
=
Γ++
∑
(где ()
z
Γ - гамма-функция Эйлера), которая является одним из
решений уравнения Бесселя
22
2
() ()( )()0
xyx xyx
x nyx
′′
′
++
−
=
besselk()
Командой besselk(n,x)
возвращается
модифи-
цированная функция Бесселя второго рода (индекса n)
() ()
() 2s
i
n
()
nn
n
Ix Ix
Kx
n
π
π
−
−
=
(где
()
n
Ix - модифицирован-
ная функция Бесселя первого рода), которая является од-
ним из решений модифицированного уравнения Бесселя
22
2
() ()( )()0
xyx xyx
x nyx
′′
′
+−
+=
.
Для целых индексов
соответствующее выражение рассчитывается как лимит
bessely()
Командой besselj(n,x) возвращается функция Бесселя
второго рода (индекса n)
()cos( ) ()
()
sin( )
nn
n
Jx nJx
Yx
n
π
π
−
−
=
(где
()
n
Jx - функция Бесселя первого рода), кото-
рая является одним из решений уравнения Бесселя
22
2
() ()( )()0
xyx xyx
x nyx
′′
′
++
−
=
.
Для целых индексов
соответствующее выражение рассчитывается как лимит
beta()
Бета-функция Эйлера. Командой beta(x,y) возвращается
значение функции
1
11
0
()()
(,)
(1)
()
xy xy
Bxy
t
tdt
xy
−−
ΓΓ
=−
=
Γ+
∫
,
где ()
x
Γ - гамма-функция Эйлера
betainc()
Неполная бета-функция Эйлера. Командой betainc(z,x,y)
возвращается значение
11
0
1
(,)
(1)
(,)
z
xy
z
Ixy
t
tdt
Bxy
−−
=−
∫
,
где (,)
Bxy - бета-функция Эйлера
betaln()
Логарифм натуральный от бета-функции Эйлера. Аргументами
передаются аргументы бета-функции
Глава 1. Принципы работы Matlab и основы вычислений
37
Функция
Описание
ellipj()
Эллиптическая функция Якоби. Если функция вызывается с дву-
мя аргументами в формате ellipj(u,m), в качестве резуль-
тата возвращаются значения (вектор) для функций ()
snu, ()
cnu
и
()
dn u , которые вычисляются на основе эллиптического инте-
грала
2
01s
i
n
(
)
d
u
m
φ
θ
θ
=
−
∫
и определяются из соотношений
() sin( )
snu
φ
=
,
() cos()
cnu
φ
=
и
2
() 1 sin()
dnu
m
φ
=−
ellipke()
Функция для вычисления полного эллиптического интеграла пер-
вого и второго рода (вектор значений). Эллиптический интеграл
первого рода вычисляется как
2
2
0
()
1s
i
n
(
)
d
Km
m
π
θ
θ
=
−
∫
.
Эллиптический интеграл второго рода вычисляется как
2
2
0
()1si
n()
Em
m
d
π
θθ
=−
∫
erf()
Функция ошибок. Командой erf(x) возвращается значение
2
0
2
()
exp( )
x
erf x
tdt
π
=−
∫
erfc()
Функция ошибок (остаточная). Командой erfc(x) возвраща-
ется значение
2
2
()
exp()1()
x
erfc x
tdt
erf x
π
+∞
=−
=
−
∫
erfcx()
Функция ошибок (остаточная нормированная). Командой
erfcx(x) возвращается значение
2
()exp() ()
erfcx x
x erfcx
=
erfinv()
Обратная функция к функции ошибок erf(). Если y=erf(x),
то erfinv(y)=x
erfcinv()
Обратная функция к функции ошибок erfc(). Если
y=erfc(x), то erfcinv(y)=x
expint()
Интегральная экспонента. Командой expint(x) возвращает-
ся значение 1
exp( )
()
x
t
Ex
dt
t
+∞
−
=
∫
gamma()
Гамма-функция Эйлера. Командой gamma(x) возвращается
значение
1
0
()
exp( )
x
xtt
d
t
∞
−
Γ=
−
∫
gammainc()
Неполная гамма-функция. Командой gammainc(z,x) воз-
вращается значение
1
0
1
(,)
exp( )
()
z
x
Pzx
t
tdt
x
−
=−
Γ∫
,
()x
Γ-
гамма-функция
Самоучитель Matlab
38
Функция
Описание
gammaln() Логарифм натуральный от гамма-функции Эйлера. Аргументом
функции передается аргумент гамма-функции
legendre()
Функция для вычисления присоединенных полиномов Лежан-
дра. Присоединенные полиномы Лежандра определяются как
2
2
() (1)(1 )
()
m
m
mm
nn
m
d
Px
x
Px
dx
=−
−
(присоединенный поли-
ном Лежандра степени n порядка m ), где полиномы Лежандра
степени n определяются как
2
1
()
(1)
2!
n
n
n
nn
d
Px
x
nd
x
⎛⎞
⎟
⎜
=−
⎟
⎜
⎟
⎝⎠
.
В результате вызова функции в формате legendre(n,x)
возвращается вектор-столбец значений присоединенных поли-
номов Лежандра ()
m
n
Pxдля
0,1, 2, ...,
mn
=
psi()
Пси-полигамная функция. Если функция вызывается с одним
аргументом в формате psi(x), в качестве результата воз-
вращается логарифмическая производная от гамма-функции
()
() ()
x
x
x
ψ
′
Γ
=
Γ
(пси-функция). Если функция вызывается с дву-
мя аргументами в формате psi(k,x), в качестве результата
возвращается k-я производная от пси-функции, то есть
()()
kx
ψ
Как и в случае с базовыми математическими функциями, для большинства
специальных функций аргументами могут указываться матрицы. В этом
случае функция вычисляется для каждого из элементов матрицы.
На заметку
Описанные в этом разделе функции составляют малую толику всех встроен-
ных функций Matlab. Многие из них рассматриваются далее в книге в контексте
освещаемых вопросов.
Формат вывода числовых данных
Если сразу не разберешь,
Плох он или хорош...
В. Высоцкий, "Песня о друге"
В некоторых случаях приходится изменять способ, которым данные с ре-
зультатом выполнения команд пользователя выводятся на экран. В пер-
вую очередь отметим, что можно вообще не отображать результат выпол-
нения команды в командном окне. Для этого достаточно соответствующую
команду закончить точкой с запятой (то есть ;). В этом случае после на-
жатия клавиши <Enter> команда выполняется, но результат ее выполне-
ния в командном окне не отображается. Такой режим особенно удобен в тех
случаях, когда нужно выполнять громоздкие промежуточные расчеты, ко-
Глава 1. Принципы работы Matlab и основы вычислений
39
торые, с одной стороны, необходимы для получения конечного результата,
а с другой – загромождают рабочее пространство. Поэтому разумный выход
из такой ситуации – скрыть результат выполнения команды.
Числовой формат вывода в явном виде задается с помощью инструкции
format. В команде определения формата вывода после ключевого слова
format указывается применяемый формат. Допустимые форматы, с крат-
ким их описанием, перечислены в табл. 1.7.
Табл. 1.7. Числовые форматы (для инструкции format)
Формат
Описание
short
Формат отображения числовых данных, при котором после де-
сятичной точки отображается четыре цифры (формат данных
с фиксированной точкой). Формат используется по умолчанию
long
Числовой формат, при котором после десятичной точки отобра-
жается 7, 14 и 15 цифр в зависимости от типа числовых данных
(формат данных с фиксированной точкой)
short e
Формат отображения числовых данных с мантиссой и показате-
лем степени (формат данных с плавающей точкой), при котором
после десятичной точки отображается четыре цифры
long e
Числовой формат отображения с мантиссой и показателем сте-
пени (формат данных с плавающей точкой), при котором после
десятичной точки отображается 7, 14 и 15 цифр в зависимости
от типа числовых данных
short g
В зависимости от значения, для отображения применяется либо
формат с плавающей точкой, либо с фиксированной точкой. По-
сле десятичной запятой отображается четыре цифры
long g
В зависимости от значения, для отображения применяется либо
формат с плавающей точкой, либо с фиксированной точкой. По-
сле десятичной запятой отображается 7, 14 или 15 цифр
short eng
Инженерный формат с четырьмя отображаемыми цифрами по-
сле десятичной точки и показателем степени, кратным трем
long eng
Инженерный формат с 7, 14 или 15 отображаемыми цифрами
после десятичной точки и показателем степени, кратным трем
+
Формат, при котором для положительных чисел отображается
знак +, для отрицательных отображается знак -, а для нуля ото-
бражается пробел
bank
Финансовый формат, при котором после десятичной точки ото-
бражается две цифры
hex
Отображение чисел в шестнадцатеричной системе счисления
rat
Отображение чисел в виде рациональной дроби
compact
Режим отображения результатов вычислений в компактной фор-
ме, с уменьшенными интервалами между строками
loose
Режим отображения результатов вычислений с увеличенными
интервалами между строками. Используется по умолчанию
Самоучитель Matlab
40
Ниже приведен пример отображения числа π в разных форматах (в коман-
дах использована встроенная константа Matlab pi, ввод пользователя вы-
делен жирным шрифтом):
>> format short e
>> pi
ans =
3.1416e+000
>> format long
>> pi
ans =
3.141592653589793
>> format long e
>> pi
ans =
3.141592653589793e+000
>> format long eng
>> pi
ans =
3.14159265358979e+000
>> format bank
>> pi
ans =
3.14
>> format rat
>> pi
ans =
355/113
>> format +
>> pi
ans =
+
Эти же команды, выполненные
в командном окне, представлены
на рис. 1.9 и рис. 1.10.
Рис. 1.9. Применение различных форматов
вывода (начальная часть командного окна)
Глава 1. Принципы работы Matlab и основы вычислений
41
Рис. 1.10. Применение различных форматов вывода (конечная часть командного окна)
Заметим, что настройки формата вывода влияют только на способ отобра-
жения числовых значений, но никак не точность их представления. Поэто-
му главным критерием при выборе способа вывода данных может быть во-
прос удобства.
На заметку
Есть одна функция, которая хотя напрямую и не относится к определению фор-
мата вывода числовых данных, ее использование значительно облегчает про-
цесс взаимодействия пользователя с системой. Это функция clc, которая
позволяет очистить рабочее пространство от команд ввода и результатов их
выполнения.
42
Глава 2
Графика в Matlab
Когда настоящие знатоки выносят свое
мнение об искусстве, я скромно молчу...
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Бесспорным является тот факт, что визуализация расчетных данных не
менее важна, чем сам процесс вычислений и анализа. Поэтому функцио-
нальность практически любого приложения, в том числе и математического
пакета, во многом определяется именно возможностями по созданию гра-
фики. Как будет показано далее, в Matlab пользователю предоставляется
широкий простор для деятельности в плане создания всевозможных графи-
ческих иллюстраций, включая анимацию.
Создание графика функции
Так где мы можем обсудить аспекты, так
сказать, нашего общего дела?
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Одной из самых простых задач в области построения графиков является
задача по созданию графика функции одной переменной. Основное прави-
ло состоит в том, что необходимо предварительно задать массив значений
аргумента (узловые точки) функции и значений функции в узловых точках.
Делаться это может по-разному. Рассмотрим наиболее общие случаи.
Для создания графика функции одной переменной используют функцию
plot(). Первым аргументом функции указывается массив узловых точек,
а второй аргумент функции – значения отображаемой на графике функции
в этих узловых точках. На рис. 2.1 показан построенный в Matlab всего с по-
мощью нескольких команд график для функции Бесселя 0()
Jx.
Для создания графика использовались следующие команды:
>> x=0:0.005:40;
>> y=besselj(0,x);
>> plot(x,y)
Первой командой x=0:0.005:40 создается вектор-строка x с число-
выми значениями от 0 до 40 и интервалом изменения 0.005 (вектор
узловых точек). Это достаточно большой массив значений. Чтобы он не
отображался на экране при выполнении команды создания вектора x, со-
Глава 2. Графика в Matlab
43
ответствующая команда заканчивается точкой с запятой. Далее, командой
y=besselj(0,x) создается вектор-строка y со значениями функции Бес-
селя в узловых точках. Для вычисления значений использована встроен-
ная функция Matlab besselj(), первым аргументом указывается индекс
функции Бесселя, а второй – массив узловых точек. Как отмечалось в пер-
вой главе, для большинства встроенных функций Matlab действует пра-
вило, согласно которому если вместо ожидаемого скалярного аргумента
функции указан вектор, в качестве результата возвращается вектор того
же размера со значениями функции в соответствующих точках. Здесь это
правило было использовано на практике. Наличие точки с запятой в конце
команды вызвано теми же причинами, что и в предыдущем случае.
Наконец, непосредственно график функции строится с помощью команды
plot(x,y). В результате выполнения команды автоматически создает-
ся графическое окно с полем, на котором отображен график функции. По
умолчанию окно имеет название Figure 1 и кроме непосредственно графи-
ка содержит ряд меню и пиктограмм для работы с созданным графическим
объектом (см. рис. 2.1).
Применяемое по умолчанию при создании графика форматирование не
всегда является оптимальным, поэтому обычно приходится прибегать
к дополнительным настройкам. Часть из них может быть выполнена
Рис. 2 .1. График функции Бесселя, построенный в Matlab
Самоучитель Matlab
44
ко мандами в рабочем документе, а часть выполняется непосредственно
в графическом окне. Назначения большинства меню, команд меню и кно-
пок на панели инструментов достаточно очевидны, и читатель сможет лег-
ко разобраться в этом самостоятельно. Остановимся только на некоторых
аспектах работы с настройками графического окна. В частности, командой
Axes Properties из меню Edit графического окна (рис. 2.2) в графическом
окне открывается специальная панель для настройки внешнего вида ко-
ординатных осей.
Рис. 2 .2 . Выбор команды Axes Properties из меню Edit графического окна для настройки
вида координатных осей графика
Графическое окно с открытой панелью настройки координатных осей по-
казано на рис. 2.3. При этом ряд настроек уже выполнен.
В частности, в текстовом поле Title указано название для графика:
Bessel Function. Это название отображается в верхней части графиче-
ского окна над областью отображения графика. Установлены флажки оп-
ций X и Y раздела Grid. Благодаря этому на графике отображается коорди-
натная сетка. При необходимости параметры сетки задаются в отдельном
окне настройки, которое открывается после нажатия кнопки Ticks. В тек-
стовых полях X Label на вкладке X Axis и Y Label на вкладке Y Axis указаны
подписи для координатных осей - x и y соответственно. На вкладке Font
выбран шрифт Arial жирный. Больше опций и параметров настройки до-
ступно после нажатия кнопки More Properties.
Глава 2. Графика в Matlab
45
После выполнения настроек координатных осей панель настройки закрыва-
ем (достаточно щелкнуть пиктограмму закрытия панели), а вместо нее от-
крываем панель настройки графических объектов Current Object Properties
(также находится в меню Edit – см. рис. 2.3). Если при этом в области гра-
фика выделить кривую отображенной функциональной зависимости, гра-
фическое окно примет вид, как на рис. 2.4.
В раскрывающемся списке Plot Type выбирают тип графика (кроме кри-
вой, можно, например, использовать стиль диаграммных столбиков,
режим заливки области между графиком и координатной осью и ряд
других). Тип линии, ее толщина и цвет выбираются в раскрывающихся
списках группы Line. Тип маркера (базовый символ, которым на графике
выделяются узловые точки, на основании которых строится кривая), раз-
Рис. 2.3. Графическое окно с панелью для настройки внешнего вида координатных осей
графика и рядом выполненных настроек
Самоучитель Matlab
46
Рис. 2 .4 . Графическое окно с разделом настройки вида кривой на графике
Рис. 2 .5 . Результат внесения изменений относительно вида координатных осей и самого
графика функции
Глава 2. Графика в Matlab
47
мер и цветовые параметры задаются с помощью раскрывающихся списков
группы Marker.
В раскрывающихся редактируемых полях X Data Source и Y Data Source
можно изменить ссылки на данные, на основе которых строится график.
В этих полях указываются имена переменных рабочего пространства, содер-
жащих числовые данные для отображения на графике: в поле X Data Source
указывается вектор значений узловых точек аргумента функции (в данном
случае это переменная x), а в поле Y Data Source указывается вектор зна-
чений в узловых точках отображаемой на графике функции. Некоторые из
выполняемых настроек вступают в силу сразу, а некоторые – после нажатия
кнопки Refresh Data. На рис. 2.5 показано графическое окно с графиком
функции Бесселя после ряда выполненных настроек.
В частности, выбран режим заливки области между графиком функции и го-
ризонтальной координатной осью, изменен цвет закраски (красный), тип ли-
нии установлен штрихованный. Важно также понимать, что одни и те же на-
стройки выполнять разными способами. Например, открыть окно настройки
координатных осей можно, выделив координатную рамку и выбрав команду
(установив флажок опции) Property Editor в меню View. То же можно делать,
выделив кривую на графике. Полезным в этом случае может оказаться и кон-
текстное меню, открывающееся при щелчке правой кнопкой мыши.
Отображение нескольких кривых на одном
графике
Да, как эксперимент это интересно.
Но какое практическое применение?
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
По умолчанию при вызове функции plot() (с разными аргументами) каж-
дый раз создается новый график, причем создается в исходном графическом
окне. Нередко нужно, чтобы несколько графиков отображались одновре-
менно. В этом случае, если графики строятся с помощью функции plot(),
между вызовами соответствующих команд необходимо выполнить команду
hold on. В результате создаваемое после этого графическое изображение
будет пересылаться в уже существующее графическое окно без удаления
существующего графика, что позволяет добиться желаемого эффекта: на
одном графике отображается сразу несколько кривых. Пример создания
в одном графическом окне двух кривых для разных функциональных за-
висимостей приведен на рис. 2.6.
Самоучитель Matlab
48
Рис. 2 .6. Две кривые на одном графике
Для создания на одном графике кривых для двух функциональных зависи-
мостей использовалась следующая последовательность команд:
>> x1=-4*pi:0.01:4*pi;
>> y1=5*sin(x1)./x1;
>> t=0:0.01:2*pi;
>> x2=4*cos(t);
>> y2=3*sin(t);
>> plot(x1,y1)
>> hold on
>> plot(x2,y2)
В данном случае строятся графики для функций () 5sin()
yx
xx
=
и функ-
ции, заданной в параметрическом виде () 4cos()
xt
t
=
и () 3sin()
yt
t
=
при
значениях параметра 02
t
π
≤≤ - это эллипс.
На заметку
В последнем несложно убедиться, если заметить, что для любого значения
02
t
π
≤≤ имеет место соотношение
22
1
43
xy
⎛⎞ ⎛⎞
⎟⎟
⎜⎜
+=
⎟⎟
⎜⎜
⎟⎟
⎟⎟
⎜⎜
⎝⎠ ⎝⎠
. Это уравнение эллипса.
Кривая для первой функции строится на основе векторов x1 и y1, а кри-
вая для второй функции – на основе векторов x2 и y2.
Глава 2. Графика в Matlab
49
Вектор x1 создается командой x1=-4*pi:0.01:4*pi. Значениями эле-
ментов вектора являются узловые точки на интервале от 4π
−
до4πсша-
гом 0.01. Значения функции () 5sin()
yx
xx
=
в этих точках записываются
элементами вектора y1. Вектор определяется командой y1=5*sin(x1)./
x1. Обращаем внимание на использование оператора ./ для выполнения
поэлементного деления одного массива на другой. Так, результатом выра-
жения 5*sin(x1) является массив (вектор) того же размера, что и x1. Эле-
менты массива рассчитываются умножением на 5 синуса от соответствую-
щего элемента массива x1. Чтобы на основе вычисленного таким образом
массива получить значения функции () 5sin()
yx
xx
=
в узловых точках,
необходимо еще выполнить деление на соответствующие элементы масси-
ва x1. Для такой операции используется оператор поэлементного деления
./ - элементы массива слева от оператора делятся на соответствующие им
элементы массива справа от оператора.
Несколько по-иному формируются векторы x2 и y2, на основании которых
строится вторая кривая. Сначала командой t=0:0.01:2*pi создается век-
тор t с узловыми значениями параметра, посредством которого в параме-
трическом виде задана кривая. Это вектор со значениями от 0 до 2π и с ша-
гом дискретности 0.01. Далее на основании значений вектора t создаются
векторы x2 и y2. В первом случае использована команда x2=4*cos(t), во
втором – команда y2=3*sin(t).
После выполнения команды plot(x1,y1) создается графическое окно
с графиком для первой функции. Затем выполняется команда hold on, по-
сле чего с помощью команды plot(x2,y2) в созданное ранее графическое
окно добавляется график для второй функции. Еще раз обращаем внимание
читателя, что если команду hold on не выполнить, второй график ото-
бразится в исходном окне с удалением уже существующего графика. Для
того чтобы выйти из режима "удержания" графиков (то есть выйти из ре-
жима добавления нового графика к уже существующему), необходимо вы-
полнить инструкцию hold off. После этого каждый новый график будет
замещать уже существующий.
На заметку
Что касается самого графика на рис. 2 .6, то несложно заметить, что эллипс вы-
тянут не так, как должно было бы быть. Причина в том, что по координатным
осям масштаб разный, поэтому картинка деформирована. Обычно это проблем
не вызывает. Но бывают случаи, когда важно, чтобы масштаб по каждой из осей
был одинаковым – например, если отображается окружность. Полезной в таких
случаях будет инструкция axis equal, которую необходимо ввести в рабочем
окне и выполнить. Более подробно команды настройки внешнего вида графиков
обсуждаются в следующем разделе.
Самоучитель Matlab
50
Формат, используемый по умолчанию при создании графиков, далеко не
самый оптимальный. Например, обе кривые по умолчанию отображаются
линией одного и того же типа и одного цвета. Тот же график, но с несколько
измененными настройками, показан на рис. 2.7.
Рис. 2 .7 . Графическое окно с двумя кривыми после внесения изменений в настройки ото-
бражения графики
Рис. 2 .8. Для выполнения настроек свойств кривой используются команды контекстного
меню
В частности, добавлены линии координатной сетки, увеличена толщина
линий для отображения кривых, а также для второй кривой изменен цвет
Глава 2. Графика в Matlab
51
(с синего на красный) и изменен тип линии (со сплошной на пунктирную).
Как уже отмечалось ранее, для внесения необходимых изменений в на-
стройки можно использовать различные пути, и в частности команды кон-
текстного меню (рис. 2.8).
Описанный способ размещения в одном графическом окне нескольких
графиков далеко не единственный. Для этих целей можно использовать
все ту же функцию plot(), но несколько иначе указать ее аргументы,
а именно последовательно указать узловые точки и значения в узловых
точках для первой и второй функций. В частности, с помощью команды
plot(x1,y1,x2,y2) создается практически такое же графическое окно
и такими же кривыми, как на рис. 2.6, но с той лишь разницей, что кривые
отображаются разным цветом. То есть в случае вызова функции plot()
в формате plot(x1,y1,x2,y2) разные кривые отображаются разным
цветом, но тип линии, как и в предыдущем случае, одинаков для обеих
кривых.
На заметку
В некоторых случаях при отображении графиков функций разумным представ-
ляется использование логарифмической шкалы по одной или обеим коорди-
натам. Для создания графика с логарифмическим масштабом координатных
осей используют функции loglog() (двойной логарифмический масштаб, то
есть логарифмический масштаб по каждой из осей), semilogx() (логариф-
мический масштаб по горизонтальной оси) и semilogy() (логарифмический
масштаб по вертикальной оси). Кроме этого, не следует пренебрегать возмож-
ностью изменять способ масштабирования уже готовых графиков в окне на-
стройки графики.
Настройки вида графика
Это мелочи. Но нет ничего важнее мелочей!
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
Хотя стандартные средства и утилиты графического окна позволяют вы-
полнять полный спектр настроек вида графики, крайне неудобно выпол-
нять настройки каждый раз после его создания. Намного удобнее делать
это непосредственно при создании графики. Для определения параметров
создаваемых графиков используют ряд команд и инструкций. Например,
цвет линии, используемой для отображения графика, можно указать с по-
мощью специальной опции – третьего необязательного аргумента функции
plot(). Значением аргумента является кодовая буква, обозначающая цвет.
Буква заключается в одинарные кавычки. В табл. 2.1 перечислены кодовые
буквы для основных цветов.
Самоучитель Matlab
52
Табл. 2.1. Кодовые буквы для обозначения цветов
Кодовая буква
Цвет
y
Кодовая буква для обозначения желтого цвета (английское назва-
ние цвета yellow)
m
Кодовая буква для обозначения малинового цвета (английское на-
звание цвета magenta)
c
Кодовая буква для обозначения цианового цвета (английское на-
звание цвета cyan)
r
Кодовая буква для обозначения красного цвета (английское на-
звание цвета red)
g
Кодовая буква для обозначения зеленого цвета (английское на-
звание цвета green)
b
Кодовая буква для обозначения синего цвета (английское назва-
ние цвета blue)
w
Кодовая буква для обозначения белого цвета (английское назва-
ние цвета white)
k
Кодовая буква для обозначения черного цвета (английское назва-
ние цвета black)
Ниже приведен пример использования опций определения цвета в командах
создания графики, а также опций, определяющих тип линий и тип маркера
(символ отображения базовых точек, на основе которых строится кривая):
>> x=0:0.01:6;
>> y=exp(-x).*cos(2*pi*x);
>> plot(x,y,'r')
>> z=x.^2.*exp(-x);
>> plot(x,y,'r',x,z,'g')
>> plot(x,y,'r:',x,z,'g--')
>> plot(x,y,'pr',x,z,'g-')
Разберем последовательно эти команды и результат их выполнения.
Командой x=0:0.01:6 создается массив узловых точек, а коман-
дой y=exp(-x).*cos(2*pi*x) в этих точках табулируется функ-
ция
( ) exp( )cos(2 )
yx
x
x
π
=−
.
График функции создается командой
plot(x,y,'r'), при этом в соответствии с использованной опцией цвет
отображения кривой на графике – красный. Результат показан на рис. 2.9.
Если создается несколько графиков в одном графическом окне, опции опре-
деления цвета задаются практически так же: для каждого графика указывает-
ся значение опции цвета. Опция цвета указывается после векторов базовых
точек для каждого из графиков. В частности, командой z=x.^2.*exp(-x)
в узловых точках табулируется функция
2
() exp( )
zx
x
x
=−
.
Для вычисле-
ния вектора квадратов аргумента в узловых точках использован оператор .^
(оператор поэлементного возведения в степень), а поэлементное произведе-
Глава 2. Графика в Matlab
53
Рис. 2 .9. График создан с явным указанием цвета линии
Рис. 2 .10. В одном графическом окне разным цветом отображаются два графика
Самоучитель Matlab
54
ние массивов реализуется с помощью оператора .* (оператор поэлементного
произведения). Далее, командой plot(x,y,'r',x,z,'g') в одном графи-
ческом окне отображаются графики двух функций, причем для отображения
первой функции использована кривая красного цвета, а для отображения
второго графика – кривая зеленого цвета. Результат представлен на рис. 2.10.
В следующих командах, помимо опций определения цвета кривых, исполь-
зованы инструкции определения типа линии и базового символа (маркера).
Для каждого из этих параметров используются свои кодовые символы. Они
указываются в строке вместе с кодовым символом цвета кривой или без него.
В табл. 2.2 перечислены кодовые символы для определения типа линии.
Табл. 2.2. Кодовые символы для определения типа линии
Кодовый символ
Тип линии
-
Сплошная линия. Используется по умолчанию, если опция опре-
деления типа линии не задана
:
Пунктирная линия
--
Штрихованная линия
-.
Штрихпунктирная линия
Вид маркера также определяется специальными кодовыми символами, ко-
торые описаны в табл. 2.3.
Табл. 2.3. Кодовые символы для определения маркера
Кодовый символ
Маркер
.
В качестве маркера используется крупная точка
o
В качестве маркера используется кружек
x
В качестве маркера используется косой крест
+
В качестве маркера используется прямой крест
*
В качестве маркера используется звездочка
s
В качестве маркера используется квадрат
d
В качестве маркера используется ромб
v
В качестве маркера используется треугольник с направленной
вниз вершиной
^
В качестве маркера используется треугольник с направленной
вверх вершиной
<
В качестве маркера используется треугольник с направленной
влево вершиной
>
В качестве маркера используется треугольник с направленной
вправо вершиной
p
В качестве маркера используется пятиконечная звезда
h
В качестве маркера используется шестиконечная звезда
Глава 2. Графика в Matlab
55
Кодовые символы, определяющие параметры кривой (тип линии, цвет, мар-
кер), указываются вместе в любой комбинации и любой последовательно-
сти. При этом если указан тип маркера и не указан тип базовой линии, базо-
вые точки отображаются маркерами, но не соединяются кривыми. Поэтому,
например, командой plot(x,y,'r:',x,z,'g--') в одном окне создают-
ся два графика. Для отображения первого используется красная пунктир-
ная кривая. Второй отображается зеленой штрихованной кривой. Результат
выполнения команды показан на рис. 2.11.
Рис. 2 .11. Графики отображаются с помощью кривых разного цвета и разного типа
В команде plot(x,y,'pr',x,z,'g-') задается не только цвет и тип
кривой, но и базовые символы (маркеры) для первого графика. В частности,
первый график отображается в виде маркеров - пятиконечных звезд крас-
ного цвета, которые между собой не соединяются линией. Второй график
отображается сплошной линией зеленого цвета без отображения маркеров.
Результат выполнения команды показан на рис. 2.12.
Поскольку базовые точки в векторе x заданы достаточно плотно, маркеры
на первом графике накладываются друг на друга, создавая иллюзию нали-
чия кривой. Однако в начальной части графика хорошо видно, что базовые
точки с маркерами кривыми не соединены.
Часть опционных параметров задаются в следующем формате: в одинарных
кавычках название опции и, через запятую, ее значение. К таким опциям мож-
Самоучитель Matlab
56
но отнести, например, LineWidth (толщина базовой линии), MarkerSize
(размер маркера), MarkerEdgeColor (цвет линии границы маркера – он
может не совпадать с цветом заливки маркера), MarkerFaceColor (цвет
заливки маркера).
Дополнительные параметры графика, такие как название, подписи к осям,
координатная сетка и легенда, также могут быть отображены с помощью
команд рабочей области. В частности, для отображения координатной сетки
используют команду grid on. Название графика определяется с помощью
функции title(), аргументом которой указывается название для графи-
ка, заключенное в одинарные кавычки. Подписи у горизонтальной и верти-
кальной координатных осей задаются соответственно с помощью функций
xlabel() и ylabel(). Аргументами функций указываются текстовые ар-
гументы (заключаются в одинарные кавычки) – подписи координатных осей.
Если в одном графическом отображается несколько графиков, полезно ото-
бражать легенду графиков. Делается это с помощью функции legend().
Ее текстовые аргументы соответствуют подписям для соответствующих
кривых (порядок передачи текстовых аргументов соответствует порядку
создания кривых), а числовой параметр определяет место расположения
легенды в графическом окне. В табл. 2.4 перечислены возможные значения
Рис. 2 .12. При отображении графиков кривых заданы опции определения цвета кривой,
типа линии и вид маркера
Глава 2. Графика в Matlab
57
целочисленного параметра функции legend() и место размещения леген-
ды для каждого из значений аргумента.
Табл. 2.4. Целочисленный аргумент функции legend()
Значение аргумента
Размещение легенды
-1
Легенда размещается в правом верхнем углу над областью
графика
0
Место для легенды выбирается автоматически так, чтобы не
перекрывать область кривых
1
Легенда размещается в правом верхнем углу области графи-
ка. Этот режим используется по умолчанию
2
Легенда размещается в левом верхнем углу области графика
3
Легенда размещается в левом нижнем углу области графика
4
Легенда размещается в правом нижнем углу области графика
Рассмотрим следующие команды в рабочей области, которыми в одном гра-
фическом окне создается три графика и в которых используются перечис-
ленные выше опции, инструкции и функции:
>> t=0:0.1:2*pi;
>> x=2*pi*cos(t);
>> y=2*pi*sin(t);
>> u=t.*cos(4*t);
>> v=t.*sin(4*t);
>> plot(x,y,'p','MarkerSize',10,'MarkerFaceColor','r','MarkerEdgeColor','g')
>> axis equal
>> grid on
>> hold on
>> plot(u,v,'b-','LineWidth',2)
>> title('All Stars')
>> xlabel('x(t)')
>> ylabel('y(t)')
>> legend('stars','line',3)
Результат выполнения этих команд представлен на рис. 2.13.
В одном графическом окне создается два графика, причем обе функции за-
даны в параметрическом виде. Кривая для первой функциональной зави-
симости представляет собой окружность радиуса 2π . Вторая кривая – это
спираль. Для создания базовых точек первой кривой используем команды
t=0:0.1:2*pi (узловые точки параметра, через который задаются в па-
раметрическом виде обе функциональные зависимости), x=2*pi*cos(t)
(соответствует уравнению () 2 cos()
xt
t
π
=
) и y=2*pi*sin(t) (соответ-
ствует уравнению () 2 sin()
yt
t
π
=
). Вторая кривая (спираль) задана зави-
симостями ()
cos(4)
ut
t
t
=
(ей соответствует команда u=t.*cos(4*t))
и()
sin(4)
vt
t
t
=
(ей соответствует команда v=t.*sin(4*t)).
Самоучитель Matlab
58
Командой plot(x,y,'p','MarkerSize',10,'MarkerFaceColor',
'r','MarkerEdgeColor','g') создается график первой функции. Базо-
вые точки отображаются пятиконечными звездами, в явном виде задан раз-
мер маркеров (значение опции MarkerSize указан равным 10), красный
цвет заливки области маркера (значение 'r' для опции MarkerFaceColor)
и зеленый цвет границ символа маркера (значение 'g' для опции
MarkerEdgeColor). Далее командами axis equal, grid on и hold on
соответственно фиксируется одинаковый масштаб по каждой из координат-
ных осей, отображается координатная сетка и выполняется переход в режим
вывода графиков без замещения в одно графическое окно – чтобы график
следующей функции отображался вместе с первым графиком.
Спираль к уже созданному графику добавляем с помощью команды
plot(u,v,'b-','LineWidth',2). Здесь через опции указаны следую-
щие параметры: сплошная линия синего цвета толщины 2 (значение опции
LineWidth).
Командой title('All Stars') добавляется заголовок графика, под-
пись для горизонтальной оси определяется командой xlabel('x(t)'),
а подпись для вертикальной оси – командой ylabel('y(t)'). Ле-
генда в левом нижнем углу области графика добавляется командой
legend('stars','line',3).
Рис. 2 .13. При создании графика использовались команды настройки параметров графики
Глава 2. Графика в Matlab
59
Достаточно полезной является функция plotyy(). Она позволяет отобра-
жать в разном масштабе по вертикальной координатной оси одновременно
два графика. Результат применения этой функции показан на рис. 2.14.
Рис. 2 .14 . Результат создания графики с помощью функции plotyy()
В данном случае для создания графика использовалась следующая после-
довательность команд:
>> x=0:0.01:10;
>> y=-5:0.01:5;
>> f=cos(x)./(1+x);
>> F=10*y.^5.*exp(-y.^2);
>> plotyy(x,f,y,F)
В графическом окне представлены графики функций
cos( )
()1
x
fx
x
=
+
на
интервале 01
0
x
≤≤ и функции
52
()10exp()
Fy
y
y
=−
на интервале
55
y
−≤
≤ . Общий интервал аргумента вдоль горизонтальной координат-
ной оси изменяется, таким образом, от -5 до 10. Что касается вертикальной
координатной оси, то для каждой из двух функций масштаб свой. Масштаб
для первой функции определяется по координатной оси вдоль левой гра-
ницы области графика и соответствует диапазону значений от -1 до 1. Мас-
штаб для второй функции определяется по координатной оси вдоль правой
границы области графика и соответствует диапазону значений от -10 до 10.
Самоучитель Matlab
60
Такой режим бывает очень удобен, когда нужно, например, сравнить два па-
раллельных (синхронных) сигнала или процесса разной амплитуды.
Достаточно удобным может быть режим отображения нескольких графиков
в отдельных подокнах одного графического окна. В этом случае использу-
ют функцию subplot(). У функции три аргумента. Первые два определя-
ют количество подокон, на которые разбивается графическое окно. Третий
аргумент определяет порядковый номер подокна для вывода следующего
графика. В частности, все графическое окно условно разбивается на по-
докна равного размера (хотя, как будет показано далее, это не всегда так).
Образуется своеобразная матрица из подокон. Первый аргумент функции
subplot() определяет количество строк, а второй – количество столбцов
такой матрицы. Например, если первый аргумент 2, а второй аргумент 3, то
в графическом окне будет 6 подокон: по три подокна в два ряда. Порядок
нумерации подокон в такой структуре выполняется слева направо, сверху
вниз (то есть сначала последовательно, начиная с единицы, нумеруются
подокна в первом ряду, затем во втором, и так далее). Сам по себе вызов
функции с тремя аргументами создает только одно подокно, в которое за-
тем функцией plot() выводится график. Пример использования функции
subplot() в блоке команд приведен ниже:
>> x=-4*pi:0.01:4*pi;
>> y1=sin(x);
>> y2=sin(x)./x;
>> y3=(1-cos(x))./x.^2;
>> y4=x.^4.*exp(-x.^2);
>> y5=tanh(x);
>> y6=exp(-x.^2).*cos(x);
>> subplot(2,3,1);plot(x,y1)
>> subplot(2,3,2);plot(x,y2)
>> subplot(2,3,3);plot(x,y3)
>> subplot(2,3,4);plot(x,y4)
>> subplot(2,3,5);plot(x,y5)
>> subplot(2,3,6);plot(x,y6)
Команды создания графических подокон и отображения в них графиков
размещаются в одной командной строке. В качестве разделителя между
командами используется точка с запятой.
На заметку
Такой режим не является обязательным: можно было команды вводить после-
довательно, одна за другой.
В результате выполнения этих команд создается следующее графическое
изображение (рис. 2.15).
Глава 2. Графика в Matlab
61
Рис. 2 .15. В одном графическом окне несколько подокон
Работа с графическими подокнами осуществляется, в общем, так же, как
и с одним окном. Следует только помнить, какое подокно на данный мо-
мент активно.
С помощью функции subplot() не обязательно создавать подокна одина-
кового размера. Например, после выполнения приведенных выше команд
выполнить еще две:
>> subplot(2,1,2)
>> plot(x,y4)
В этом случае получим результат, как на рис. 2.16.
Произошло следующее: в верхнем ряду графического окна-контейнера ото-
бражено три подокна одинакового размера, а в нижнем ряду – одно подокно,
которое занимает всю нижнюю область графического окна. Дело в том, что
командой subplot(2,1,2) область графического окна условно разбива-
ется на две части (два подокна одинакового размера), но реально создается
только нижнее подокно – в соответствии с третьим аргументом функции
subplot(). При этом три уже существующие подокна в нижней части, ко-
торые полностью перекрываются вновь созданным подокном, исчезают. Бо-
лее того, даже если существующее подокно перекрывается новым подокном
только частично, оно тоже удаляется. Например, рассмотрим команды:
Самоучитель Matlab
62
Рис. 2 .16. Подокна разного размера
Рис. 2 .17 . Подокна совершенно разного размера
Глава 2. Графика в Matlab
63
>> subplot(2,2,1)
>> plot(x,y2)
С их помощью в левой верхней четверти графического окна создается но-
вое подокно, которое полностью перекрывает одно подокно в первом ряду
и еще одно, следующее, подокно – частично. В результате удаляются оба
подокна (рис. 2.17).
Работа с графиками в подокнах осуществляется, в общем-то, так же, как
и с обычными графическими окнами, просто предварительно необходимо
с помощью функции subplot() выделить нужное подокно. На рис. 2.18
показан результат отображения в подокне, активированном командой
subplot(2,2,1) координатной сетки.
Рис. 2 .18. В один из графиков добавлена координатная сетка
Сетка, как и в предыдущих случаях, добавляется командой grid on. После
выполнения команд subplot(2,1,2) и legend('my function',4) в гра-
фик в нижней части графического подокна будет добавлена легенда (рис. 2.19).
На заметку
Чтобы убрать легенду из графика, достаточно выполнить команду legend off.
Так же поступаем, чтобы убрать координатную сетку – полезной окажется
команда grid off. Еще раз напомним, что предварительно нужно будет акти-
вировать соответствующее подокно.
Самоучитель Matlab
64
Нередко возникает необходимость работать сразу с несколькими графи-
ческими окнами. Такой режим работы также возможен. В этом случае по-
лезной окажется инструкция figure, с помощью которой создается новое
графическое окно, которое становится активным. Следующий создаваемый
график будет отображен в этом окне. Окна нумеруются подряд, то есть
Figure 1, Figure 2 и так далее. При желании активным можно сделать любое
из существующих окон, для чего достаточно вызвать функцию figure(),
указав ее аргументом номер окна, которое необходимо активировать.
График в полярных координатах
Вы - умный человек. Вы, очевидно, точно
рассчитали, что в моих силах, а что выше
моих сил.
К/ф "Семнадцать мгновений весны"
Для создания графика в полярной системе координат используют встро-
енную функцию Matlab polar(). Напомним, что положение точки на
плоскости в полярных координатах задается расстоянием r до точки от
начала координат и углом φ направления на точку. Между полярными
координатами (, )
r φ и декартовыми (, )
xy существует связь:
cos( )
xrφ
=
и
sin( )
yrφ
=
.
Рис. 2 .19. В один из графиков добавлена легенда
Глава 2. Графика в Matlab
65
При создании графика в полярных координатах первым аргументом функ-
ции polar() передается вектор со значениями φ -координат, а второй ар-
гумент – вектор со значениями r -координат. Например, для того, чтобы по-
строить график функции, заданной в полярных координатах соотношением
sin(3 )
r
φ
=
, используем следующие команды:
>> phi=0:0.01:2*pi;
>> r=sin(3*phi);
>> polar(phi,r)
Результат представлен на рис. 2.20.
Рис. 2 .20. График в полярных координатах
Фактически тот же график в декартовых координатах можно построить
с помощью функции plot(), если воспользоваться такой последователь-
ностью команд:
>> x=r.*cos(phi);
>> y=r.*sin(phi);
>> plot(x,y)
Здесь на основе полярных координат создаются векторы с декартовыми ко-
ординатами, на основе которых затем строится график функции. Результат
для этого случая представлен на рис. 2.21.
Самоучитель Matlab
66
Рис. 2 .21. График создан в декартовых координатах
Несмотря на такую простоту и эффективность, пользоваться функцией
polar() следует достаточно осторожно. Дело в том, что по определению,
в полярных координатах полагают
0
r ≥ . Поэтому если формально функ-
циональная зависимость такая, что r -координата должна быть отрицатель-
ной, то обычно это означает, что
0
r = (или что для этого углового сегмен-
та функциональная зависимость не определена). Несколько иначе дела
обстоят в Matlab. При построении графика в полярных координатах точки
с отрицательными r -координатами тоже отображаются на графике. В этом
случае выполняется инверсия направления на точку. Другими словами,
если точка для отображения на графике имеет координаты (,)
r
φ , причем
0
r < , то отображается точка с координатами (,)
r
φπ
+−
.
В рассмотренном выше примере при создании векторов значений коор-
динат точек графика вектор для r -координат содержит отрицательные
значения (желающие могут в этом убедиться, для чего достаточно ввести
в командную строку имя переменной r и нажать клавишу <Enter>).
На заметку
Это, кстати, вполне логично и правильно – вектор координат создается, в со-
ответствии с уравнением кривой, по тем же правилам, что и обычные векторы.
Было бы странным, если бы отрицательные значения почему-то игнорирова-
лись или обрабатывались по-особенному.
Глава 2. Графика в Matlab
67
Почему же график, приведенный выше, был простроен правильно?
Причина проста: часть графика, построенная по точкам с отрицатель-
ными r -координатами, дублирует ту часть графика, что построена по
положительным r -координатам. Действительно, для зависимости, опре-
деляющей кривую в полярных координатах, имеет место соотношение
sin(3( )) sin(3 3 )
sin(3 )
r
φπ
φπ
φ
=+
=+
=
−
.
Другими словами, симме-
трия графика такова, что даже по "неправильному" набору точек получа-
ется "правильный" график. Такая ситуация имеет место для зависимостей
()
r φ , для которых ()(
)
rr
φπφ
+=
−
. Однако далеко не все кривые облада-
ют указанной симметрией. В качестве примера рассмотрим кривую, задан-
ную соотношением
12s
i
n
()
r
φ
=−
. Результат создания графика для этой
зависимости в Matlab представлен на рис. 2.22.
Рис. 2 .22 . На графике отображена "лишняя" ветка
График построен последовательностью команд:
>> phi=0:0.01:2*pi;
>> r=1-2*sin(phi);
>> polar(phi,r)
В принципе, диапазон значений
15
66
πφπ
<< полярного угла определяет
зону, в которой графика быть не должно (здесь 2sin( ) 1
φ> )–еготаминет.
Зато есть дополнительная, меньшая, ветка графика. Эта ветка строится по
точкам с отрицательными полярными координатами для значений полярного
Самоучитель Matlab
68
угла
15
66
πφπ
<< . В последнем убедиться достаточно легко – стоит лишь
построить график функции
|1 2sin( )|
r
φ
=−
. Результат показан на рис. 2.23.
Рис. 2.23. График построен по "правильному" набору точек
На заметку
Для создания графика вектор полярных координат вычисляется с помощью
команды r=abs(1-2*sin(phi)), в которой использована встроенная функ-
ция вычисления модуля abs().
Принципиальное различие между графиками, представленными на
рис. 2.22 и рис. 2.23, состоит в способе отображения "маленькой" ветки. На
рис. 2.23 она отображена "правильно", в соответствии со способом опреде-
ления функции. На рис. 2.22 наличие "маленькой" ветки – целиком "заслу-
га" Matlab. С математической точки зрения ее вообще не должно быть.
Несмотря на сделанное замечание, описанная особенность, связанная со
способом отображения графиков в полярных координатах в Matlab, может
быть достаточно полезной, и ею не следует пренебрегать. Если все же нужно,
чтобы точки с отрицательными значениями для радиальных координат не
отображались, необходимо предпринять некоторые специальные меры. На-
пример, чтобы построить в полярных координатах "правильный" график для
зависимости () 1 2sin()
rφφ
=−
, можно воспользоваться при создании век-
тора значений радиальной координаты вместо команды r=1-2*sin(phi)
Глава 2. Графика в Matlab
69
командой r=max(0,1-2*sin(phi)). В этом случае с помощью встроенной
функции max() определения максимального значения из списка аргумен-
тов функции добиваемся того эффекта, что вместо отрицательных значений
радиальных координат в вектор значений заносятся нулевые значения, как
и должно быть. Результат желающие могут проверить самостоятельно.
Цвет и тип линий для графиков в полярных координатах определяются
так же, как и для обычных графиков. В известном смысле это относится
и к способу создания сразу нескольких графиков в одном графическом окне.
Правда, функция polar() не воспринимает второй набор аргументов для
отображения двух графиков – для этого нужно воспользоваться командой
hold on и перейти в режим отображения графиков в одном окне без удале-
ния уже существующих. На рис. 2.24 приведен пример создания нескольких
графиков в полярных координатах.
Рис. 2 .24. В одном графическом окне отображены два полярных графика
Для создания графиков в одном окне использовались следующие команды:
>> phi=-pi:0.01:pi;
>> r=cos(3*phi).^2;
>> Phi=0:0.01:10*pi;
>> R=Phi./(10*pi);
>> polar(phi,r,'--r')
>> hold on
>> polar(Phi,R,'-b')
Самоучитель Matlab
70
В результате в одном окне отображается сразу два графика: один красной
штрихованной линией, другой – синей сплошной.
Графики в полярных координатах можно отображать в подокнах графиче-
ского окна одновременно с обычными графиками (то есть графиками в де-
картовых координатах). Например, можно воспользоваться такой последо-
вательностью команд:
>> y=sin(phi)./phi;
>> subplot(2,1,1)
>> plot(phi,y)
>> subplot(2,2,3)
>> polar(phi,r)
>> subplot(2,2,4)
>> polar(Phi,R)
>> subplot(2,1,1)
>> grid on
В результате получаем графическое окно с тремя подокнами: в верхнем под-
окне отображен график в декартовых координатах, а в двух нижних подок-
нах – графики в полярных координатах (рис. 2.25).
Рис. 2 .25. Графики отображаются в подокнах графического окна
Такой подход является общим для работы с графиками разного типа, если
они отображаются в подокнах одного графического окна.
Глава 2. Графика в Matlab
71
Контурные графики
Холмс, это исключено. Сразу видно, что
Вы мало читаете.
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
Контурные графики используются для графического представления функ-
ций от двух координат и являются альтернативой к созданию трехмерных
поверхностей. На контурном графике для функциональной зависимости
(,)
fxy в координатной плоскости строятся кривые вида (, )
fxy const
=
(контуры) для разных значений константы const в правой части. Обычно
в качестве дополнительного (а иногда и основного) индикатора исполь-
зуется цветовая раскраска контурного графика. В этом случае цветовой
диапазон соотносится с диапазоном значений отображаемой на контурном
графике функции. Такой режим достаточно наглядный и используется, на-
пример, при построении температурных карт.
Для создания контурного графика, среди прочего, может использоваться
функция contour(). Существует несколько способов передачи аргумен-
тов этой функции. Рассмотрим наиболее общие.
Поскольку речь идет о функции двух переменных, базовые точки, на осно-
вании которых строится контурный график, и значения функции в этих
базовых точках должны представляться в виде матриц. Процесс созда-
ния матриц узловых точек обычно подразумевает использование функ-
ции meshgrid(). Если в качестве первого и второго аргументов функции
указать векторы-строки, то в качестве результата функцией возвращается
две матрицы. Первая получается построчным повторением первого век-
тора, а количество повторений определяется количеством компонентов
во втором векторе-аргументе. Вторая матрица, возвращаемая функцией
meshgrid(), получается транспонированием второго вектора-аргумента
функции. Столбцы повторяются столько раз, сколько элементов в пер-
вом векторе-аргументе. Например, если вызвать функцию meshgrid()
в команде вида [X,Y]=meshgrid(x,y), то в результате матрица X будет
состоять из строк, совпадающих с вектором x. Количество строк равняется
количеству элементов в векторе y. Матрица Y будет состоять из столбцов,
совпадающих с транспонированным вектором y. Количество столбцов рав-
няется количеству элементов в векторе x.
Этот способ создания матриц узловых точек может показаться несколь-
ко запутанным и сложным, но даже если так, это впоследствии с лихвой
компенсируется простотой создания матрицы значений функции в узло-
вых точках и быстротой и легкостью построения всевозможных графиков.
Самоучитель Matlab
72
Например, предположим, что матрица значений функции в узловых точках Z
вычисляется на основе матриц X и Y. Если для этого используется стандарт-
ная встроенная функция Matlab, то обычное правило вычисления функции
для матричных аргументов состоит в том, что в вычислениях используются
соответствующие элементы матриц. Так, для вычисления значения Z(i,j)
будут использованы узловые точки X(i,j) и Y(i,j). Если матрицы X и Y
создавались по описанной выше схеме на основании векторов x и y, то тог-
да X(i,j) совпадает со значением x(j), а Y(i,j) совпадает со значением
y(i). Таким образом, первый индекс элемента матрицы значений функции
в узловых точках соответствует индексу вектора узловых точек, переданного
вторым аргументом функции meshgrid(), а второй индекс элемента матри-
цы значений функции в узловых точках соответствует индексу вектора узло-
вых точек, переданного первым аргументом функции meshgrid().
Для создания контурного графика функции, табулированной матрицей Z
в узловых точках X и Y, можно воспользоваться командой contour(X,Y,Z).
На рис. 2.26 приведен пример создания контурного графика для функции
22
sin( ) sin( )
(,)
xy
zxy
xy
=
+
.
Рис. 2 .26. Простой контурный график
Для создания графика использовались следующие команды:
Глава 2. Графика в Matlab
73
>> x=-2*pi:0.1:2*pi;
>> y=x;
>> [X,Y]=meshgrid(x,y);
>> Z=sin(X).*sin(Y)./sqrt(X.^2+Y.^2);
>> contour(X,Y,Z)
График функции строится на интервале значений от 0 до 2π по каждо-
му из аргументов. Узловые точки с помощью функции meshgrid() за-
носятся в матрицы X и Y. Значения функции в узловых точках командой
Z=sin(X).*sin(Y)./sqrt(X.^2+Y.^2) заносятся в матрицу Z. Кон-
турный график строится командой contour(X,Y,Z).
При создании контурного графика контурные линии определяются автома-
тически. Третьим аргументом можно указать целое число, которое опреде-
лит количество контурных линий (точнее, количество значений функции,
для которых отображаются контурные линии). Если третьим аргументом
указан вектор с числовыми значениями, то на контурном графике будут
отображаться контурные линии. На рис. 2.27 представлен результат созда-
ния контурного графика командой contour(X,Y,Z,30).
Рис. 2 .27. На контурном графике увеличено количество контурных линий
Как видим, количество контурных линий на графике значительно уве-
личилось (теперь контурные линии отображаются для 30 значений
функции). Результат последовательного выполнения команд vals=
Самоучитель Matlab
74
[-0.3
- 0.1
- 0.05 0 0.01 0.05] и contour(X,Y,Z,vals) пред-
ставлен на рис. 2.28.
Рис. 2 .28. На контурном графике отображаются контурные линии с предопределенными
значениями функции
Контурные линии отображаются всего для пяти значений функции. Значе-
ния, для которых отображаются контурные линии, представлены элементом
вектора vals, который передается третьим аргументом функции contour().
Достаточно серьезным недостатком представленных выше графиков явля-
ется то обстоятельство, что контурные линии не содержат меток, на основа-
нии которых можно было бы установить, какому значению соответствует
та или иная контурная линия. Для отображения меток у контурных линий
используют функцию clabel(). Функции первым аргументом передается
матрица контурных линий и указатель на соответствующий графический
объект. Эти два параметра возвращаются при вызове функции contour().
На заметку
В Matlab указатели (переменные специального типа) играют роль ссылок на раз-
личные объекты (в том смысле, в котором термин объект используется в про-
граммировании). Мы в основном будем использовать указатели на функции, но
об этом речь пойдет позже.
На рис. 2.29 представлен контурный график с метками для контурных линий.
Глава 2. Графика в Matlab
75
Рис. 2 .29. На контурном графике отображаются метки значений для контурных линий
Для создания графика использовались команды:
>> [C,h]=contour(X,Y,Z,[-0.5
-0.1 0 0.1 0.3]);
>> clabel(C,h)
Первой командой создается контурный график, а в переменные C и h соот-
ветственно записываются значения матрицы контурных линий и указателя
на графический объект. Командой clabel(C,h) на этом графике добавля-
ются маркеры контурных линий.
На заметку
В Matlab функции могут возвращать (и как правило возвращают) сразу несколь-
ко значений в качестве результата. Если из функции нужно "считать" несколько
значений, они "считываются" в список. Общий формат команды вызова функции,
возвращающей несколько значений, имеет вид [значение1,значение2,...]=
функция(аргументы). Именно такого типа команда и использовалась выше.
Несложно заметить, что надписи вдоль контурных линий отображаются не
всегда самым приемлемым образом. При вызове функции clabel() мож-
но перейти в режим, который позволяет вручную определять, в каком месте
на контурных линиях отображать метки значений. Для этого необходимо
третьим аргументом указать текст manual (аргумент заключается в оди-
нарные кавычки). После выполнения такой команды создается график,
Самоучитель Matlab
76
Рис. 2 .30. Ввод меток контурных линий в ручном режиме
Рис. 2 .31. Контурный график с заливкой области графика
Глава 2. Графика в Matlab
77
в котором, в интерактивном режиме пользователем, с помощью мыши,
определяется место размещения меток для контурных линий. Процедуру
выбора места для меток контурных линий иллюстрирует рис. 2.30.
На контурной линии выбирается место, и после щелчка мышью там появ-
ляется метка (подпись) со значением функции, соответствующим выбран-
ной контурной линии. Для прекращения ввода меток достаточно нажать
клавишу <Enter> или щелкнуть мышкой вне области рисунка.
Для отображения контурного графика с заливкой области графика цветом
используют функцию contourf(). На рис. 2.31 приведен пример создания
контурного графика с помощью команды contourf(X,Y,Z).
Способ использования функции contourf() аналогичен к функции
contour(). Например, на рис. 2.32 представлен контурный график, кото-
рый создается командой contourf(X,Y,Z,30).
Рис. 2 .32. Контурный график с заливкой и увеличенным количеством контурных линий
В данном случае третьим аргументом указывается количество зна-
чений функции, для которых строятся контурные линии. Командой
contourf(X,Y,Z,vals) (где вектор vals такой же, как и в рассмотрен-
ном выше примере) создается контурный график (с заливкой цветом)
с контурными линиями для значений, определяемых третьим аргументом –
вектором vals (рис. 2.33).
Самоучитель Matlab
78
Рис. 2 .33. Контурный график с заливкой и контурными линиями для предопределенных
значений функции
Рис. 2 .34. Контурный график с заливкой и отображением подписей для контурных линий
Глава 2. Графика в Matlab
79
Точно так же, как отображаются метки для контурных линий в случае ис-
пользования функции contour(), выполняется отображение меток для
контурных линий заполненного цветом контурного графика (рис. 2.34).
В данном случае использовались следующие команды:
>> [C,h]=contourf(X,Y,Z,[-0.5
- 0.1 0 0.1 0.3]);
>> clabel(C,h)
Отметим также, что при выполнении заливки цветом в контурных графи-
ках (и не только) полезной может быть функция colormap(). Она по-
зволяет изменить используемую по умолчанию цветовую палитру. Аргу-
ментом функции могут указываться, кроме прочего, следующие ключевые
слова: jet, hsv, hot, cool, spring, summer, autumn, winter, gray, bone,
copper, pink и lines. Каждое из этих ключевых слов соответствует пре-
допределенной цветовой палитре. Желающие изучить этот вопрос подроб-
но могут обратиться к справочной системе Matlab или поэкспериментиро-
вать с рабочими документами. Для перехода к используемой по умолчанию
цветовой палитре воспользуемся командой colormap('default').
Создание трехмерных графиков
-
Крупное дело?
-
Давно такого не было!
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Собака Баскервилей"
Трехмерные поверхности создаются с помощью функции mesh(). Аргу-
менты функции (узловые точки и значения функции в этих точках) опре-
деляются так же, как и для рассмотренных выше функций contour()
и contourf(). На рис. 2.35 представлена поверхность для той же функци-
ональной зависимости по тем же базовым точкам, для которой выше строи-
лись контурные графики.
Для создания поверхности использовалась команда mesh(X,Y,Z). При
этом поверхность отображается в виде сетки. У функции mesh() существу-
ют модификации: функции meshc() и meshz(). Функция meshc() по-
зволяет одновременно с трехмерной поверхностью строить в горизонталь-
ной координатной плоскости контурный график, как показано на рис. 2.36.
График построен с помощью команды meshc(X,Y,Z). В таком (то есть
в режиме отображения кроме трехмерной поверхности еще и контурных
линий) обычно бывает легче анализировать представленные в графическом
виде зависимости, поскольку фактически для одной и той же функцио-
нальной зависимости отображается сразу два графика: пространственная
поверхность и контурный график.
Самоучитель Matlab
80
Рис. 2 .35. Трехмерная поверхность (сетка)
Рис. 2 .36. Трехмерная поверхность и контурные линии
Глава 2. Графика в Matlab
81
При вызове команды meshz(X,Y,Z) создается график, представленный на
рис. 2.37.
Рис. 2 .37. Трехмерная поверхность с "подложкой"
В этом случае график отображается с "подложкой": область под поверхно-
стью представляет собой заполненный объем. Это довольно специфический
режим отображения поверхностей, который, тем не менее, бывает в некото-
рых случаях весьма удобен и полезен.
С помощью функции mesh() создаваемые трехмерные поверхности ото-
бражаются в виде сетки. Если необходимо сделать поверхность сплошной,
обычно используют функцию surf(). Результат создания трехмерной по-
верхности с помощью команды surf(X,Y,Z) представлен на рис. 2.38.
Кроме базовой сетки, выполнена также заливка цветом. Во всем остальном
график схож с тем, что создавался функцией mesh() (см. рис. 2.36).
Функция surfc() позволяет отображать не только трехмерную поверх-
ность, но и контурные линии в горизонтальной координатной плоскости –
в полной аналогии с функцией meshc(). На рис. 2.39 представлен резуль-
тат создания графика с помощью команды surfc(X,Y,Z).
В некоторых случаях удобным может быть режим, в котором график (трех-
мерная поверхность) "подсвечивается" (рис. 2.40).
Самоучитель Matlab
82
Рис. 2 .38. Трехмерная поверхность с заливкой цветом
Рис. 2 .39. Трехмерная поверхность с заливкой цветом и контурными линиями
Глава 2. Графика в Matlab
83
Рис. 2 .40. Трехмерная поверхность в режиме выделения цветом
Речь идет о цветовом выделении поверхности графика так, как если бы он
находился под действием источника света. Для отображения графика в та-
ком режиме используют функцию surfl(). В частности, график (поверх-
ность) на рис. 2.40 создан с помощью команды surfl(X,Y,Z).
Параметрические кривые и поверхности
Скажите, доктор Ватсон, Вы понимаете
всю важность моего открытия?
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Знакомство"
Как известно, самый простой способ задать пространственную кривую со-
стоит в том, чтобы параметризировать ее, то есть ввести параметр, и коор-
динаты точек на пространственной кривой представить в виде функции от
этого параметра. Для создания пространственных кривых в Matlab исполь-
зуют функцию plot3(). В самом простом случае аргументами функции
указывают векторы координат точек на пространственной кривой. Пример
такой кривой представлен на рис. 2.41.
Для создания пространственной кривой использовалась следующая после-
довательность команд:
Самоучитель Matlab
84
>> t=0:0.01:2*pi;
>> x=cos(10*t).*sin(t/2);
>> y=sin(10*t).*sin(t/2);
>> z=cos(t/2);
>> plot3(x,y,z)
>> grid on
>> axis equal
В данном случае речь идет о своеобразной винтовой линии, накрученной на
сферу. Пространственная кривая задается в параметрическом виде зависи-
мостями ( ) cos(10 ) sin( 2)
xt
tt
=
,
( ) sin(10 )sin( 2)
yt
tt
=
и () cos(2)
zt
t
=
,
где параметр 02
t
π
≤≤ . Точка с координатами (, , )
xyz находится на по-
верхности единичного радиуса (с центром в начале координат). Для реали-
зации векторов с координатами точек на кривой создается вектор значений
параметра t параметрической зависимости (команда t=0:0.01:2*pi).
На основе этого вектора командами x=cos(10*t).*sin(t/2),
y=sin(10*t).*sin(t/2) и z=cos(t/2) создается три вектора с коорди-
натами. Затем командой plot3(x,y,z) строится пространственная кри-
вая. Командами grid on и axis equal отображается координатная сетка
и устанавливается одинаковый масштаб по координатным осям.
В параметрическом виде может быть задана и поверхность. В этом случае
координаты точек на поверхности определяются как функции от двух пара-
Рис. 2 .41. Пространственная кривая
Глава 2. Графика в Matlab
85
метров. Процесс создания параметрически заданной поверхности в Matlab
мало отличается от создания поверхности, заданной в явном виде. В част-
ности, на основе параметрических зависимостей строятся матрицы узловых
точек и значения функции в этих узловых точках, после чего поверхность
строится с помощью функции mesh() или surf().
В качестве иллюстрации рассмотрим процесс построения сферы, при
условии, что она задана в параметрическом виде. Для сферы единичного
радиуса с центром в начале координат координаты на поверхности сферы
задаются зависимостями ( , ) cos( ) sin( )
xφθ
φθ
=
,
(,) sin()sin()
yφθ
φθ
=
и
(,) cos()
zφθ
θ
=
, где параметры 02
φπ
≤≤и0 θπ
≤≤. Построить сфе-
ру можно с помощью серии следующих команд:
>> phi=0:0.1:2*pi;
>> theta=0:0.1:pi;
>> [Phi,Theta]=meshgrid(phi,theta);
>> X=cos(Phi).*sin(Theta);
>> Y=sin(Phi).*sin(Theta);
>> Z=cos(Theta);
>> mesh(X,Y,Z)
>> axis equal
Результат представлен на рис. 2.42.
Рис. 2 .42. Сфера построена на основе параметрических зависимостей
Самоучитель Matlab
86
В данном случае командами phi=0:0.1:2*pi и theta=0:0.1:pi соз-
даются векторы со значениями параметров. При построении поверхности,
заданной в параметрическом виде, весь процесс содержит несколько допол-
нительных этапов по сравнению со случаем, когда поверхность задана явно.
При этом цель та же: создать три матрицы – две матрицы с узловыми точка-
ми и матрицу со значениями функции в узловых точках. Если поверхность
задана явно, то обычно с помощью функции meshgrid() на основании
векторов узловых точек строятся матрицы узловых точек. В данном случае
на основании векторов значений параметров построим сначала матрицы
узловых точек по параметрам, а затем на основании этих матриц создадим
матрицы узловых точек в декартовых координатах.
Матрицы узловых точек Phi и Theta по параметрам возвращаются при
выполнении команды [Phi,Theta]=meshgrid(phi,theta). На осно-
вании матриц Phi и Theta командами X=cos(Phi).*sin(Theta),
Y=sin(Phi).*sin(Theta) и Z=cos(Theta) в соответствии с параметри-
ческими соотношениями для координат точек на поверхности строятся ма-
трицы базовых точек в декартовых координатах. Командой mesh(X,Y,Z)
отображается поверхность, а команда axis equal необходима для того,
чтобы установить равный масштаб по всем координатным осям – в против-
ном случае сфера будет больше походить на эллипс.
Параметры трехмерной графики
Все те вопросы, которые были
поставлены, мы их все соберем
в одно место.
В. Черномырдин
Настроек, применяемых при работе с графикой, в Matlab очень много. Этой
теме можно было бы посвятить отдельную книгу. Это замечание относится
отдельно как к двумерной графике, так и к трехмерной. Настройки могут
выполняться как в графическом окне посредством утилит интерфейса, так
и с помощью команд, вводимых и выполняемых в рабочей области. Здесь
отметим только некоторые, наиболее показательные и часто используемые
команды.
В первую очередь остановимся на функции view(), которая позволяет за-
дать способ ориентации трехмерного графика при отображении. Аргумен-
том функции указывается вектор со значением азимутального и полярного
углов, определяющих направление на график, вдоль которого выполняется
проекция. Пример отображения одного и того же графика "под разными
углами" представлен на рис. 2.43.
Глава 2. Графика в Matlab
87
Рис. 2 .43. Трехмерный график под разными углами зрения
Графики строятся с помощью такой последовательности команд:
>> u=0:0.1:2*pi;
>> v=0:0.1:pi;
>> [U,V]=meshgrid(u,v);
>> X=V.*cos(U);
>> Y=V.*sin(U);
>> Z=cos(3*V).*U;
>> subplot(2,2,1);mesh(X,Y,Z);view([0 30]);title('view([0 30])')
>> subplot(2,2,2);mesh(X,Y,Z);view([60 45]);title('view([60 45])')
>> subplot(2,2,3);mesh(X,Y,Z);view([120 60]);title('view([120 60])')
>> subplot(2,2,4);mesh(X,Y,Z);view([180 90]);title('view([180 90])')
Собственно, в четырех подокнах графического окна отображается одна
и та же поверхность, заданная в параметрическом виде уравнениями
(,)
cos( )
xuv
v
u
=
,
(,)
sin()
yuvvu
=
и
(,)
cos(3 )
zuv
u
v
=
,
параметры
02
u
π
≤≤и0 v
π
≤≤. Однако каждый раз выбирается разное направ-
ление проекции. Направление задается функцией view(). Аргументом
функции указывается вектор с двумя элементами – значениями (в граду-
сах) азимутального и полярного углов. Для удобства с помощью функции
title() в подокнах отображается текст команды выбора направления на
график с аргументами функции view().
Самоучитель Matlab
88
Обычно при цветовом выделении поверхности удобно отображать рядом
с поверхностью цветовую шкалу. Для этого используется команда colorbar.
Пример использования команды приведен ниже:
>> figure
>> surf(X,Y,Z)
>> view([120 60])
>> colorbar
В результате получаем графическое окно с графиком поверхности и цвето-
вой шкалой, как на рис. 2.44.
Рис. 2 .44 . На графике отображена цветовая шкала
График создается в новом окне на основе введенных ранее данных (см.
предыдущий пример отображения графиков под разным углом).
При отображении поверхности в виде сетки по умолчанию действует ре-
жим, при котором части поверхности на заднем фоне, которые закрываются
впереди расположенными частями поверхности, не отображаются. Выйти
из этого режима можно с помощью инструкции hidden off. Результат
представлен на рис. 2.45.
Поверхность создавалась такими командами:
>> mesh(X,Y,Z)
>> hidden off
Глава 2. Графика в Matlab
89
При этом сетка становится "прозрачной" – становятся видимыми и даль-
ние части поверхности. Для поверхностей, созданных с помощью функции
surf(), инструкция hidden off воздействия не имеет.
Тем не менее, самый простой способ придать графику нужный вид – вос-
пользоваться встроенными утилитами настройки, которые доступны в гра-
фическом окне и реализуются через систему кнопок и меню. Общая схема
настройки трехмерной графики в основном мало отличается от того, как
выполняется настройка внешнего вида двумерных кривых. Поскольку ни-
чего принципиально сложного в этом нет, думается, читатель при необходи-
мости освоит эти методы самостоятельно.
Анимация
После истории с часами я готов верить все-
му, что Вы скажете. Но, черт возьми, как?!
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Кровавая надпись"
В Matlab можно создавать не только превосходные графики, но и довольно
неплохую анимацию. Существует несколько фундаментальных подходов от-
носительно создания анимации. Здесь рассмотрим один – пожалуй, наиболее
простой. В этом случае задача по созданию анимации сводится, по большо-
Рис. 2 .45. Поверхность в виде сетки отображается в режиме прозрачности
Самоучитель Matlab
90
му счету, к созданию набора анимационных кадров и, затем, к их последова-
тельному отображению. Полезными при этом могут оказаться две функции:
функция movie() для отображения последовательности кадров и функция
getframe(), используемая для создания анимационного кадра. Если вы-
звать функцию getframe() без аргументов, то в качестве значения возвра-
щается изображение (структура, имеющая два поля – матрицу изображе-
ния cdata и матрицу цветовой палитры colormap). Аргументом функции
getframe() можно передать ссылку (указатель) на графическое окно или
систему координат. В свою очередь, получить ссылку на текущее графиче-
ское окно можно с помощью функции gcf. Более простой способ – указать
номер графического окна (номер графического окна указывается в его на-
звании после слова Figure). Ссылку на текущую систему координат можно
получить с помощью функции gca. Кроме ссылки на графическое окно, вто-
рым аргументом можно указать четырехкомпонентный вектор, определяю-
щий область графического окна, которая записывается в кадр. Первые два
элемента вектора определяют позицию нижней левой точки области на гра-
фике в пикселях по отношению к нижней левой точке рисунка или системы
координат (в зависимости от того, какая ссылка указана первым аргументом
функции getframe()), третий и четвертый - ширину и высоту области со-
ответственно. Далее приведены примеры использования этих функций для
создания единичных кадров. В частности, выполняем такую последователь-
ность команд (жирным шрифтом выделен ввод пользователя):
>> x=0:0.1:2*pi;
>> y=sin(x).^2./x;
>> z=cos(x)./(1+x);
>> plot(x,y,'r-o',x,z,'b--+')
>> grid on
>> F1=getframe(1,[100 50 300 200])
F1=
cdata: [200x300x3 uint8]
colormap: []
>> figure;image(F1.cdata)
В результате выполнения кода создается график двух функций (в одном
графическом окне) и на основании этого графика создается один анимаци-
онный кадр. График функций представлен на рис. 2.46.
Созданный кадр (изображение) представлен на рис. 2.47.
Разберем детальнее использованный код. Думается, команды созда-
ния исходного графика особых комментариев не требуют. Командой
F1=getframe(1,[100 50 300 200]) в переменную F1 записывается кадр,
который получается на основе фрагмента созданного перед этим графика. Это
область размерами 300 на 200 пикселей, левый нижний угол которой нахо-
Глава 2. Графика в Matlab
91
Рис. 2 .46. График, на основе которого создается анимационный кадр
Рис. 2 .47. Изображение, попавшее в кадр
Самоучитель Matlab
92
дится на расстоянии 100 пикселей по горизонтали и 50 пикселей по вертика-
ли от левого нижнего угла рисунка. Обращаем внимание, что первым аргумен-
том функции getframe() указано значение 1 – номер графического окна,
на основе которого создается кадр. Для отображения картинки, записанной
в кадр, используем команду image(F1.cdata), перед которой инструкцией
figure создается новое графическое окно, в котором и отображается картинка.
Картинка отображается с помощью функции image(). Аргументом указыва-
ется матрица изображения. Переменная кадра F1 является записью и имеет,
как отмечалось, два поля – матрица изображения cdata и матрица цветовой
палитры colormap. Аргументом функции image() указывается матрица
изображения, ссылка на которую выполняется в "точечном синтаксисе": ука-
зывается имя записи и, через точку, имя поля. В данном случае это F1.cdata.
Далее выполняем такую последовательность команд (ввод пользователя
выделен жирным шрифтом):
>> figure(1);h=gca
h=
170.0029
>> F2=getframe(h,[0 0 400 250])
F2=
cdata: [250x400x3 uint8]
colormap: []
>> figure;image(F2.cdata)
Результат представлен на рис. 2.48.
В данном случае командой figure(1) активным делается первое графиче-
ское окно, а командой h=gca создается ссылка на координатную систему
первого графического объекта. Отсчет для области выделения картинки на-
чинается от левого нижнего угла координатной системы.
Однако обычно для создания кадров анимации используется функция
getframe() без аргументов. Например, выполним в рабочем документе,
к уже выполненным, еще несколько команд:
>> figure(1);F3=getframe
F3=
cdata: [343x435x3 uint8]
colormap: []
>> figure;image(F3.cdata)
В результате создается кадр, представленный на рис. 2.49.
От исходного графика на рис. 2.47 данное изображение отличается, в общем-
то, только подписями вдоль координатных осей. На рис. 2.49 значения ука-
заны в пикселях.
Глава 2. Графика в Matlab
93
Рис. 2 .48. Второй кадр, созданный на основе графического изображения
Рис. 2.49. Кадр создается на основе всего изображения
Самоучитель Matlab
94
Как отмечалось выше, для создания анимации необходимо создать после-
довательность кадров (вектор, элементами которого являются кадры –
структуры, которые создаются с помощью функции getframe()). Вектор
с кадрами анимации указывается первым аргументом функции movie().
Вторым аргументом указывается целое число, которое определяет количе-
ство прокруток анимации, то есть сколько раз будет отображаться последо-
вательность кадров, указанная в виде вектора первым аргументом функции
movie(). Если анимацию предполагается прокручивать один раз, то вто-
рой (единичный) аргумент можно не указывать.
Обычно при создании последовательности кадров используется оператор
цикла for. Операторы цикла, как и прочие методы программирования,
описываются в следующей главе. Здесь только кратко остановимся на син-
таксисе использования и принципах выполнения оператора цикла.
Оператор цикла начинается с ключевого слова for, после которого указывает-
ся индексная переменная, оператор присваивания и диапазон изменения этой
переменной (если нужно, с шагом дискретности). После этого указываются
команды, выполняемые в рамках каждого цикла. Заканчивается оператор цик-
ла ключевым словом end. Рассмотрим следующую последовательность команд:
>> phi=0:0.01:2*pi;
>> N=100;
>> X=cos(phi);
>> Y=sin(phi);
>> for k=1:N
alpha=phi-pi*k/N;
r=max(0,3*cos(2*alpha));
x=r.*cos(phi);
y=r.*sin(phi);
area(x,y)
hold on
area(X,Y)
grid on
axis equal
axis([-4 4
-4
4])
text(-0.8,3.5,['Frame N',num2str(k)],'FontSize',15,'Background
Color',[.5
.8
.5])
F(k)=getframe;
hold off
end
>> movie(F,2)
С помощью этого кода создается последовательность анимационных кад-
ров, а затем эти кадры отображаются. На рис. 2.50-2.54 показаны некоторые
из кадров анимации.
Глава 2. Графика в Matlab
95
Рис. 2.50. Первый кадр анимации
Рис. 2.51. Двадцать пятый кадр анимации
Самоучитель Matlab
96
Рис. 2 .52. Пятидесятый кадр анимации
Рис. 2 .53. Семьдесят пятый кадр анимации
Глава 2. Графика в Matlab
97
Рис. 2 .54. Сотый кадр анимации
Таким образом, создан своеобразный вращающийся пропеллер. Рассмотрим
подробнее программный код, с помощью которого создается анимация.
Командой phi=0:0.01:2*pi создается вектор значений полярного угла
для дальнейшего использования при создании функциональных зависимо-
стей. Командой N=100 определяется значение переменной-количества кад-
ров анимации. С помощью команд X=cos(phi) и Y=sin(phi) создаются
векторы узловых точек и значения функции в этих точках для окружности
единичного радиуса. Эти векторы используются для отображения централь-
ного круга на анимационных кадрах. Далее следует оператор цикла. Инструк-
ция for k=1:N в его начале означает, что индексная переменная k пробегает
значения от 1 до N с шагом дискретности 1 (шаг дискретности по умолча-
нию). Командой alpha=phi-pi*k/N создается вектор значений полярно-
го угла, повернутого по отношению к стандартному углу phi на величину
pi*k/N против часовой стрелки. Командой r=max(0,3*cos(2*alpha))
создается вектор базовых точек для заданной в полярных координатах
функции вида ( ) 3 cos(2(
))
rk
N
φφ
π
=−
-
то есть "лепесток" с поворотом.
Командами x=r.*cos(phi) и y=r.*sin(phi) создаются соответствую-
щие зависимости в декартовых координатах, а командой area(x,y) соз-
дается графическое окно с графиком, закрашенным цветом. Чтобы следую-
щий график выводился в том же окне, используем инструкцию hold on.
Самоучитель Matlab
98
Этот следующий график (закрашенная окружность) создается командой
area(X,Y). Командой grid on отображается координатная сетка. Для
установки одного масштаба по координатным осям используем инструк-
цию axis equal, а командой axis([-4 4
-4
4]) задается диапазон
значений по каждой из координатных осей. Следующая команда нужна
для того, чтобы отобразить на графике текст с номером кадра. Для этого
используем функцию text(). Первые два аргумента функции text() –
значения координат точки на графике, определяющих место вывода текста.
Третий аргумент – текстовая строка, которая выводится на графике. В дан-
ном случае это вектор, состоящий из двух элементов. Первый – текстовая
строка 'Frame N'. Второй аргумент – результат преобразования числа k
(индексная переменная) к текстовому формату. Для перевода числа в текст
используем функцию num2str(). Далее в функции text() идут аргумен-
ты, определяющие параметры текста. Аргументы указываются в формате
опция-значение. Сначала в одинарных кавычках указывается имя устанав-
ливаемой опции (параметра) текста, а после запятой – применяемое зна-
чение для опции. Так, размер шрифта (опция FontSize) устанавливается
равным 15, а цвет фона области вывода текста (опция BackgroundColor)
задается в формате RGB. Для этого используется вектор из трех числовых
значений (содержание красного, зеленого и синего цветов).
Командой F(k)=getframe создается кадр и записывается в качестве k-го
элемента вектора F. Команда hold off нужна для того, чтобы выйти из
режима удержания графики (то есть выйти из режима отображения новых
графиков без замещения уже существующих). В противном случае при соз-
дании последующих кадров новая картинка накладывалась бы на уже су-
ществующую. Инструкция end свидетельствует о том, что тело оператора
цикла закончилось. Наконец, посредством команды movie(F,2) анимаци-
онные кадры отображаются один за другим два раза.
Использование изображений
Мы продолжаем то, что мы уже много
наделали.
В. Черномырдин
Растровое графическое изображение в Matlab – это трехмерный массив
(доступ к элементам осуществляется по трем индексам). Размер по первым
двум размерностям определяется количеством пикселей в изображении.
Третий индекс может принимать всего три значения (1, 2 и 3). Цвет каждо-
го пикселя в изображении определяется в формате RGB. Если изображение
записано в массив A, то значение для содержания красного цвета в формате
RGB для пикселя, находящегося на пересечении i-й строки и j-го столбца,
Глава 2. Графика в Matlab
99
определяется элементом A(i,j,1), для зеленого – элементом A(i,j,2),
а для синего – элементом A(i,j,3) соответственно. Таким образом, рас-
тровое изображение состоит из трех двумерных матриц, каждая из которых
задает содержание соответственно красного, зеленого и синего цветов.
Чтобы отобразить растровое изображение, массив, в который записано изо-
бражение, указывают аргументом функции image(). Рассмотрим следую-
щий программный код:
>> for i=1:300
for j=1:500
A(i,j,1)=rem(i,30)/30;
A(i,j,2)=rem((i^2+j^2),200)/200;
A(i,j,3)=rem(j,50)/50;
end
end
>> image(A)
В результате создается изображение, представленное на рис. 2.55.
Рис. 2 .55 . Отображение созданного изображения
В данном случае изображение создается попиксельно, с помощью вложен-
ных операторов цикла. Индексная переменная i пробегает значение от 1 до
300. Индексная переменная j пробегает значения от 1 до 500. Изображение
формируется поэлементным заполнением массива A, и его размеры – 300 на
Самоучитель Matlab
100
500 пикселей. Содержание красного цвета для пикселя с координатами i
и j задается командой A(i,j,1)=rem(i,30)/30, в которой использована
функция rem() вычисления остатка от деления. Получаемые значения не
больше нуля и не превышают единицы и чередуются через каждые 30 пик-
селей вдоль вертикали. Для определения содержания синего цвета исполь-
зуется команда A(i,j,3)=rem(j,50)/50. Значения чередуются через
каждые 50 пикселей по горизонтали. Содержание зеленого цвета определя-
ется командой A(i,j,2)=rem((i^2+j^2),200)/200. В этом случае по-
лучаются периодические структуры из серии "круги на воде". Для отобра-
жения созданной таким образом картинки используем команду image(A).
Намного чаще изображения не создаются, а считываются из файла. Для счи-
тывания графического файла используют функцию imread(). Аргументом
функции указывают полное имя считываемого файла (аргумент заключается
в одинарные кавычки). Результатом вызова функции является трехмерный
массив растрового изображения файла. Обычно его присваивают в качестве
значения какой-нибудь переменной. Рассмотрим следующий код:
>> P=imread('F:\Книги\В работе\Matlab\Docs\tiger.jpg');
>> image(P)
Командой считывается файл tiger.jpg, расположенный в каталоге F:\
Книги\В работе\Matlab\Docs. Результат записывается в переменную
P. Командой image(P) считанное изображение отображается в графиче-
ском окне. Результат показан на рис. 2.56.
По умолчанию изображение масштабируется под размер графического
окна. В данном случае эффект искажения изображения не заметен, по-
скольку пропорции в исходном изображении близки к пропорциям графи-
ческого окна. Однако такое счастливое совпадение имеет место далеко не
всегда. Считаем другой файл с изображением:
>> B=imread('bee.jpg');
>> image(B)
>> axis image
В частности, считывается файл bee.jpg, размещенный в рабочем каталоге
Matlab (в этом случае аргументом функции imread() достаточно указать
только имя файла, без полного пути к нему). Результат выполнения первых
двух команд представлен на рис. 2.57.
Поскольку, в отличие от предыдущего случая, соотношение сторон для
рисунка далеко от единицы, при отображении рисунка возникает значи-
тельное, видимое на глаз, искажение пропорций. Устранить его можно, вос-
пользовавшись командой axis image. В результате окно с изображением
изменится так, как показано на рис. 2.58.
Глава 2. Графика в Matlab
101
Рис. 2 .56. Считанное из файла изображение
Рис. 2 .57. Изображение масштабировано под размер графического окна
Самоучитель Matlab
102
Рис. 2 .58. Изображение отображено в правильном масштабе
В соответствии с командой axis image масштабирование для рисунка
устанавливается в соответствии с его размерами (в пикселях).
Со считанным изображением можно работать так же, как и с созданным в ра-
бочем документе. Далее приведен пример кода, которым в считанном из фай-
ла изображении устанавливается "красный фильтр" - оставляется только со-
ставляющая красного цвета (жирным шрифтом выделен ввод пользователя).
>> [M N k]=size(B)
M=
1140
N=
2964
k=
3
>> for i=1:M
for j=1:N
B(i,j,2)=0;
B(i,j,3)=0;
end
end
>> image(B)
>> axis image
Глава 2. Графика в Matlab
103
После выполнения этих команд в графическом окне отображается картин-
ка, как на рис. 2.59.
Рис. 2 .59. Для изображения установлен "красный фильтр"
С помощью функции size() определяются размеры массива, указанного
аргументом функции. Результат функции – вектор из трех элементов. Пер-
вый элемент определяет количество пикселей в столбце, второй – в стро-
ке рисунка. Третий всегда равен трем (три составляющие цвета в формате
RGB). Поэтому после выполнения команды [M N k]=size(B) в перемен-
ную M записывается значение размера (в пикселях) по вертикали, а в пе-
ременную N записывается размер (в пикселях) по горизонтали. Затем
в двойном вложенном операторе цикла элементы массива B, отвечающие
содержанию зеленого и синего цвета, обнуляются.
104
Глава 3
Элементы программирования
Мы здесь по такому делу, в котором оши-
биться нельзя.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В режиме командного окна (то есть путем ввода и выполнения отдельных
команд в командном окне) можно решать многие задачи. Но на практике
такой подход не очень эффективный, особенно если необходимо выполнять
существенные объемы вычислений. Другими словами, важно иметь возмож-
ность выполнять быстро и просто определенные фрагменты кода, причем
весьма желательно вводить этот код один раз, а выполнять столько, сколько
нужно. Разумеется, такая возможность в Matlab есть. Базируется она на ис-
пользовании так называемых m-файлов. Это файлы с программным кодом,
или командами для выполнения, если хотите. В нужном месте и в нужное
время на соответствующий файл в командном окне выполняется ссылка,
и в результате весь код (то есть команды), записанный в соответствующий
файл, будет выполнен так, как если бы он вводился в командную строку при
пошаговых вычислениях. В подобных случаях говорят об использовании
сценариев. О них дальше и будет идти речь.
На заметку
Еще одна важная ветвь или направление в использовании m-файлов связана
с созданием функций пользователя. Хотя обе темы близки, при их практиче-
ском применении имеются некоторые особенности. Вопросу создания функций
пользователя посвящен второй раздел этой главы.
Создание сценариев
Пусть это будет естественный отбор, но
ускоренно и заботливо направляемый.
В. Черномырдин
В самом простом варианте сценарий в Matlab – это набор команд, занесен-
ных в файл с расширением .m. В принципе, для создания сценария можно
воспользоваться обычным текстовым редактором, набрать в нем код команд
по правилам синтаксиса Matlab и сохранить файл с расширением .m (толь-
ко нужно правильно выбрать каталог или прописать к нему путь, чтобы при
вызове сценария приложение могло найти соответствующий m-файл). Од-
нако удобнее воспользоваться встроенным редактором m-файлов, который
есть в Matlab.
Глава 3. Элементы программирования
105
В известном смысле сценарий – этот обычный набор команд, которые выпол-
няются одна за другой последовательно, как они указаны в файле. При вызо-
ве сценария его имя (точнее, имя соответствующего файла без расширения)
указывается в командной строке рабочей области. Эта аналогия становится
особенно уместной, если учесть, что в Matlab в сценариях не используются
локальные переменные. Другими словами, все переменные в сценариях гло-
бальные, поэтому доступны в пределах всего рабочего пространства: от непо-
средственно командной строки до любых других сценариев и функций.
На заметку
К последним, кстати, правило использования исключительно глобальных пере-
менных не относится – в функциях могут быть как глобальные, так и локальные
переменные.
Для создания m-файла достаточно выбрать команду File ► New ► M-File
в главном меню окна приложения Matlab. В результате открывается редак-
тор m-файлов, в рабочей области которого вводятся команды. На рис. 3.1
представлено окно редактора m-файлов с набором введенных туда команд.
Рис. 3.1. Окно редактора m-файлов с командами
Файл сохранен с названием SinX.m. Непосредственно в файле записаны
следующие команды:
x=-4*pi:0.01:4*pi;
y=sin(x)./x;
plot(x,y,'b-','LineWidth',2)
title('Plot for function y(x)=sin(x)/x')
xlabel('x')
ylabel('sin(x)/x')
grid on
Их последовательное выполнение в командном окне привело бы к созда-
нию графика функции
sin( )
()x
yx
x
=
на интервале значений аргумента
Самоучитель Matlab
106
44
x
ππ
−≤
≤ . При этом на графике отображается заголовок, подписи
у координатных осей и координатная сетка. Кривая отображается сплош-
ной линией синего цвета толщины 2. То же происходит, если в командной
строке рабочей области ввести и выполнить всего одну команду:
>> SinX
В результате создается график функции, представленный на рис. 3.2.
Рис. 3.2 . График функции создан в результате выполнения сценария
В том, что все использованные в сценарии переменные являются глобаль-
ными, достаточно легко убедиться. Для этого после команды вызова сцена-
рия в рабочей области проверяем значения первых элементов векторов x
и y, как показано на рис. 3.3.
Хотя ни вектор x, ни вектор y непосредственно в рабочей области не опре-
делялись, они здесь доступны и им присвоены значения – во время выпол-
нения сценария в соответствии с выполнявшимися при этом командами.
Ситуация может быть обратной: переменная объявляется в рабочей обла-
сти командами пользователя, а используется в сценарии. Правда, это уже
относится скорее к области экзотики. Тем не менее, в качестве иллюстрации
можем рассмотреть следующий пример. В файл с названием SinX2.m за-
писываем следующие команды:
Глава 3. Элементы программирования
107
b=abs(ans);
a=-b;
step=b/50;
x=a:step:b;
y=sin(x)./x;
plot(x,y,'r--o')
grid on
Окно редактора m-файлов с этим ко-
дом представлено на рис. 3.4.
В сценарии переменной b в качестве зна-
чения присваивается модуль системной
переменой ans (команда b=abs(ans)).
Переменной а командой a=-b присваи-
вается такое же по модулю, но отрица-
тельное значение, а переменная step по-
лучает значение step=b/50. Вектор x формируется командой x=a:step:b
и представляет собой набор узловых точек на симметричном интервале, а шаг
дискретности равен 1/100 от длины интервала. Вектор y формируется коман-
дой y=sin(x)./x и представляет собой набор значений рассматривавшейся
выше функции в узловых точках. Наконец, командой plot(x,y,'r--o')
строится график функции (красная штрихованная линия с маркерами в виде
кругов). Командой grid on на графике отображается координатная сетка.
После того, как m-файл с кодом сценария создан, в рабочей области выпол-
няем следующие команды (ввод пользователя выделен жирным шрифтом):
>> 8*pi
ans =
25.1327
>> SinX2
Рис. 3 .3. Все переменные в сценарии
являются глобальными
Рис. 3.4 . Окно редактора m-файлов с кодом сценария
Самоучитель Matlab
108
На рис. 3.5 представлено рабочее окно с введенными в него командами.
Рис. 3.5. Окно рабочей области с командами пользователя
После выполнения команды 8*pi значение получает системная перемен-
ная ans. Поэтому когда следующей командой SinX2 вызывается соответ-
ствующий сценарий, в результате его выполнения получаем график, как на
рис. 3.6.
Рис. 3.6. Результат выполнения команд и вызова сценария
В данном случае график строится для функции
sin( )
()x
yx
x
=
на интерва-
ле значений аргумента 88
x
ππ
−≤
≤ (в соответствии со значением сис-
темной переменной ans).
Глава 3. Элементы программирования
109
Образно выражаясь, в последнем примере в сценарий был передан свое-
образный аргумент – системная переменная ans. Это не очень удачный
способ передачи аргументов. Обычно в случае, если для выполнения кода
необходимо передать аргумент (или аргументы), определяют функцию
пользователя.
На заметку
Еще раз обращаем внимание читателя на тот факт, что все переменные в сце-
нарии глобальные. Например, в рассмотренном выше примере переменная
step, использованная в сценарии, переопределяет стандартную функцию
step(). Поэтому если после выполнения сценария ввести в командную стро-
ку имя step и выполнить команду, получим не подсказку по функции step(),
а значение переменной step.
Функции пользователя
Есть еще время сохранить лицо.
В. Черномырдин
Способ создания функции пользователя мало чем отличается от способа
создания сценария. С точки зрения кода одно из отличий состоит в том, что
код функции начинается с ключевого слова function. После этого клю-
чевого слова следует специального вида конструкция, в которой определя-
ется, во-первых, имя функции, во-вторых, ее аргументы, и, в-третьих, воз-
вращаемые функцией значения (их может быть несколько). Общий формат
заголовка функции такой:
function [результат1,результат2,...]=имя_функции(аргумент1,аргумент2,...)
После ключевого слова function в квадратных скобках перечисляются
переменные, в которые записываются результаты функции. Затем следует
оператор присваивания и имя функции. После имени функции в круглых
скобках через запятую перечисляются переменные - аргументы функ-
ции. Если результат у функции один, квадратные скобки можно не ис-
пользовать. Если функция результат не возвращает (может быть и такое),
переменные результата вообще не указываются: после ключевого слова
function следует имя функции и список аргументов. Для начала рассмо-
трим самый простой случай, когда у функции один аргумент и результат
она не возвращает. Редактор m-файлов с кодом такой функции представ-
лен на рис. 3.7.
Код у функции следующий:
function nums(n)
step=n/5;
0:step:n
Самоучитель Matlab
110
У функции nums() один аргумент, и она не возвращает результат. В резуль-
тате выполнения функции на экране появляется шесть числовых значений:
от 0 до значения аргумента функции n с равным интервалом изменения,
который определяется локальной переменной step=n/5. Здесь еще раз
подчеркнем, что все переменные, использованные в функции, являются ло-
кальными. Поэтому в данном случае переопределения встроенной функции
step() не происходит.
При сохранении m-файла с кодом функции его название должно совпадать
с именем функции. В данном случае функция записана в файл nums.m.
Результат использования созданной функции показан на рис. 3.8.
Рис. 3.8. Результат использования функции пользователя nums()
Рабочая область содержит такие команды и результат их выполнения (жир-
ным шрифтом выделены команды пользователя):
>> nums(10)
ans =
0
2
4
6
8
10
>> nums(-6.2)
ans =
0
-1.2400 -2.4800 -3.7200 -4.9600
-6.2000
Рис. 3.7 . Окно редактора m-файлов с кодом функции nums()
Глава 3. Элементы программирования
111
Практически так же легко определяется и функция, возвращающая резуль-
тат. Рассмотрим следующий программный код m-файла:
function y=Sinus(x)
y=sin(x)./x;
end
На рис. 3.9 представлен редактор m-файлов с кодом функции Sinus().
Рис. 3 .9. Окно редактора m-файлов с кодом функции Sinus()
В данном случае функция называется Sinus() и имеет один аргумент, ко-
торый в программном коде обозначен как x. Результат имеет название y
и вычисляется согласно соотношению y=sin(x)./x. Очевидно, что в дан-
ном случае речь идет о зависимости вида
sin( )
()x
yx
x
=
. Обращаем внима-
ние, что при делении использован оператор ./, что позволяет в качестве
аргумента использовать не только скаляр, но и матрицу (список значений
аргумента). Ниже приведен пример вызова созданной функции (жирным
шрифтом выделен ввод пользователя):
>> Sinus(pi/4)
ans =
0.9003
>> Sinus([pi/4 pi/3 pi/2 pi])
ans =
0.9003
0.8270
0.6366
0.0000
>> Sinus([pi/4 pi/3;pi/2 pi])
ans =
0.9003
0.8270
0.6366
0.0000
Видим, что результат одинаково хорошо вычисляется как для скалярного, так
и для матричного аргумента функции. При этом результатом является мас-
сив той же размерности, что и массив-аргумент. На рис. 3.10 показано окно
рабочего документа с результатом выполнения приведенных выше команд.
Еще раз обращаем внимание читателя: несмотря на то, что аргументом
функции может передаваться матрица, и такого же размера матрица воз-
Самоучитель Matlab
112
вращается как результат, у функции один аргумент и одно значение воз-
вращается в качестве результата – просто эти значения могут быть матри-
цами. Это принципиально отличная ситуация от случая, когда у функции
несколько аргументов и/или несколько значений возвращаются в качестве
результата. Пример такой функции приведен в документе на рис. 3.11.
Рис. 3.11 . Окно редактора m-файлов с кодом функции SpherCoords()
Окно редактора m-файлов содержит следующий код функции пользова-
теля:
function [x,y,z]=SpherCoords(r,phi,theta)
x=r*sin(theta)*cos(phi);
y=r*sin(theta)*sin(phi);
z=r*cos(theta);
end
Рис. 3.10. Результат использования функции пользователя Sinus()
Глава 3. Элементы программирования
113
В данном случае речь идет, очевидно, о функции для выполнения преоб-
разования сферических координат r , φ и θ в декартовые x , y и z по фор-
мулам
sin( ) cos( )
xr θφ
=
,
sin( ) sin( )
yr θφ
=
и
cos( )
zrθ
=
. Полярные ко-
ординаты точки передаются в качестве аргумента функции, а декартовые
координаты возвращаются в качестве результата. На рис. 3.12 приведен
пример использования функции SpherCoords() для выполнения преоб-
разования одних координат в другие.
Рис. 3.12. Пример использования функции SpherCoords()
Если при вызове функции ее результат записывается в скалярную перемен-
ную, как, например, в команде x=SpherCoords(1,pi/3,pi/4), то соответ-
ствующая переменная получит в качестве значения первый элемент из списка
результатов. В результате выполнения команды [x,y,z]=SpherCoords(1,
pi/3,pi/4) значения получают все три переменные, указанные в списке, ко-
торому присваивается значение.
В программных кодах m-файлов могут использоваться комментарии. Ком-
ментарий предназначен исключительно для программиста (или пользо-
вателя) и при обработке кода игнорируется. Начинается комментарий со
знака процента (то есть %). Все, что находится после знака процента, рас-
сматривается как комментарий.
Комментарий, размещенный в шапке (в заголовке) m-файла, несет дополни-
тельную функциональную нагрузку – он используется в качестве справки
Самоучитель Matlab
114
по программному коду (функции) этого m-файла. На рис. 3.13 окно редак-
тора m-файлов с кодом функции, у которой имеется комментарий в начале
программного кода.
Рис. 3.13. Окно с кодом функции и комментарием
В программном коде определена функциональная зависимость
exp() 1
()x
fx
x
−
=
. Функция называется mExp(), и программный код для
ее реализации (вместе с комментарием):
% В качестве значения для аргумента x функцией
% возвращается выражение (exp(x)-1)/x
function y=mExp(x)
y=(exp(x)-1)/x;
end
Для того чтобы получить справку по функции (в том числе и функции, соз-
данной пользователем), достаточно в командной строке ввести ключевое
слово help, после которого вводится имя функции, и с помощью клавиши
<Enter> соответствующая команда выполняется. На рис. 3.14 показан ре-
зультат применения этой процедуры по отношению к созданной функции.
Рис. 3 .14 . Справка для функции пользователя
Глава 3. Элементы программирования
115
После выполнения команды help mExp появляется следующее текстовое
сообщение:
В качестве значения для аргумента x функцией
возвращается выражение (exp(x)-1)/x
Несложно заметить, что это именно тот текст, что был введен в начале
m-файла с кодом функции mExp() в качестве комментария. При этом если
просто вызвать функцию с каким-то числовым аргументом, выводится зна-
чение функции для данного аргумента. Например, в результате выполнения
команды mExp(2) получаем числовое значение 3.1945 (см. рис. 3.14).
Нередко удобно или просто необходимо в процессе вычисления функции вво-
дить данные и выводить сообщения. Для ввода данных используется функ-
ция input(). Аргументом этой функции указывается текст приглашения,
которое выводится перед тем, как нужно будет ввести значение. Результатом
функции возвращается значение, введенное пользователем. На рис. 3.15 при-
ведено окно редактора m-файлов с кодом функции, при выполнении которой
пользователем вводится числовое значение для ее аргументов.
Рис. 3.15. В коде функции использована инструкция ввода значения
Программный код функции ComplPower() имеет следующий вид:
function z=ComplPower
Re=input('Действительная часть Re=');
Im=input('Мнимая часть Im=');
n=input('Целочисленная степень n=');
z=(Re+1i*Im)^n;
end
Функция предназначена для вычисления целочисленной степени комплексно-
го числа. У нее нет аргументов, а в качестве результата она возвращает комплекс-
ное число. Поскольку для вычисления результата необходимо знать три значе-
ния: действительную часть комплексного числа, мнимую часть комплексного
числа и степень, эти значения вводятся при выполнении функции. Для ввода
действительной части в программном коде функции ComplPower() исполь-
Самоучитель Matlab
116
зуется инструкция Re=input('Действительная часть Re='). В резуль-
тате ее выполнения в командной строке выводится текстовое сообщение Дей-
ствительная часть Re=, после чего пользователь должен ввести числовое
значение для действительной части возводимого в степень комплексного числа
и нажать клавишу <Enter>. В результате введенное пользователем значение
считывается и возвращается в качестве результата выполнения инструкции inp
ut('Действительная часть Re='). Этот результат, в соответствии с коман-
дой Re=input('Действительная часть Re='), записывается в перемен-
ную Re. Аналогично с помощью команд Im=input('Мнимая часть Im=')
и n=input('Целочисленная степень n=') считываются значения для
мнимой части комплексного числа и степени (соответственно, переменные Im
и n). Командой z=(Re+1i*Im)^n формируется результат и записывается в пе-
ременную z (которая указана в заголовке функции как переменная результата).
При этом мнимая единица в коде реализована в виде 1i.
Результат вычисления с помощью созданной функции выражения
4
(2 3)
119 120
ii
−=
−
+ показан на рис. 3.16.
Рис. 3.16. Вычисление степени комплексного числа
В приведенном далее коде жирным шрифтом выделен ввод пользователя:
>> ComplPower()
Действительная часть Re=2
Мнимая часть Im=-3
Целочисленная степень n=4
ans =
-1.1900e+002 +1.2000e+002i
На заметку
После ввода инструкции ComplPower() для вычисления соответствующей
функции последовательно выводятся текстовые сообщения, после которых не-
обходимо ввести нужное значение. Каждое следующее сообщение появляется
после ввода числа и нажатия клавиши <Enter>.
Глава 3. Элементы программирования
117
Вывод сообщений в процессе выполнения функции обычно осуществля-
ется с помощью функции disp(). Функция предназначена для вывода на
экран значений массива, переданного аргументом функции, или текстовой
строки. Особенность функции связана с тем, что выводятся только значе-
ния, без имени массива (если речь идет об аргументе-массиве). На рис. 3.17
показано окно редактора m-файлов с кодом функции, в которой использо-
вана встроенная функция disp() для вывода сообщений.
Рис. 3.17 . Функция с командами вывода на экран сообщений
Программный код функции mCos() приведен ниже:
function mCos(x)
disp('Вычисление функции f(x)=(1-cos(x))/x^2');
disp(['Аргумент x=',num2str(x)]);
z=(1-cos(x))/x^2;
disp(['Значение функции f(x)=',num2str(z)]);
end
Функцией по аргументу x вычисляется выражение
2
1c
o
s
()
x
x
−
,нокак
результат это значение не возвращается, а только отображается. Инте-
рес представляют команды, содержащие вызов функции disp(). В пер-
вом случае аргументом функции disp() передается текстовая стро-
ка 'Вычисление
функции
f(x)=(1-cos(x))/x^2'. Во втором
случае аргументом функции disp() передается массив из двух элемен-
тов ['Аргумент x=',num2str(x)]. Первый элемент массива – текст
'Аргумент x='. Второй элемент тоже текстовый. Он получается преоб-
разованием числового значения x (аргумент функции mCos()) в текст.
Делается это с помощью встроенной функции num2str(). Аналогичная
ситуация имеет место при вызове команды disp(['Значение функ-
ции f(x)=',num2str(z)]), только в этом случае к текстовому формату
преобразуется значение переменной z, которой предварительно присвоено
нужное значение. На рис. 3.18 приведен пример вызова функции mCos().
Самоучитель Matlab
118
Рис. 3.18. Результат вызова функции
После выполнения команды mCos(1) на экран выводятся следующие со-
общения:
Вычисление функции f(x)=(1-cos(x))/x^2
Аргумент x=1
Значение функции f(x)=0.4597
Кроме функции disp(), для вывода специальных сообщений используются
функции warning() и error(). В наиболее простом варианте аргументом
функции warning() передается текстовый аргумент, который и выводит-
ся на экран. При этом в текст сообщения автоматически добавляется слово
Warning. Выполнение функции, в которой выводится сообщение, при этом
не прекращается. В отличие от функции warning(), функция error() не
только выводит сообщение (текст, переданный аргументом функции), но
и завершает работу кода, в котором вызвана функция error(). Пример ис-
пользования функций warning() и error() приведен в следующем коде:
function ShowFunc
disp('Начало работы функции!');
warning('Предупреждение!');
error('Сообщение об ошибке!');
disp('Эта строка на экране не появится!');
end
Окно редактора m-файлов с кодом показано на рис. 3.19.
Рис. 3.19. Окно редактора m-файлов с кодом функции, выводящей сообщения на экран
Глава 3. Элементы программирования
119
Код функции фактически состоит из четырех инструкций по выводу на
экран сообщений. Первое сообщение выводится функцией disp(). Второе
сообщение выводится с помощью функции warning(). Третье сообщение
выводится функцией error(). Наконец, в коде использована еще одна
функция disp(), однако сообщение этой функцией выводиться не будет,
поскольку после выполнения инструкции с функцией error() выполне-
ние кода функции ShowFunc() будет прекращено. Результат вызова функ-
ции ShowFunc() представлен на рис. 3.20.
Рис. 3 .20. Результат вызова функции, выводящей сообщения на экран
На заметку
Обращаем внимание, что при выводе сообщений с помощью функций
warning() и error() не только добавляются дополнительные инструкции,
но еще и указывается (через гиперссылку) та строка кода, которая вызвала со-
ответствующее сообщение.
Управляющие инструкции
Полковник, забудьте про дворцовый этикет.
Все новости докладывать немедленно!
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Далее остановимся на управляющих инструкциях, которые могут исполь-
зоваться в программных кодах Matlab. Речь в первую очередь пойдет об
условных операторах и операторах цикла.
К условным операторам относят операторы if и оператор перебора switch.
Оба они используются для создания точек ветвления в программном коде,
когда в зависимости от выполнения некоторого условия (или условий) вы-
полняются разные фрагменты кода.
В наиболее простом варианте синтаксис вызова условного оператора if
имеет следующий вид:
Самоучитель Matlab
120
if условие
команды
end
После ключевого слова if указывается условие – выражение логического
типа. Обычно условия строятся на основе операций отношения. Особен-
ности реализации логического типа данных в Matlab (в том числе и логи-
ческие операторы) описываются далее в этой главе. Так вот, если условие
истинно, то выполняются команды после этого условия до ключевого слова
end. Эта инструкция является идентификатором окончания условного опе-
ратора. После этого управление передается оператору, следующему после
условного. Если условие истинным не является, управление сразу передает-
ся оператору, указанному после условного. Другими словами, при ложном
условии команды после условия и до ключевого слова end не выполняются.
Кроме рассмотренных выше инструкций, в условном операторе могут ис-
пользоваться ключевые слова else и elseif. Если синтаксис вызова
условного оператора имеет вид
if условие
команды_1
else
команды_2
end
то при истинном условии выполняются команды между условием и ключе-
вым словом else (то есть блок команды_1). Если условие ложно, выпол-
няются команды между ключевым словом else и инструкцией окончания
условного оператора end. Допускается и более сложный формат вызова
условного оператора:
if условие_1
команды_1
elseif условие_2
команды_2
elseif условие_3
команды_3
...
elseif условие_N
команды_N
else
команды_N+1
end
В этом случае сначала проверяется первое условие (условие_1 после клю-
чевого слова if). Если условие_1 истинно, выполняются команды после
этого условия и до первого ключевого слова elseif. Если условие лож-
но, проверяется условие_2 после первого ключевого слова elseif. При ис-
Глава 3. Элементы программирования
121
тинном условии выполняется блок команд до следующего ключевого слова
elseif. Если условие условие_2 ложно, проверяется условие_3, и так далее.
В случае, если ни одно из условий не выполнено, выполняются команды
после ключевого слова else. Далее приведен пример программного кода,
в котором используются условные операторы:
function y=MakeChoice(x)
if x<0
disp('Отрицательное значение аргумента!');
else
disp('Неотрицательное значение аргумента!');
end
disp('Вычисление значения функции:');
if x<-5
y=x+5;
elseif x<0
y=x*(x+5);
elseif x<7
y=x*(x-7);
else
y=x-7;
end
disp('Вычисление значения функции завершено!');
if y==0
disp('Значение функции равно нулю!');
end
end
Окно редактора m-файлов с этим кодом представлено на рис. 3.21.
Код функции MakeChoice() несколько искусственный и носит иллюстра-
тивный характер. Основу его составляют три условных оператора. В первом
из них проверяется условие x<0, где через x обозначен аргумент функции.
Условие x<0 является истинным, если аргумент функции меньше нуля.
В этом случае на экран выводится сообщение о том, что у функции отри-
цательный аргумент. В противном случае, то есть если условие x<0 ложно,
выводится сообщение о том, что аргумент неотрицательный.
В следующем условном операторе проверяется условие x<-5. Если это так,
то переменной y, которая предназначена для записи значения функции,
присваивается значение x+5. Если условие x<-5 не выполнено, проверя-
ется условие x<0. В этом случае выполняется команда y=x*(x+5). Если
же не выполнено и условие x<0, проверяется условие x<7. На этот случай,
то есть когда аргумент функции меньше семи (но не меньше нуля), преду-
смотрена команда y=x*(x-7). Если ни одно из перечисленных условий не
выполняется (аргумент функции больше либо равен семи), значение пере-
менной y определяется с помощью команды y=x-7.
Самоучитель Matlab
122
После того, как вычислено значение функции (присвоено значение пере-
менной y), выполняется еще один условный оператор, в котором прове-
ряется условие равенства нулю значения функции (условие y==0). Если
условие выполнено, выводится текстовое сообщение о том, что значение
функции нулевое. В противном случае никаких дополнительных действий
не предпринимается. Результат вызова функции MakeChoice() с разными
аргументами приведен на рис. 3.22.
На заметку
Стоит обратить внимание на второй условный оператор с несколькими прове-
ряемыми условиями. Особенность его состоит в том, что каждое следующее
условие проверяется только в том случае, если не выполнено ни одно из преды-
дущих условий.
Подобно условному оператору if, в котором проверяется серия условий,
с помощью оператора перебора switch выполняется проверка значения
переменной или выражения. Переменная указывается после ключевого
слова switch. Ключевое слово case используется для организации про-
граммных блоков, которые выполняются в зависимости от значения пере-
менной. Общий синтаксис вызова оператора перебора switch следующий:
Рис. 3 .21. Программный код функции MakeChoice() с использованием
условных операторов
Глава 3. Элементы программирования
123
switch выражение
case значение_1
команды_1
case значение_2
команды_2
...
case значение_N
команды_N
otherwise
команды_N+1
end
Рис. 3.22 . Результат вычисления функции MakeChoice() для разных аргументов
Самоучитель Matlab
124
Оператор выполняется по следующей схеме: вычисляется значение выра-
жения. Затем это значение последовательно сравнивается со значениями,
указанными в case-блоках (после ключевого слова case), до первого со-
впадения. Если совпадение найдено, выполняются команды в соответ-
ствующем case-блоке. Если совпадения не найдено, выполняется блок
команд, помеченный инструкцией otherwise. Последний блок (то есть
otherwise-блок) не является обязательным. Пример использования опе-
ратора перебора switch приведен ниже:
function y=MultiFunc(x,n)
switch n
case 1
y=x;
case 2
y=x*(10-x);
case {3,4,5}
y=x*sin(n*x);
otherwise
y=1/(1+x^2);
end
end
Кодом объявляется функция MultiFunc(), у которой два аргумента. При-
чем второй аргумент играет роль индикатора, который определяет тип
функциональной зависимости. Варианты перебираются с помощью опера-
тора switch. Значение функции записывается в переменную y. При еди-
ничном втором аргументе (переменная n) функции MultiFunc() значе-
ние переменной y определяется командой y=x в первом case-блоке (через
x обозначен первый аргумент функции). Если значение переменной n равно
2, выполняется команда y=x*(10-x). Если же второй аргумент функции
MultiFunc() равен 3, 4 или 5, значение функции вычисляется командой
y=x*sin(n*x).
На заметку
Обращаем внимание читателя, что в этом случае в качестве проверяемого
значения в соответствующем case-блоке указаны фигурные скобки с пере-
численными в них значениями 3, 4 и 5 (в качестве разделителя используется
запятая).
Наконец, если значение переменной n не совпадает ни с одним из перечис-
ленных выше значений, для определения значения функции выполняется
команда y=1/(1+x^2) (блок otherwise). На рис. 3.23 показано окно ре-
дактора m-файлов с кодом функции MultiFunc().
Глава 3. Элементы программирования
125
Рис. 3.23. Код функции с оператором перебора
Результат вызова функции MultiFunc() с разными аргументами приве-
ден на рис. 3.24.
Рис. 3.24. Результат вызова функции с оператором перебора
Самоучитель Matlab
126
Кроме условных операторов, имеются операторы цикла for и while. И тот,
и другой используются для выполнения последовательности однотипных
действий, однако синтаксис у них существенно отличается. В частности,
синтаксис вызова оператора цикла for имеет такой вид:
for переменная=значение_1:значение_2:значение_3
команды
end
После ключевого слова for указывается индексная переменная, для кото-
рой через знак равенства указывается начальное значение (значение_1),
шаг дискретности (значение_2) и конечное значение (значение_3). Началь-
ное значение, шаг дискретности и конечное значение разделяются двоето-
чиями. Шаг дискретности можно не указывать – в этом случае шаг дискрет-
ности единичный.
Выполняется оператор цикла for по следующей схеме: индексная пере-
менная последовательно, с установленным шагом дискретности, пробегает
значения от начального до конечного значений, и для каждого из этих зна-
чений индексной переменной выполняются команды, вплоть до ключевого
слова end, являющегося идентификатором окончания оператора цикла. Да-
лее приведен пример кода, в котором использован оператор цикла for для
вычисления суммы ряда:
function y=MyExp(x,n)
z=0;
q=1;
for i=0:n-1
z=z+q;
q=q*x/(i+1);
end
y=z+q;
end
Функцией MyExp() по двум ее аргументам (первый x и второй n ) вы-
числяется сумма
23
0
1.
.
.
2! 3!
!
!
n
nk
k
xx
x
x
x
nk
=
+++++=∑
, которая дает при-
ближенное значение для экспоненциальной зависимости
0
exp( )
!
k
k
x
x
k
∞
=
=
∑.
В коде функции объявляются две локальные переменные (переменная z
с начальным нулевым значением и переменная q с начальным единичным
значением), а основу кода составляет оператор цикла for. В операторе цик-
ла вводится индексная переменная i с начальным значением 0, конечным
значением n-1 (через переменную n обозначен второй аргумент функции
MyExp()). Шаг дискретности индексной переменной явно не задан, поэто-
Глава 3. Элементы программирования
127
му по умолчанию он равен единице. На каждом итерационном шаге в опе-
раторе цикла выполняется две команды: сначала значение переменной z
увеличивается на величину q (команда z=z+q), а затем командой q=q*x/
(i+1) текущее значение переменной q умножается на x (первый аргумент
функции MyExp()) и делится на увеличенное на единицу значение индекс-
ной переменной. В переменную z записывается сумма ряда, а каждое оче-
редное слагаемое ряда заносится в переменную q. Здесь использовано то
обстоятельство, что если на k-м шаге добавка рана
!
k
k
x
q
k
≡
, то на следу-
ющем, k+1-м шаге
1
1
(1
)
!
1
k
kk
xx
qq
kk
+
+≡=
⋅
++
. После выполнения опера-
тора цикла сумма вычислена с учетом слагаемого для значения индексной
переменной со значением n-1, а переменная q имеет значение добавки для
следующего итерационного шага. Этот шаг реализуется уже после операто-
ра цикла командой y=z+q, в результате чего переменная y получает нужное
значение. На рис. 3.25 показано окно редактора m-файлов с кодом функции
MyExp().
Рис. 3.25. Программный код функции с оператором цикла для вычисления экспоненты
Результат вычисления экспоненты для единичного первого аргумента (ар-
гумент в экспоненциальной зависимости) и различных значений второго
аргумента (верхний индекс суммы ряда) представлен на рис. 3.26.
Стоит отметить, что чем больше по абсолютной величине первый аргумент,
тем больше необходимо учитывать слагаемых при расчете экспоненты.
Синтаксис вызова оператора while такой:
while условие
команды
end
Самоучитель Matlab
128
После ключевого условия while указывается условие. Это условие прове-
ряется, и если оно истинно, выполняются команды, указанные после это-
го условия, вплоть до инструкции окончания оператора end. Затем снова
проверяется условие. Работа оператора while завершается, если условие
становится ложным. Отсюда следует, что команды в операторе while
должны быть такими, чтобы их выполнение на каком-то этапе приводило
к изменению значения условия, иначе цикл будет бесконечным. Хотя это
и необязательно: работа условных операторов и операторов цикла может
быть прервана с помощью инструкции break. Существует инструкция
и для досрочного завершения работы функции – это инструкция return.
На рис. 3.27 показано окно редактора m-файлов с кодом функции, в которой
использован оператор цикла while.
Рис. 3.27. Окно редактора m-файлов с кодом функции, в которой использован
оператор while
Код функции SqrAvr() приведен ниже:
Рис. 3.26. Результат вычисления экспоненты по разному числу слагаемых в ряде
Глава 3. Элементы программирования
129
function s=SqrAvr(n)
sum=0;
i=1;
while i<=n
sum=sum+i*i;
i=i+1;
end
s=sum/n;
end
У функции один аргумент (обозначен как n ), на основании которо-
го по формуле
2
1
1
n
k
k
n=
∑ вычисляется значение, возвращаемое функцией
в качестве результата. Сразу оговоримся, что имеет место соотношение
2
1
1
( 1)(2 1)
6
n
k
nn
k
n=
++
=
∑
, которое можно использовать для проверки кор-
ректности работы функции. Результат вызова функции приведен в доку-
менте на рис. 3.28.
Рис. 3.28. Результат вызова функции SqrAvr()
Легко видеть, что значение вычислено корректно. Что касается самого
программного кода, использованного для вычислений, то он достаточно
прост. Вначале объявляются локальные переменные sum (используется
для вычисления суммы квадратов натуральных чисел, начальное значение
равно 0) и i (индексная переменная с начальным значением 1). В опера-
торе цикла while проверяется условие i<=n (индексная переменная не
превышает значение аргумента n функции SqrAvr()). В теле оператора
цикла выполняется команда sum=sum+i*i, которой на величину квадрата
индексной переменной i увеличивается значение переменной sum, а затем
командой i=i+1 на единицу увеличивается значение индексной перемен-
ной. После завершения работы оператора цикла командой s=sum/n в пере-
менную s записывается значение функции SqrAvr().
Самоучитель Matlab
130
Логические значения и логические
операторы
Все выглядит очень логично, Штирлиц.
К/ф "Семнадцать мгновений весны"
Как уже упоминалось в первой главе книги, в Matlab в качестве логического
значения истина используется единица, а в качестве логического значения
ложь используется ноль. Другими словами, любое логическое выражение,
если оно истинно, интерпретируется как единица, а если ложно – как ноль.
Более того, если числовое значение употребляется в качестве логического
выражения, то ненулевое значение интерпретируется как истина, а нулевое
значение интерпретируется как ложь.
Особый интерес представляют возможные операции, которые применимы
к логическим значениям, а также способы получения и обработки логиче-
ских массивов. Начнем с логических операций, логических функций и ло-
гических операторов. Сюда же отнесем и операторы сравнения, которые
часто используются в логических выражениях.
На заметку
В первой главе мы кратко познакомились с логическими и условными операто-
рами. Здесь мы несколько расширим свои познания в этой области.
Некоторые операторы сравнения уже использовались нами ранее. Для
удобства список операторов сравнения приведен в табл. 3.1 вместе с встро-
енными функциями, используемыми для сравнения значений.
Табл. 3.1. Операторы сравнения
Оператор Функция
Описание
<
lt()
Меньше. Выражение A<B истинно, если значение перемен-
ной A меньше значения переменной B. Тот же результат мо-
жет быть получен с помощью команды lt(A,B)
>
gt()
Больше. Выражение A>B истинно, если значение перемен-
ной A больше значения переменной B. Тот же результат мо-
жет быть получен с помощью команды gt(A,B)
<=
le()
Меньше или равно. Выражение A<=B истинно, если значе-
ние переменной A не превышает значения переменной B.
Тот же результат может быть получен с помощью команды
le(A,B)
>=
ge()
Больше или равно. Выражение A>=B истинно, если зна-
чение переменной A не меньше значения переменной B.
Тот же результат может быть получен с помощью команды
ge(A,B)
Глава 3. Элементы программирования
131
Оператор Функция
Описание
==
eq()
Равно. Выражение A==B истинно, если значение перемен-
ной A равно значению переменной B. Тот же результат мо-
жет быть получен с помощью команды eq(A,B)
~=
ne()
Не равно. Выражение A~=B истинно, если значение пере-
менной A не равно значению переменной B. Тот же резуль-
тат может быть получен с помощью команды ne(A,B)
Выражения с операторами сравнения возвращают логические значения –
истинные выражения соответствуют единице, а ложные соответствуют
нулю. Если операции сравнения применяются к массивам, то в этом случае
речь идет о поэлементном сравнении элементов. Результатом является мас-
сив того же размера, что и исходные массивы, с нулями и единицами в за-
висимости от результата сравнения. Некоторые примеры использования
операторов сравнения приведены в документе на рис. 3.29.
Сначала переменным A и B присваиваются соответственно значения 5 и 9.
Затем командой C=A+2*(A<B) переменной C присваивается значение
(результатом переменная C получает значение 7). Объяснение простое:
поскольку выражение A<B является истинным, то значением этого выра-
жения фактически есть 1. После умножения на 2 и прибавления текущего
значения переменной A получаем 7.
Командами X=[1 2 5;5 4 -1] и Y=[-2 2
- 7;3 3 -1] задаются
числовые матрицы одинаковых размеров, после чего к этим матрицам при-
меняются операции сравнения. В частности, использована команда X==Y,
в результате выполнения которой создается матрица того же размера, что
и сравниваемые матрицы X и Y. Матрица-результат состоит из нулей и еди-
ниц. Это результаты сравнения соответствующих элементов матриц X и Y
(единица соответствует ситуации, когда соответствующие элементы, в со-
ответствии с использованным оператором == матриц совпадают, а нули
соответствуют ситуации, когда соответствующие элементы различны).
Если в качестве одного из операндов в операции сравнения указать вместо
матрицы скаляр (как, например, в команде A~=X), то скаляр сравнивается
с каждым из элементов матрицы-операнда. Результатом является матрица
из нулей и единиц того же размера, что и матрица-операнд. Принцип за-
полнения матрицы-результата такой: если результат сравнения скалярного
операнда и элемента матрицы-операнда истинен, в соответствующем месте
матрицы-результата стоит единица, в противном случае – нуль.
В Matlab есть ряд операторов (и дублирующих их функций) для работы с ло-
гическими выражениями. Они соответствуют базовым логическим операци-
ям, таким как логическое и, логическое или, логическое отрицание и прочие.
Основные логические операторы и функции Matlab представлены в табл. 3.2.
Самоучитель Matlab
132
Табл. 3.2. Логические операторы и функции
Оператор Функция
Описание
&
and() Логическое и. Результатом является единица, если оба опе-
ранда (или аргумента) равны единице
|
or()
Логическое или. Результатом является единица, если хотя
бы один операнд (или аргумент) равен единице
xor()
Логическое исключающее или. Результатом является еди-
ница, если один и только один операнд (или аргумент) равен
единице
Рис. 3.30. Логические операторы
и функции
Рис. 3.29. Использование операторов
сравнения
Глава 3. Элементы программирования
133
Оператор Функция
Описание
~
not()
Логическое отрицание. Если операнд (аргумент) равен еди-
нице, результатом будет ноль, и наоборот
&&
Логическое сокращенное и. Отличие состоит в способе вы-
числения результата. Если первый операнд нулевой, второй
операнд не вычисляется
||
Логическое сокращенное или. Отличие состоит в способе
вычисления результата. Если первый операнд единичный,
второй операнд не вычисляется
Для логических операторов и функций существуют побитовые аналоги – это
функции, которые выполняют соответствующие операции на битовом уров-
не, то есть операнды представляются в виде последовательности битов, и для
каждой пары битов выполняется нужная операция. Например, с помощью
функции bitor() операция логического или применяется на побитовом
уровне. Для вычисления исключающего побитового или используется функ-
ция bitxor(). Функцией bitand() вычисляется побитовое и. Полезными
могут быть и другие побитовые функции. Например, у функции bitget()
два числовых аргумента. В качестве результата возвращается значение бита
в первом аргументе на позиции, определяемой вторым аргументом. У функ-
ции bitset() два или три аргумента. Значение функции вычисляется сле-
дующим образом. В числе, указанном первым аргументом функции на по-
зиции, определяемой вторым аргументом, устанавливается значение бита,
указанное третьим аргументом функции. Если третий аргумент не указан, по
умолчанию он полагается равным единице. Некоторые примеры использова-
ния логических операторов и функций приведены в документе на рис. 3.30.
Логические операторы и функции широко используются в условных опера-
торах и операторах цикла при создании сложных условий.
Обработка исключительных ситуаций
Если мы будем предполагать невозможное,
тогда Вы ошиблись адресом.
К/ф "Семнадцать мгновений весны"
Хотя программные коды пишутся для того, чтобы они работали правильно
и быстро, нередко при выполнении программного кода возникают ошибки.
Речь идет в данном случае об ошибках времени выполнения, то есть тех ошиб-
ках, которые не связаны с некорректным синтаксисом, а, скорее, с алгоритмом
выполнения кода. Обычно такого рода ошибка, если речь идет о какой-нибудь
среде программирования, приводит к завершению работы программы. Прило-
жение Matlab в этом отношении намного демократичнее. Многие стандартные
ошибки, такие как деление на ноль, не являются фатальными, и код может вы-
Самоучитель Matlab
134
полняться и дальше. Как он будет выполняться – это уже другой вопрос. В лю-
бом случае, проблема остается – необходим механизм, позволяющий миними-
зировать влияние прогнозируемых или непрогнозируемых ошибок (которые
обычно называют исключениями или исключительными ситуациями). Такой
механизм в Matlab есть, и реализуется он с помощью оператора try-catch.
На заметку
Данная конструкция должна быть хорошо знакома программистам Java и C++.
Общий синтаксис оператора следующий:
try
основные_команды
catch объект_ошибки
команды_обработки
end
Программный код, подозреваемый на предмет непредсказуемого поведе-
ния, указывается в блоке try. Начало блока маркируется соответствую-
щим ключевым словом. Признаком окончания try-блока (и начала catch-
блока) является ключевое слово catch. Если при выполнении кода между
ключевыми словами try и catch никаких ошибок не возникает, команды
catch-блока игнорируются и далее выполняются команды, размещен-
ные после ключевого слова end, которым завершается catch-блок и, тем
самым, весь оператор try-catch. В случае если при выполнении команд
в try-блоке ошибка все-таки возникает, то выполнение команд try-блока
прекращается, и начинают выполняться команды catch-блока (вплоть до
ключевого слова end). После этого выполняются команды после операто-
ра try-catch. Таким образом, оператор try-catch в некотором смысле
представляет собой аналог условного оператора, только условием служит
возникновение ошибки. Если ошибки нет, выполняется только блок try.
Если ошибка возникает, выполняются команды catch-блока.
Непосредственно после ключевого слова catch может указываться пере-
менная, обозначающая объект ошибки.
На заметку
Дело в том, что при возникновении ошибочной ситуации (или исключения) авто-
матически создается объект класса MException. Этот объект содержит опи-
сание возникшей ошибки, и заложенная в объекте информация может исполь-
зоваться в программном коде при обработке ошибки. Именно для формального
обозначения данного объекта вводится соответствующая объектная переменная,
которая и указывается после ключевого слова catch. Однако если в коде обра-
ботки ошибочной ситуации обращение к объекту ошибки не планируется, после
ключевого слова catch соответствующую переменную можно не указывать.
Глава 3. Элементы программирования
135
Ниже приведен пример кода, содержащего обработку исключительных си-
туаций:
function ShowPlot(x,y)
try
plot(x,y,'LineWidth',2)
grid on
catch
disp('Неверно указаны аргументы функции!')
end
disp('Выполнение функции завершено!')
end
У функции два аргумента (массивы), на основе которых строится график
функции. Главная проблема состоит в том, что массивы могут иметь разные
размеры. Поскольку в функции это условие (равенство размеров массивов)
не проверяется, при вызове функции возможно возникновение ошибки.
Как раз для такого случая предусмотрена обработка исключительных си-
туаций. Команды по созданию графика функции заключены в блок try.
Если ошибки при построении графика не возникает, то после создания гра-
фика выводится сообщение 'Выполнение функции завершено!' (ар-
гумент функции disp()), после чего выполнение функции завершается.
При возникновении ошибки выполняются команды catch-блока (команда
disp('Неверно указаны аргументы функции!')), после чего вы-
полняется команда disp('Выполнение функции завершено!'). Окно
редактора m-файлов с кодом функции показано на рис. 3.31.
Рис. 3.31. Редактор m-файлов с кодом функции, содержащей обработку
исключительных ситуаций
На рис. 3.32 показано командное окно приложения с командами, иллюстри-
рующими работу созданной функции.
Самоучитель Matlab
136
Рис. 3.32. Команды с вызовом функции, содержащей обработку исключительной ситуации
Вот эти команды (жирным шрифтом выделены вводимые пользователем
команды):
>> x=-4*pi:0.01:4*pi;
>> y=(1-cos(x))./x;
>> z=0:0.02:4*pi;
>> ShowPlot(x,y)
Выполнение функции завершено!
>> ShowPlot(z,y)
Неверно указаны аргументы функции!
Выполнение функции завершено!
Первыми тремя командами создаются массивы x, y и z. Массив y создается
на основе массива x, и оба они имеют одинаковые размеры, чего не скажешь
о массиве z. Поэтому если график функции строится с помощью команды
ShowPlot(x,y), результатом является график функции (рис. 3.33).
После создания графика в командном окне выводится сообщение о завер-
шении выполнения функции. Если же попытаться выполнить команду
ShowPlot(z,y), возникнет ошибка, поскольку исходные массивы (аргу-
менты функции) имеют разные размеры. В этом случае при вычислении
функции ShowPlot() выполняется catch-блок, в результате чего появ-
ляется сообщение о неверно указанных аргументах функции. При этом код
функции продолжает выполняться, то есть экстренного завершения не про-
исходит. Это важно, и именно это является главной целью всего процесса
обработки исключительных ситуаций (ошибок).
Рассмотренная ситуация достаточно проста в том смысле, что можно прак-
тически безошибочно предугадать, какого типа ошибка может возникнуть
при вычислении функции. На практике это не всегда так и бывает важно
знать, что именно, какая причина, лежит в основе исключительной ситуа-
ции. Достоверную информацию о произошедшей ошибке содержит объект
исключения, который уже упоминался выше. Ниже приведен несколько
Глава 3. Элементы программирования
137
модифицированный программный код функции, которой строится график.
В частности, в блоке catch используется объектная переменная ME, кото-
рая обозначает создаваемый при возникновении ошибки объект.
function ShowPlot2(x,y)
try
plot(x,y,'LineWidth',2)
grid on
catch ME
disp(ME.message)
disp('Неверно указаны аргументы функции!')
end
disp('Выполнение функции завершено!')
end
На заметку
Объекты и классы – основа концепции любого объектно-ориентированного языка
программирования. По большему счету класс – это специальный шаблон, кото-
рый определяет способ группировки данных и функций для их обработки. Данные
называются свойствами класса, а функции – методами класса. Класс – это аб-
стракция. Хорошая аналогия для класса – чертеж автомобиля, например. По это-
му чертежу можно сделать один автомобиль, два, три и т.д . У каждого автомобиля
есть один и тот же набор свойств, как, например, цвет или тип обшивки. Значение
Рис. 3.33. Результат выполнения функции, если ее аргументы указаны корректно
Самоучитель Matlab
138
На заметку
этих свойств у разных автомобилей разное, но набор свойств один и тот же.
У автомобилей есть "методы": они могут ехать, сигналить, светить фарами. Если
чертеж – это класс, то автомобиль, созданный по чертежу, – экземпляр класса,
или объект.
Использованная в приведенном выше коде переменная ME обозначает
объект класса MException, то есть объект ошибки. У этого класса, кроме
прочего, имеется свойство message, которое содержит текстовое описа-
ние произошедшей ошибки. Другими словами, у каждого объекта класса
MException есть свойство message, но значение этого поля для каждо-
го объекта разное и зависит от типа возникшей ошибки. Этим свойством
мы и воспользовались для вывода информации о том, что же произошло.
В частности, чтобы узнать значение свойства message объекта ME, необхо-
димо указать имя объекта (объектной переменой) и, через точку, название
свойства, то есть ME.message. Именно эта инструкция указана аргументом
функции disp(). На рис. 3.34 показано окно с кодом функции с изменен-
ным кодом обработки исключительной ситуации.
Рис. 3 .34. Код функции содержит обработку исключительной ситуации с явным
обращением к объекту исключения
Результат обработки исключительной ситуации проиллюстрирован на рис. 3.35.
Рис. 3 .35. Результат обработки исключительной ситуации
Глава 3. Элементы программирования
139
При попытке выполнить команду ShowPlot2(z,y) в командном окне ото-
бражаются три сообщения:
Vectors must be the same lengths.
Неверно указаны аргументы функции!
Выполнение функции завершено!
Первое из трех сообщений, на английском языке, является следствием вы-
полнения команды ME.message. Оно подтверждает первоначальное пред-
положение о том, что причина ошибки в несоответствии размеров исходных
массивов – аргументов функции.
Функции с переменным числом
аргументов
Какое глубокое проникновение в суть вещей!
Впрочем, принц всегда тонко анализировал
самую сложную ситуацию.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В Matlab существует простой и элегантный способ создания функций, при-
нимающих произвольное количество аргументов. Необходимость в таких
функциях на практике достаточно велика. В качестве примера рассмотрим
следующую ситуацию. Представим, что необходимо создать функцию поль-
зователя, которая позволяет строить в одном графическом окне графики
сразу нескольких функций. Первым аргументом функции передается мас-
сив базовых точек для аргумента функций, а каждый следующий аргумент –
массив значений функции в базовых точках. Таким образом, количество ото-
бражаемых графиков на единицу меньше количества аргументов. Проблема
в том, что количество аргументов может меняться от вызова к вызову.
При описании функций с переменным количеством аргументов использует-
ся переменная varargin. Далее приведен код функции, в котором исполь-
зована эта переменная:
function MyPlots(varargin)
n=length(varargin);
if n<2
disp('Недостаточное количество аргументов!')
else
x=varargin{1};
y=varargin{2};
plot(x,y,'LineWidth',1,'Color','red')
grid on
hold on
Самоучитель Matlab
140
colors=['b' 'g' 'r'];
for i=3:n
y=varargin{i};
plot(x,y,'LineWidth',1+mod(i,2),'Color',colors(mod(i,3)+1))
end
hold off
end
end
Переменная varargin указана единственным аргументом функции MyPlots.
Первой командой n=length(varargin) в теле функции вычисляется количе-
ство аргументов, переданных функции. Это значение записывается в перемен-
ную n. Далее с помощью условного оператора проверяется ситуация, когда коли-
чество аргументов меньше двух: в этом случае выводится сообщение о том, что
функции передано недостаточное количество аргументов. В противном случае
выполняются команды, предназначенные для создания графики. Первый график
создается, что называется, в явном виде. Для этого командами x=varargin{1}
и y=varargin{2} из списка аргументов varargin считываются первый и вто-
рой массивы и записываются соответственно в переменные x и y. Обращаем
внимание читателя, что индексация элементов в данном случае выполняется
с помощью фигурных скобок. Дело в том, что переменная varargin представ-
ляет собой массив ячеек. Массивы ячеек предназначены для хранения элементов
разного типа. Доступ к элементам таких массивов осуществляется с помощью
фигурных скобок: после имени массива ячеек в фигурных скобках указывается
номер элемента (ячейки). Именно такой подход использован в данном случае.
Так, первый элемент переменной-массива varargin возвращается инструкци-
ей varargin{1}, второй – инструкцией varargin{2}, и так далее.
На заметку
Некоторую полезную информацию о массивах ячеек читатель может найти
в Приложении Б.
Командой plot(x,y,'LineWidth',1,'Color','red') создается пер-
вый график. Координатная сетка устанавливается командой grid on. Что-
бы следующий график отображался в том же графическом окне, используем
команду hold on. Кроме этого, командой colors=['b' 'g' 'r'] соз-
дается массив из трех элементов с буквенными значениями (буквы заклю-
чаются в одинарные кавычки) для последующего использования в качестве
идентификаторов цвета кривых для разных графиков.
Все прочие графики создаются в теле оператора цикла, в котором индексная
переменная i пробегает значения от 3 до n (с шагом единица по умолчанию).
Командой y=varargin{i} считывается массив значений функции для оче-
редного графика, а сам график создается командой plot(x,y,'LineWidth',
Глава 3. Элементы программирования
141
1+mod(i,2),'Color',colors(mod(i,3)+1)). Здесь дважды использо-
вана функция mod(), у которой два аргумента, а в качестве результата возвра-
щается остаток от деления первого аргумента на второй. Поэтому результатом
инструкции 1+mod(i,2) является значение 1 для четных значений пере-
менной i и 2 для нечетных. В результате графики по очереди отображаются
тонкой и толстой кривыми. Значением выражения mod(i,3)+1 являются
числа 1, 2 и 3, поэтому инструкцией colors(mod(i,3)+1) осуществляется
циклический перебор элементов массива colors. Наконец, после создания
всех графиков инструкцией hold off отменяется режим отображения гра-
фиков в одном окне. На рис. 3.36 показано окно редактора m-файлов с кодом
рассмотренной выше функции.
Рис. 3.36. Код функции с переменным числом аргументов в окне редактора m-файлов
Пример вызова созданной функции представлен в командном окне на
рис. 3.37.
Сначала создается базовый массив со значениями аргумента, а затем еще че-
тыре массива со значениями различных функций в этих точках. Следующие
три команды представляют собой вызов функции с одним, пятью и тремя ар-
гументами (жирным шрифтом выделены команды, вводимые пользователем):
>> x=-2*pi:0.01:2*pi;
>> y1=sin(x);
>> y2=cos(x);
>> y3=sin(x)./x;
Самоучитель Matlab
142
>> y4=(1-cos(x))./x;
>> MyPlots(x)
Недостаточное количество аргументов!
>> MyPlots(x,y1,y2,y3,y4)
>> MyPlots(x,y1,y2)
При вызове функции с одним аргументом появляется сообщение о недо-
статочном количестве аргументов. Результат вызова функции с пятью аргу-
ментами показан на рис. 3.38.
Рис. 3 .38. Результат вызова функции с пятью аргументами
Рис. 3.37. Вызов функции с разным количеством аргументов в командном окне
Глава 3. Элементы программирования
143
Если вызвать функцию с тремя аргументами, получим результат, как на рис. 3.39.
Рис. 3 .39. Результат вызова функции с тремя аргументами
На заметку
Отметим, что если вызвать функцию MyPlots() с двумя аргументами, будет
построен лишь один график, поскольку в теле оператора цикла нижняя граница
диапазона изменения индексной переменной превышает верхнюю, и поэтому
оператор цикла не выполняется.
Точно так же, как функция может иметь произвольное количество аргумен-
тов, она может возвращать и произвольное количество значений в качестве
результата. В этом случае в качестве результата функции указывается пере-
менная varargout. Как и переменная varargin, переменная varargout
является массивом ячеек, каждая из которых содержит возвращаемый
функцией результат. Ниже приведен пример функции, которая называется
moments() и может возвращать произвольное количество значений в ка-
честве результата:
function [varargout] = moments(x)
for k=1:nargout
y=x.^k;
varargout{k}=sum(y)/length(x);
end
end
Самоучитель Matlab
144
Предполагается, что функции аргументом передается массив числовых зна-
чений. В качестве значений функцией возвращаются статистические (или
выборочные) моменты. Здесь имеет смысл отметить, что статистическим
(выборочным) моментом порядка k по выборке (множеству значений) 1
x,
2
x ,...,
n
x называется число
1
1
n
k
ki
i
mx
n=
=
∑ . Таким образом, момент первого
порядка представляет собой среднее арифметическое. В данном случае ко-
личество вычисляемых моментов определяется тем, сколько переменных
содержит массив результата. На рис. 3.40 показан редактор m-файлов с ко-
дом функции.
Рис. 3.40. Программный код функции в окне редактора m-файлов
На рис. 3.41 показано командное окно с примером использования функции
moments().
Рис. 3.41 . Пример использования функции moments()
Глава 3. Элементы программирования
145
Здесь с помощью команд (жирным шрифтом выделен ввод пользователя)
>> x=[1,2,5,-3,-2,0,2,1,-1,3];
>> [m1,m2,m3]=moments(x)
m1=
0.8000
m2=
5.8000
m3=
13.4000
сначала создается числовой массив x, а затем на его основе вычисляются
моменты от первого до третьего порядка включительно. Результат записы-
вается соответственно в переменные m1, m2 и m3.
Функции eval () и feval ()
Софистика, пастор, софистика!
К/ф "Семнадцать мгновений весны"
Полезными при составлении программных кодов в Matlab могут оказаться сис-
темные функции eval() и feval(). У функций есть несколько вариантов ис-
пользования. Здесь рассмотрим самый распространенный. Начнем с функции
eval(). Функции передается текстовый аргумент, представляющий собой
команду, которую необходимо выполнить. Обратимся к документу на рис. 3.42.
Рис. 3.42. Использование функции eval()
Фрагмент кода следующий:
>> eval('x=[1,2,3,4,5]')
x=
1
2
3
4
5
Самоучитель Matlab
146
>> eval('y=sin(pi./x)')
y=
0.0000
1.0000
0.8660
0.7071
0.5878
При выполнении команды eval('x=[1,2,3,4,5]') результат такой
же, как если бы выполнялась команда x=[1,2,3,4,5]. А при выполне-
нии команды eval('y=sin(pi./x)'), как если бы выполнялась коман-
да y=sin(pi./x). В качестве иллюстрации полезности функции eval()
рассмотрим следующий пример (жирным шрифтом выделен ввод пользо-
вателя):
>> A=[1,2,3;4,5,6;7,8,9];
>> for i=1:3
for j=1:3
str=['a',int2str(i),int2str(j),'=A(i,j);'];
eval(str);
end
end
>> [a11,a12,a13;a21,a22,a23;a31,a32,a33]
ans =
1
2
3
4
5
6
7
8
9
Командой A=[1,2,3;4,5,6;7,8,9] создается матрица A размерами
3×3, заполненная натуральными числами от 1 до 9 включительно. Затем
выполняется двойной оператор цикла, в котором индексные переменные
i и j пробегают значения от 1 до 3 каждая. Внутри тела циклов выполня-
ется по две команды. Командой str=['a',int2str(i),int2str(j),
'=A(i,j);'] формируется текстовая строка str, которая получается
объединением нескольких фрагментов. Первый фрагмент – буква 'a'.
Два других фрагмента получаются преобразованием индексных пере-
менных к текстовому формату. Для преобразования числа в текст ис-
пользуем встроенную функцию int2str(). Еще один фрагмент – текст
'=A(i,j);'. Обращаем внимание, что в конце текстового фрагмента на-
ходится точка с запятой. Это сделано для того, чтобы при выполнении со-
ответствующей команды результат не отображался. Таким образом, пере-
менная str содержит текст, который получается объединением буквы a,
текущих значений индексов, оператора присваивания, элемента матрицы
A с соответствующими индексами и точки с запятой. Для выполнения
ко манды, представленной этой текстовой строкой, используем инструк-
цию eval(str). В результате элементы матрицы A записываются в пере-
менные a11, a12 и так далее до a33. То есть фактически здесь с помощью
функции eval() мы автоматизировали процедуру присваивания зна-
чений этим переменным вместо того, чтобы выполнять каждую команду
Глава 3. Элементы программирования
147
присваивания в явном виде. На рис. 3.43 показан документ с описанным
выше кодом.
Рис. 3.43. Еще один пример использования функции eval()
Функция feval() используется для непрямого вызова других функций.
Первым аргументом функции feval() передается указатель вызываемой
функции или ее текстовое имя, а прочие аргументы функции feval() –
это те аргументы, которые передаются неявно вызываемой функции. При-
меры использования этой функции приведены в документе на рис. 3.44.
Рис. 3.44 . Примеры использования функции feval()
Самоучитель Matlab
148
Здесь мы последовательно использовали команды feval('sin',pi/6)
и feval(@sin,pi/6), которыми вычисляется один и тот же результат.
В последнем случае для получения указателя на функцию вычисления си-
нуса задействован оператор @ перед именем функции (вся инструкция для
указателя на функцию вычисления синуса имеет вид @sin).
На заметку
Здесь мы воспользовались общим правилом получения указателя на функцию.
Для этого перед именем функции указывают оператор @. Результатом такой ин-
струкции является указатель на соответствующую функцию.
149
Глава 4
Элементы матричной алгебры
Мы столкнулись с трудной задачей... Надо
придумать что-то необычное.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В этой главе мы рассмотрим основные приемы, методы, функции, которые
полезны при решении задач линейной алгебры. Интриги прибавляет то об-
стоятельство, что данные в Matlab, так сказать, по умолчанию, реализуются
в виде матриц, что дает небезосновательные надежды на эффективное при-
менение Matlab в данном случае.
Векторы и операции с ними
Никто нам не мешает перевыполнить наши
законы.
В. Черномырдин
С точки зрения технической реализации вектор в Matlab – это матрица,
состоящая из одной строки (вектор-строка) или одного столбца (вектор-
столбец). Здесь мы рассмотрим методы выполнения некоторых базовых
операций с векторами – например, вычисление скалярного и векторного
произведений (разумеется, с использованием средств Matlab). Для соответ-
ствующих операций в Matlab предусмотрены специальные функции, хотя
при желании можно обойтись и без них.
На заметку
Следует понимать, что обсуждаемые далее функции описаны в контексте тех
задач, для решения которых они применяются. В общем случае функции, как
правило, имеют более широкое применение.
С практической точки зрения наибольший интерес представляют векторы
в двумерном (на плоскости) и трехмерном (в объеме) пространстве. Именно
последним случаем и ограничимся. Другими словами, здесь и далее будем
рассматривать трехмерные векторы. Начнем с операции вычисления моду-
ля вектора. По определению модулем вектора a с компонентами 12 3
(,,)
aaa
называется число
222
123
||
a aaa
=+
+. Особой проблемы в том, чтобы вы-
числить такое значение, нет. Но в Matlab для этих целей имеется специаль-
ная функция norm(). Аргументом функции указывается вектор, для кото-
рого вычисляется модуль. Результатом функции, как несложно догадаться,
является модуль вектора. Пример вычисления модулей для векторов-строк
и векторов-столбцов приведен в документе на рис. 4.1.
Самоучитель Matlab
150
Рис. 4 .1. Вычисление модуля вектора
В командном окне вводится и выполняется следующий код (жирным
шрифтом выделен ввод пользователя):
>>a=[135]
a=
1
3
5
>> norm(a)
ans =
5.9161
>> b=[1;3;5]
b=
1
3
5
>> norm(b)
ans =
5.9161
Видим, что результат одинаково хорош как для вектора-строки, так и для
вектора-столбца.
Глава 4. Элементы матричной алгебры
151
На заметку
Скалярным произведением векторов
123
(,,)
aa
a
a
=
и
123
(,,)
bb
b
b
=
называ-
ется число
11
22
33
abababab
⋅=
++.
На заметку
Строго говоря, для вычисления скалярного произведения первый вектор дол-
жен быть вектором-строкой, а второй – вектором-столбцом. Мы от таких тонко-
стей абстрагируемся.
Вычислить скалярное произведение можно с помощью функции dot().
Аргументы функции – векторы, для которых вычисляется скалярное про-
изведение. Примеры приведены в документе на рис. 4.2.
Рис. 4 .2 . Вычисление скалярного произведения
Операция вычисления скалярного произведения коммутативна – аргумен-
ты функции dot() можно указывать в произвольном порядке. Здесь мы
использовали такой код:
>> a=[1 -2 3];
>> b=[3;1;-1];
>> dot(a,b)
Самоучитель Matlab
152
ans =
-
2
>> dot(b,a)
ans =
-
2
>> dot(a,a)
ans =
14
>> dot(b,b)
ans =
11
Стоит обратить внимание на два обстоятельства. Во-первых, один из век-
торов является строкой, а второй – столбцом. Вне зависимости от того, как
передаются эти векторы аргументами функции dot(), результат вычис-
ляется один и тот же. Во-вторых, если вычислить скалярное произведение
вектора на себя же, получим квадрат модуля этого вектора.
Достаточно просто скалярное произведение вычисляется и без использова-
ния функции dot().
Рис. 4 .3. Альтернативный способ вычисления скалярного произведения
Соответствующий программный код приведен ниже:
Глава 4. Элементы матричной алгебры
153
>> a*b
ans =
-
2
>> sum(a.*a)
ans =
14
>> a*a'
ans =
14
>> sum(b.*b)
ans =
11
Так, значение переменной a есть вектор-строка, а значением переменной
b является вектор-столбец. Скалярное произведение можно вычислить
командой a*b. Здесь, фактически, речь идет о произведении двух матриц
(см. далее). В соответствии с правилом вычисления произведения матриц
принципиально важно, чтобы количество столбцов первой матрицы равня-
лось количеству строк второй матрицы. В отношении векторов это означа-
ет, что первый вектор - это вектор-строка, а второй – вектор-столбец.
В результате выполнения команды a.*a получаем массив, элементы кото-
рого равны попарным произведениям соответствующих элементов первого
и второго вектора, то есть квадратам элементов вектора a. Чтобы получить
скалярное произведение (квадрат модуля вектора), используем функцию
sum(). Другой способ получить тот же результат – воспользоваться коман-
дой a*a'. Здесь мы командой a' транспонировали вектор-строку, получив
в результате вектор-столбец. Поэтому мы этот вектор можем умножить
(указав его вторым в произведении) на вектор-строку a.
Команда sum(b.*b) вычисляется по тому же принципу, что и команда
sum(a.*a), только теперь речь идет о векторах-столбцах.
Еще одна важная операция, которую достаточно часто приходится выпол-
нять, связана с вычислением векторного произведения.
На заметку
Векторным произведением двух векторов a и b является вектор cab
=×,
элементы которого вычисляются по следующему правилу. Если векторы
123
(,,)
aa
a
a
=
и
123
(,,)
bb
b
b
=
, то компоненты вектора
123
(,,)
cc
c
c
=
вы-
числяются как
12
21
kkk kk
cab ab
++
++
=−
.
Индексы k пробегают значения 1,
2 и 3, причем имеет место циклическая "перестановка" индекса. То есть, напри-
мер, если
3
k=
, то формальное значение
14
k += следует заменить на 1,
а значение
25
k += следует заменить на 2.
Самоучитель Matlab
154
Векторное произведение вычисляется с помощью функции cross(). Ар-
гументами указываются векторы, для которых вычисляется векторное про-
изведение. Векторы могут быть как строками, так и столбцами. Если среди
аргументов есть вектор-строка, то результатом также будет вектор-строка.
Если оба вектора являются столбцами, то результатом будет вектор-столбец.
Примеры вызова функции cross() приведены в документе на рис. 4.4.
Рис. 4 .4 . Вычисление векторного произведения
Для удобства ниже приведен соответствующий программный код (жирным
шрифтом выделен ввод пользователя):
>> a=[-1 2 1];
>> b=[2 -1 3];
>> cross(a,b)
ans =
75-3
>> cross(a',b)
ans =
75-3
Глава 4. Элементы матричной алгебры
155
>> cross(a,b')
ans =
75-3
>> cross(a',b')
ans =
7
5
-
3
Думается, что особых комментариев этот код не требует. Единственное, на
что стоит обратить внимание, – это то, что векторное произведение анти-
коммутативно, то есть ba ab
×=
−
×.
На заметку
Есть еще такие тривиальные операции, как умножение/деление вектора на
число или вычисление суммы/разности векторов. В этом случае правила до-
статочно простые. При умножении/делении вектора на число с помощью со-
ответственно оператора * или / операция выполняется с каждым элементом
вектора, то есть в соответствии с правилом умножения/деления вектора на чис-
ло. Складываются и вычитаются векторы посредством операторов + и -. В этом
случае необходимо, чтобы векторы-операнды имели одинаковый размер и были
одного типа (оба векторы-столбцы или векторы-строки).
Операции с матрицами
-
Эти сведения недорого стоят.
-
Ну, какие есть.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Среди наиболее важных задач, относящихся к работе с матрицами, можно
выделить такие: вычисление детерминанта (определителя) матрицы, вы-
числение собственных значений и собственных векторов матрицы, обраще-
ние матрицы (вычисление обратной матрицы), транспонирование матри-
цы, умножение матриц, вычисление функций с матричными аргументами.
Рассмотрим, как эти задачи решаются средствами Matlab. Начнем с произ-
ведения матриц.
Для вычисления произведения матриц используется стандартный оператор
произведения *. Если операндами этого бинарного оператора являются ма-
трицы, то произведение вычисляется по правилам вычисления матрично-
го произведения. Необходимым условием является равенство количества
столбцов первой матрицы и строк второй. Это автоматически означает, что
произведение можно вычислить далеко не для всех матриц. Часто прихо-
дится иметь дело с квадратными матрицами, у которых количество строк
равняется количеству столбцов. В этом случае можно множить матрицы
Самоучитель Matlab
156
одинаковых размеров. Так, если ˆ
Aиˆ
B – квадратные матрицы одного раз-
мера, то можно вычислить и произведение ˆ ˆ
AB
⋅
, и произведение
ˆ
ˆ
BA
⋅
,но
результат вычислений в общем случае различный. То есть свойством ком-
мутативности матричное произведение не обладает.
На заметку
Если матрица ˆ
Aсостоит из элементов ik
a (индексы
1, 2, ..,
im
=
и
1, 2, ...,
kp
=
),
а матрица ˆ
B состоит из элементов kj
b (индексы
1, 2, ...,
kp
=
и
1, 2, ...,
jn
=
),
то элементы матрицы
ˆ
ˆ
CAB
=⋅
ˆ
вычисляются как
1
p
ij
ik kj
k
ca
b
=
=
∑,при
условии, что индексы принимают значения
1, 2, ..,
im
=
и
1, 2, ...,
jn
=
.
В результате матричного произведения получаем матрицу. Количество
строк матрицы определяется количеством строк в первой матрице. Количе-
ство столбцов определяется количеством столбцов во второй матрице.
На заметку
Поэтому при вычислении произведения вектора-строки на вектор-столбец по-
лучаем скаляр: это матрица, которая состоит из одной строки одного столбца.
Пример вычисления матричного произведения приведен в документе на
рис. 4.5.
В командном окне представлен такой код (жирным шрифтом выделен ввод
пользователя):
>>A=[1-23-1;0-212;-2110]
A=
1-2
3-1
0-2
1
2
-2
1
1
0
>> B=[1 2;-2 1;0 -1;1 0]
B=
1
2
-2
1
0-1
1
0
>> C=A*B
C=
4-3
6-3
-4
-4
Исходные матрицы имеют размеры 3×4 и 4×2, поэтому матрица-результат
имеет размер 3×2.
Глава 4. Элементы матричной алгебры
157
На заметку
Результатом произведения двух квадратных матриц размера nn
× является
квадратная матрица размера nn
×.
Достаточно тривиальной является процедура транспонирования матрицы.
При транспонировании матрица-результат получается из исходной матри-
цы взаимной заменой строк и столбцов: первая строка исходной матрицы
становится первым столбцом матрицы-результата, вторая строка исходной
матрицы становится вторым столбцом матрицы-результата и так далее.
В Matlab для выполнения операции транспонирования используется опе-
ратор .' (или оператор ' для действительных матриц).
На заметку
Оператор ' используется для вычисления сопряженной матрицы, которая по-
лучается из исходной транспонированием и комплексным сопряжением ее эле-
ментов. Поскольку мы будем использовать в основном матрицы действитель-
ные, то процедура сопряжения совпадает с процедурой транспонирования.
Вообще же для транспонирования используется составной оператор .'.
Рис. 4 .5 . Произведение матриц
Самоучитель Matlab
158
Если к матрице C из предыдущего примера, где вычислялось матричное
произведение, применить процедуру транспонирования, получим резуль-
тат, как на рис. 4.6.
Рис. 4.6. Транспонирование матрицы
Для вычисления суммы или разности матриц они должны быть одинако-
вого размера. При умножении или делении матрицы на число эта операция
применяется к каждому элементу матрицы. В качестве иллюстрации рас-
смотрим такой код:
>> A=[1 2 3;-2
-1 0]
A=
1
2
3
-2
-1
0
>>B=[0-12;1-12]
B=
0-1
2
1-1
2
>> C=2*A-3*B
C=
2
7
0
-7
1-6
Этим кодом вычисляется линейная
комбинация матриц
ˆ
ˆ
23
CAB
=−
ˆ
.
Результат получается так. Каждый
элемент матрицы ˆ
A умножается на
2. От элементов полученной матри-
цы отнимаются соответствующие
элементы матрицы ˆ
B, предвари-
тельно умноженные на 3 (рис. 4.7).
Определитель, или детерминант,
вычисляется только для квадрат-
Рис. 4 .7. Линейная комбинация матриц
Глава 4. Элементы матричной алгебры
159
ных матриц. Это число. Методику его вычисления проще всего описать через
рекурсивную процедуру. Так, для матрицы размерами 2×2 детерминант вы-
числяется как разность произведений диагональных и недиагональных эле-
ментов. Другими словами, если матрица
11
12
21
22
ˆ
aa
A
aa
⎛⎞
⎟
⎜
⎟
=⎜
⎟
⎜
⎟⎟
⎜⎝⎠
, то ее детерминант
вычисляется как
11 22
12 21
ˆ
det( )Aaa aa
=−
. Для квадратных матриц размера
nn
×(
2
n > ) детерминант вычисляется так:
1
ˆ
det( )
(1)
n
ij
ij ij
j
Aa
M
+
=
=−
∑
, где
индексi -любойвпределахот1доn,ачерез ij
M обозначен дополнитель-
ный к элементу ij
a минор – определитель матрицы размера (1
)(1
)
nn
−×
−,
которая получается из исходной матрицы вычеркиванием i -й строки
и j -го столбца. Уже отсюда совершенно очевидно, что вычислять детерми-
нант матрицы лучше с помощью специальных, предназначенных для этой
цели, функций, которые в Matlab, к счастью, имеются. В частности, детер-
минант вычисляется с помощью функции det(). Аргументом функции
указывается матрица, для которой вычисляется детерминант. Пример вы-
числения детерминанта матрицы приведен в документе на рис. 4.8.
Рис. 4 .8. Вычисление детерминанта матрицы
Если детерминант матрицы отличен от нуля, такая матрица называет-
ся невырожденной. Для невырожденной матрицы может быть вычислена
обратная матрица. По определению обратной к невырожденной матрице
ˆ
A называется такая матрица (обычно обозначается
1
ˆ
A− ), которая, будучи
умноженной на матрицу ˆA, дает единичную матрицу (по диагонали едини-
цы, а все прочие элементы равны нулю). Для вычисления обратной матри-
Самоучитель Matlab
160
цы в Matlab используется функция inv(), аргументом которой указывает-
ся матрица, для которой нужно вычислить обратную. Пример вычисления
обратной матрицы приведен в документе на рис. 4.9.
Рис. 4 .9. Вычисление обратной матрицы
Мы использовали такую последовательность команд (жирным шрифтом
выделен ввод пользователя):
>>A=[121;-101;2-11]
A=
1
2
1
-1
0
1
2-1
1
>> B=inv(A)
B=
0.1250 -0.3750
0.2500
0.3750 -0.1250 -0.2500
0.1250
0.6250
0.2500
>> A*B
ans =
1
0
0
0
1
0
0
0
1
Глава 4. Элементы матричной алгебры
161
Сначала создаем командой A=[1 2 1;-1 0 1;2 -1 1] матрицу, для которой
затем вычисляем обратную матрицу. Используем команду B=inv(A), с по-
мощью которой вычисляем обратную матрицу и результат записываем в пе-
ременную B. Свойства обратной матрицы проверяем, вычислив произведение
A*B. В результате, как и следовало ожидать, получаем единичную матрицу.
При работе с матрицами часто приходится решать задачу о вычислении
собственных чисел и собственных векторов матрицы. Собственные числа
λ матрицы ˆ
A получаются как решение уравнения
ˆ
ˆ
det(
)0
AE
λ
−=
.
Соб-
ственным вектором, который соответствует собственному числу λ матрицы
ˆ
A, называется такой ненулевой вектор ξ , при котором уравнение ˆ
Aξλ
ξ
=
имеет нетривиальное решение (то есть решение, отличное от тождественно
нулевого).
На заметку
Собственные векторы определяются не однозначно, а с точностью до общего
множителя. Обычно этот множитель выбирается так, чтобы вектор имел единич-
ный модуль.
Собственные числа матрицы могут быть комплексными. Количество собствен-
ных чисел, с учетом их кратности, совпадает с рангом матрицы. Разным соб-
ственным числам отвечают разные собственные векторы. Для кратных соб-
ственных чисел количество независимых собственных векторов может быть
в пределах от одного до кратности собственного числа.
Для вычисления собственных чисел и собственных векторов в Matlab ис-
пользуется функция eig(). Пример использования этой функции в раз-
ных вариантах вызова приведен в документе на рис. 4.10.
Сначала создаем матрицу A, а затем командой eig(A) вычисляем собствен-
ные числа матрицы. Стоит обратить внимание, что среди трех вычислен-
ных собственных чисел матрицы два – комплексные. Результатом функции
eig() в данном формате вызова возвращается вектор с элементами - соб-
ственными числами матрицы. Если результат вызова функции eig() запи-
сать в массив из двух элементов, то в первый элемент запишутся по столби-
кам собственные векторы матрицы-аргумента функции eig(), а во второй
элемент записывается матрица, по диагонали которой располагаются соот-
ветствующие собственные числа (недиагональные элементы этой матрицы
равны нулю). Примером может быть команда [x,l]=eig(A). В результа-
те матрица x будет состоять из столбцов, которые являются собственны-
ми векторами матрицы A, а матрица l будет диагональной. Ее диагональ-
ные элементы являются собственными числами матрицы A. Для удобства
ниже приведен код, который содержится в документе на рис. 4.10 (жирным
шрифтом выделен ввод пользователя):
Самоучитель Matlab
162
>>A=[121;-101;2-11]
A=
1
2
1
-1
0
1
2-1
1
>> eig(A)
ans =
2.4883
- 0.2442 + 1.7764i
- 0.2442 - 1.7764i
>> [x,l]=eig(A)
x=
0.6170
-0.0583 - 0.5276i -0.0583 + 0.5276i
0.0671
0.6082
0.6082
0.7841
-0.2068 + 0.5528i -0.2068 - 0.5528i
l=
2.4883
0
0
0
-0.2442 + 1.7764i
0
0
0
-0.2442 - 1.7764i
Рис. 4 .10. Вычисление собственных чисел
Глава 4. Элементы матричной алгебры
163
Вычисленные таким образом матрицы x, l и исходная матрица A должны
быть такими (в силу определения собственных чисел и векторов), что-
бы произведения A*x и x*l давали одинаковые результаты. Это обстоя-
тельство мы проверяем во второй части рассмотренного ранее документа
(см. рис. 4.10), представленной на рис. 4.11.
Рис. 4 .11. Проверка результатов вычислений собственных чисел и собственных векторов
Как и следовало ожидать, результаты вычисления матриц A*x и x*l иден-
тичны.
При работе с квадратными матрицами, кроме прочего, можно использовать
операцию возведения в степень ^. Показатель степени может быть любым
целым числом, в том числе и отрицательным. Примеры возведения матриц
в целочисленные степени приведены в документе на рис. 4.12.
Например, командой A^3 вычисляем произведение ˆ
AAA
⋅⋅
ˆˆ
, а командой
A^(-1) вычисляется обратная матрица к матрице ˆ
A.
В некоторых случаях полезно прибегать к вычислению функций от матрич-
ных аргументов. При решении задач в аналитическом виде к такому под-
ходу прибегают редко, поскольку для функции от матричного аргумента
намного легче записать символьное выражение, чем получить приемлемое
для прикладного использования выражение. Другое дело, когда для расче-
тов используется прикладной математический пакет, такой как Matlab. Си-
туацию проиллюстрируем на примере вычисления матричной экспоненты.
Как известно, в Matlab есть встроенная функция exp() для вычисления
экспоненты.
Самоучитель Matlab
164
На заметку
По определению экспоненциальная функция для скалярного аргумента x опре-
деляется как
2
0
exp() 1
..
...
2!
!
!
nk
x
k
xx
x
exx
nk
∞
=
≡=
+
+
+
+
+
=
∑.
Аргументом функции exp() можно указать матрицу. В этом случае резуль-
татом будет матрица, элементы которой получаются экспонированием со-
ответствующих элементов исходной матрицы. Так, если матрица ˆ
A состоит
из элементов ij
a (индексы
1, 2, ..,
im
=
и
1, 2, ...,
jn
=
) и она записана в пе-
ременную A, то в результате вычисления выражения exp(A) получим ма-
трицу с элементами exp( )ij
a . По-другому вычисляется функция expm(A).
Во-первых, матрица-аргумент A должна быть квадратной. Во-вторых, ре-
зультатом является матрица, которая, если не вдаваться в подробности, вы-
числяется в виде ряда
2
ˆ
ˆ
ˆ
...
...
2!
!
n
AA
EA
n
+++++
ˆ
, то есть по тому же пра-
вилу, что и экспонента от скалярного аргумента. Здесь через ˆ
E обозначена
единичная матрица того же ранга, что и матрица ˆ
A. Различие в функциях
exp() и expm() иллюстрирует документ на рис. 4.13.
Рис. 4 .12. Возведение матрицы в степень
Глава 4. Элементы матричной алгебры
165
Рис. 4 .13. Матричная экспонента
На первый взгляд может показаться, что польза от функции expm() и, бо-
лее обще, матричных функций, которые вычисляются аналогично функци-
ям скалярного аргумента, не очень велика. Но это не так. Рассмотрим про-
стой, но показательный пример.
Допустим, что нам необходимо решить задачу Коши: систему диффе-
ренциальных уравнений
() 2() 3()
dxt
xt yt
dt
=−
+
и
() 3() ()
dyt
xt yt
dt
=−
+
с начальными условиями (0) 1
x
=
и(0)3
y=
.
Это линейная систе-
ма дифференциальных уравнений первого порядка, и для ее реше-
ния в аналитическом виде существуют стандартные приемы. Слож-
ного в них ничего нет, но вычисление решения по общепринятому
алгоритму может занять некоторое время. Поэтому простым, но длинным
путем мы не пойдем. Отметим только, что точное решение данной систе-
мы уравнений имеет вид
53
33
3
(/2) s
i
n
c
(o
s
22
)e
x
p
3
tt
t
xt
⎛⎛⎞⎛⎞
⎞
⎟⎟
⎟
⎜⎜
⎜
⎟⎟
⎟
−+
⎜⎜
⎜
⎟⎟
⎟
⎜⎜
⎜
⎟⎟
⎟
⎜⎜
⎜
⎝⎝⎠
⎠
=
⎝⎠
Самоучитель Matlab
166
и
13
3
3
3
(/2) s
i
n
3
c
o
s
22
3
() exp
t
xt
t
t
⎛⎛⎞ ⎛⎞
⎞
⎟⎟
⎟
⎜⎜
⎜
⎟⎟
⎟
−+
⎜⎜
⎜
⎟⎟
⎟
⎜⎜
⎜
⎟⎟
⎟
⎜⎜
⎜
⎝⎝⎠ ⎝⎠
=
⎠
.
Если отобразить со-
ответствующе решения на графике (а мы это увидим далее), то получим
осциллирующие с затуханием функции.
Приведенное решение в числовом виде можно получить достаточно просто
без использования специальных функций для решения систем дифферен-
циальных уравнений. Для этого представим исходную систему уравнений
в векторном виде:
() ˆ()
dft
Aft
dt
=
, где введена вектор-функция
()
() ()
xt
ft
yt
⎛⎞
⎟
⎜
⎟
=⎜
⎟
⎜
⎟⎟
⎜⎝⎠
и матрица коэффициентов правых частей системы дифференциальных
уравнений
23
ˆ
31
A
⎛⎞
−
⎟
⎜
⎟
=⎜
⎟
⎜
⎟
−
⎟
⎜⎝⎠
. Начальное условие примет вид
0
1
(0)
3
ff
⎛⎞⎟
⎜⎟
≡=
⎜⎟
⎜⎟⎟
⎜⎝⎠
.
Затем воспользуемся формальной аналогией. Если бы у нас было не вектор-
ное уравнение, а скалярное
() ()
dft
Aft
dt
=
с начальным условием
0
(0)
ff
=
,
то решение можно было бы записать практически сразу:
0
() exp( )
ftfAt
=
.
Но у нас уравнение векторное, поэтому все операции в соответствующем
выражении для решения следует понимать в смысле операций с матрицами.
В том числе и вычисление экспоненты. Поэтому решение исходной систе-
мы уравнений имеет вид
0
ˆ
() exp( )
ft
Atf
=⋅
. Таким образом, для получения
решения в фиксированный момент времени t необходимо матрицу ˆA умно-
жить на скаляр t (выполняется поэлементное умножение). В результате по-
лучаем матрицу ˆAt. Затем вычисляем матрицу
ˆ
exp( )
At (по правилу вычис-
ления функции expm()) и умножаем ее (по правилу умножения матриц)
на вектор начальных значений 0f .
На заметку
Выше при построении решения для системы уравнений мы апеллировали к ана-
логии. Разумеется, аналогия не является критерием корректности метода. Тем
не менее, можно убедительно доказать, что использованный метод верный.
Таким образом, процедура поиска решения ясна, и теперь ее можно автома-
тизировать – составить программный код, с помощью которого поиск реше-
ния системы из двух линейных дифференциальных уравнений первого по-
рядка будет выполняться автоматически. Код соответствующей функции,
которая называется ldes(), приведен ниже:
function [x y]=ldes(A,t,z)
N=length(t);
Глава 4. Элементы матричной алгебры
167
for i=1:N
M=expm(A*t(i));
x(i)=z(1)*M(1,1)+z(2)*M(1,2);
y(i)=z(1)*M(2,1)+z(2)*M(2,2);
end
end
Аргументов у функции три: матрица коэффициентов A, список значений
аргумента t (узловые точки), в которых вычисляются значения искомых
функций, а также вектор начальных значений функций z. Результат вычис-
ления функции записывается в массивы x и y, каждый из которых пред-
ставляет набор точек-значений соответственно первой ()
xt и второй ()
yt
искомых функций в узловых точках.
Командой N=length(t) определяется количество узловых точек, для ко-
торых необходимо вычислить значения функций. Затем запускается опе-
ратор цикла, в котором индексная переменная i пробегает значения от
1 до N. На каждой итерации определяются значения искомых функций
в соответствующей узловой точке. Так, при фиксированном значении ин-
дексной переменной командой M=expm(A*t(i)) вычисляется матрич-
ная экспонента (для данного момента времени t(i)). Затем командами
x(i)=z(1)*M(1,1)+z(2)*M(1,2) и y(i)=z(1)*M(2,1)+z(2)*M(2,2)
вычисляются значения функций в узловой точке.
На заметку
При вычислении произведения матрицы M на вектор-столбец начальных усло-
вий z получаем вектор-столбец. Первый элемент этого вектора-столбца дает
значение функции ()
xt в узловой точке (элемент x(i)). Второй элемент
вектора-столбца дает значение функции ()
yt в узловой точке (элемент y(i)).
Чтобы получить первый элемент вектора-столбца, необходимо перемножить
и сложить соответствующие элементы первой строки матрицы M и элемен-
ты вектора начальных значений z. Первая строка матрицы M – это элементы
M(1,1) и M(1,2). Первый элемент вектора начальных значений – это z(1),
а второй элемент вектора начальных значений – это z(2). В результате полу-
чаем комбинацию z(1)*M(1,1)+z(2)*M(1,2). Аналогично вычисляется
второй элемент вектора-столбца: перемножаются и суммируются элементы
второй строки матрицы M и элементы вектора начальных значений. Желающие
могут подумать, как тот же алгоритм можно было бы реализовать с использо-
ванием операции матричного произведения вместо явного выписывания сумм
и произведений.
Окно редактора m-файлов с кодом функции ldes() показано на рис. 4.14.
После того, как функция ldes() создана, ее можно использовать для ре-
шения системы дифференциальных уравнений. В командном окне вводим
следующие команды (жирным шрифтом выделен ввод пользователя):
Самоучитель Matlab
168
>> A=[-2 3;-3 1]
A=
-2
3
-3
1
>> t=0:0.01:3*pi;
>> [x y]=ldes(A,t,[1 3]);
>> plot(t,x,t,y)
Здесь командой A=[-2 3;-3 1] создается матрица коэффициентов, коман-
дой t=0:0.01:3*pi формируется набор узловых точек, а затем командой
[x y]=ldes(A,t,[1 3]) находим решение системы дифференциальных
уравнений. Командное окно с кодом приведено на рис. 4.15.
Рис. 4.15. Командное окно с кодом для вычисления решения
дифференциального уравнения
В результате выполнения команды plot(t,x,t,y) создается график для
функциональных зависимостей ()
xtи()
yt , полученных в результате реше-
ния системы дифференциальных уравнений. Графики функций ()
xtи()
yt
представлены на рис. 4.16.
Рис. 4 .14 . Редактор m-файлов с кодом функции для вычисления решения
дифференциального уравнения
Глава 4. Элементы матричной алгебры
169
Рис. 4 .16. Графическое представление для найденного решения
На заметку
Графики функций строятся на интервале от 0 до 3π. Наличие числа π здесь яв-
ляется чистой формальностью и никакой особой смысловой нагрузки не несет.
Преобразование матриц
Этого объяснить я Вам не могу, потому что
сам толком ни черта не понимаю.
К/ф "Семнадцать мгновений весны"
В этом разделе речь пойдет о некоторых специфических операциях, кото-
рые относятся скорее к использованию матриц не как математических объ-
ектов, а как массивов данных. Понятно, что вариантов здесь может быть
очень много. Для большинства из них в Matlab есть специальные функции.
Мы остановимся только на наиболее интересных моментах.
Достаточно часто приходится создавать так называемые блочные матрицы,
которые можно представить как такие, что состоят из матричных блоков.
Другими словами, элементами блочной матрицы являются матрицы. При-
меры приведены в документе на рис. 4.17.
Самоучитель Matlab
170
Рассмотрим следующий команд-
ный код более внимательно (жир-
ным шрифтом выделен ввод поль-
зователя):
>> E=eye(2)
E=
10
01
>> O=zeros(2)
O=
00
00
>> U=ones(2)
U=
11
1
>> A=[E,2*U;3*U,O]
A=
1
0
2
2
0
1
2
2
3
3
0
0
3
3
0
0
Здесь
использовано
несколько
встроенных функций для созда-
ния матриц специального вида. Так,
функция eye() вызывается для соз-
дания единичной матрицы (по диа-
гонали единицы, прочие элемен-
ты нулевые). Функцией zeros() создается матрица с нулевыми элемен-
тами, а функцией ones() создается матрица, все элементы которой еди-
ничные. Размер матрицы указывается аргументом перечисленных функ-
ций. Таким образом, создается три матрицы размерами 2×2 каждая: единич-
ная матрица E, нулевая матрица O и матрица из единиц U. Затем командой
A=[E,2*U;3*U,O] создается блочная матрица A. Если посмотреть на эту
команду формально, то речь идет о создании матрицы 2×2. Однако элемен-
ты матрицы сами являются матрицами. Причем матрица U при передаче
элементом в блочную матрицу предварительно умножается на число. В ре-
зультате получаем матрицу A, которая имеет размеры 4×4. Ее левый верх-
ний блок – это матрица E. Верхний правый блок – матрица, состоящая из
двоек (результат умножения матрицы U на 2). Левый нижний блок – ма-
трица, состоящая из троек (результат умножения матрицы U на 3). Правый
нижний блок – нулевая матрица O.
Рис. 4 .17. Создание блочной матрицы
Глава 4. Элементы матричной алгебры
171
Достаточно просто из матрицы извлечь блок. Рассмотрим следующий
командный код:
>>A=[12345;678910;1112131415;1617181920]
A=
1
2
3
4
5
6
7
8
910
1112131415
1617181920
>> B=A(2:4,1:3)
B=
6
7
8
111213
161718
Сначала создается матрица A размерами 4×5, а затем командой
B=A(2:4,1:3) из нее извлекается блок (подматрица, которая записыва-
ется в переменную B). Блок выделяется из исходной матрицы так: стро-
ки со 2-й по 4-ю включительно и столбцы с 1-го по 3-й включительно
(рис. 4.18).
Рис. 4.18. Создание блочной матрицы
Еще одна полезная процедура, которую нередко приходится выполнять, –
удаление из матрицы строки или столбца. Формально она состоит в том,
что соответствующей строке или столбцу в качестве значения присваивает-
ся пустой список. Примеры приведены в документе на рис. 4.19.
Самоучитель Matlab
172
Рис. 4 .19. Удаление строк и столбцов
Сначала создается матрица A, а затем командой A(:,3)=[] из матрицы A
удаляется 3-й столбец. Следующей командой A(:,3:4)=[] из измененной
на предыдущем этапе матрицы A удаляются 3-й и 4-й. Матрица A стано-
вится еще меньше. После этого командой A(3,:)=[] из матрицы удаляем
3-ю строку. Весь командный код имеет следующий вид (жирным шрифтом
выделен ввод пользователя):
>>A=[12345;678910;1112131415;1617181920]
A=
1
2
3
4
5
6
7
8
910
1112131415
1617181920
Глава 4. Элементы матричной алгебры
173
>> A(:,3)=[]
A=
1
2
4
5
6
7
910
11121415
16171920
>> A(:,3:4)=[]
A=
1
2
6
7
11 12
16 17
>> A(3,:)=[]
A=
1
2
6
7
16 17
На заметку
Для ссылки на все элементы строки или столбца мы использовали двоеточие
вместо соответствующего индекса.
В Matlab, на уровне реализации и поддержки базовых операций, серьезное
внимание уделяется так называемым разряженным матрицам. Под разряжен-
ными подразумевают матрицы, содержащие значительное количество нуле-
вых элементов. Примером разряженной матрицы может быть диагональная
(ненулевые элементы только на главной диагонали) матрица или трехдиаго-
нальная (ненулевые элементы на диагонали и рядом с ней) матрица. В принци-
пе, никакой особой проблемы с разряженными матрицами нет – матрицы как
матрицы. Все так называемые проблемы связаны с компьютерной обработкой
таких матриц. Дело в том, что если разряженная матрица достаточно большого
размера, то для нее нужно много места в памяти. При этом память расходу-
ется достаточно нерационально в том смысле, что подавляющее количество
элементов нулевое, и под каждый из них необходимо выделить ячейку памяти.
На заметку
В данном случае не важно, что элементы именно нулевые. Важно то, что все они
одинаковые.
Например, если мы имеем дело с квадратной диагональной матрицей раз-
мера nn
× , то на диагонали будет n элементов, а всего элементов
2
n.То
есть доля "полезных" элементов в матрице составляет
2
1
nn
n
=
.
При
100
n=
с пользой для дела будет использоваться только 1% от объема па-
мяти, выделенной под матрицу. Такая расточительность может стать кри-
Самоучитель Matlab
174
тичной – кто сталкивался с серьезным математическим моделированием,
знает, о чем идет речь.
В Matlab данная проблема решается достаточно просто – в разреженных
матрицах запоминаются только ненулевые элементы. За счет этого эконо-
мится память. При этом вся кухня, связанная с особенностями реализации
разреженных матриц, от пользователя скрыта, и внешне иллюзия такая, как
если бы мы имели дело с обычной матрицей.
Поскольку разница между разреженной и обычной матрицей достаточно зыб-
кая, принимать решение о том, какую матрицу считать разреженной, должен
пользователь. Другими словами, разреженной матрица сама по себе не станет,
даже если состоит сплошь из нулей. Разреженную матрицу нужно специально
создавать. Для создания разреженной матрицы на основе уже существующей
используют встроенную функцию sparse(). Аргументом можно указать
обычную (не разреженную) матрицу (но можно и что-то другое). Простой
пример создания разреженной матрицы приведен в документе на рис. 4.20.
Следующими командами создается прототип разреженной матрицы:
>> A=eye(5);
>> for i=1:4
A(i,i+1)=2;
A(i+1,i)=3;
end
В результате создается матрица, на диагонали которой единицы, поддиа-
гональ сверху заполнена двойками, а поддиагональ снизу заполнена трой-
ками. На основе созданной с такими параметрами матрицы A командой
B=sparse(A) создаем разреженную матрицу. На эту команду стоит обра-
тить внимание, хотя бы из-за того, каков будет ее результат:
>> B=sparse(A)
B=
(1,1)
1
(2,1)
3
(1,2)
2
(2,2)
1
(3,2)
3
(2,3)
2
(3,3)
1
(4,3)
3
(3,4)
2
(4,4)
1
(5,4)
3
(4,5)
2
(5,5)
1
Глава 4. Элементы матричной алгебры
175
Это при том, что матрица A отображается совершенно обычным образом:
>>A
A=
1
2
0
0
0
3
1
2
0
0
0
3
1
2
0
0
0
3
1
2
0
0
0
3
1
Несложно сообразить, что разреженная матрица отображается по-особому:
это два столбика, в первом из которых в круглых скобках указываются ин-
дексы ненулевых элементов, а во втором столбце – значения ненулевых
элементов. Все прочие элементы матрицы автоматически полагаются нуле-
выми. Например, запись
Рис. 4 .20. Создание разреженной матрицы
Самоучитель Matlab
176
(3,4)
2
означает, что элемент матрицы, находящийся в 3-й строке и 4-м столбце,
равен 2. Чтобы проверить эффект от экономии места, воспользуемся ин-
струкцией с ключевым словом whos:
>>whosAB
Name
Size
Bytes Class
Attributes
A
5x5
200
double
B
5x5
180
double
sparse
Тот же результат можно видеть в документе на рис. 4.21.
Рис. 4 .21. Выделяемая для записи матриц память
В данном случае эффект от использования разреженной матрицы не очень
существенный: на такую же обычную матрицу выделяется 200 байт, а на
разреженную – 180. Эффект экономии имеет место только при работе с ма-
трицами больших размеров.
На заметку
Чтобы увидеть разреженную матрицу во всей красе, то есть в обычном пред-
ставлении, используют функцию full() с передачей ей аргументом разре-
женной матрицы.
Приведенный выше способ создания разреженной матрицы малополезен,
поскольку подразумевает предварительное создание обычной матрицы.
Обычно разумнее и удобнее сразу создавать разреженную матрицу. В этом
случае также используется функция sparse(), но несколько иначе пере-
даются аргументы. Первым и вторым аргументами указываются списки
с индексами строк и столбцов для ненулевых элементов. Третий аргумент –
список со значениями ненулевых элементов. Четвертый и пятый числовые
аргументы задают количество строк и столбцов в разреженной матрице.
Если эти аргументы не указать, то размеры матрицы определяются автома-
тически на основании списка ненулевых элементов. Рассмотрим такой код:
A=sparse([1,1,2,2,2,3,5],[1,2,1,3,5,1,4],[1,0,3,4,4,1,2],6,5)
Глава 4. Элементы матричной алгебры
177
Командой создается разреженная матрица размерами 6×5 (четвертый
и пятый аргументы функции sparse()). Ненулевые элементы размеще-
ны на пересечении строк с номерами [1,1,2,2,2,3,5] (первый аргу-
мент функции sparse()) и столбцов с номерами [1,2,1,3,5,1,4] (вто-
рой аргумент функции sparse()). Сами значения определяются списком
[1,0,3,4,4,1,2] (третий аргумент функции sparse()). Это означает,
что например, элемент A(1,1) равен 1, элемент A(1,2) равен 0, элемент
A(2,1) равен 3 и так далее (рис. 4.22).
Рис. 4 .22 . Еще один способ создания разреженной матрицы
На заметку
При создании разреженной матрицы в приведенном выше примере один из
элементов указан как нулевой (это элемент с индексами 1 и 2). При отображе-
нии списка значений разреженной матрицы в формате индексы/значение такие
элементы игнорируются, несмотря на то, что они указывались при создании ма-
трицы в явном виде.
Самоучитель Matlab
178
Некоторые примеры
Я бы не стал увязывать эти вопросы
так перпендикулярно.
В. Черномырдин
В этом разделе рассмотрим некоторые примеры решения задач линейной
алгебры с использованием средств Matlab. Более детально рассмотрим во-
прос о вычислении матричных функций. В частности, вычислим разными
способами матричный синус и матричный косинус.
Для вычисления матричного синуса, то есть синуса, у которого ар-
гумент – квадратная матрица ˆ
A, используем следующую формулу:
35
21
21
0
ˆ
(1)
(1)
ˆ
sin( )
...
...
3! 5!
(2 1)!
(2 1)!
kk
kk
k
AA
A
A
AA
kk
∞
++
=
−−
=−+
−+
+=
++
∑
ˆ
ˆˆ
ˆ
.
Эта фор-
мула является обобщением для матричного аргумента ряда Тейлора для
синуса от скалярного аргумента. Процедуру вычисления такого ряда при
известной матрице ˆ
A реализуем с помощью специальной функции, код ко-
торой приведен ниже:
function M=SinM(A)
M=A;
for i=1:100
M=M+(-1)^i*A^(2*i+1)/factorial(2*i+1);
end
end
Функция называется SinM(), и у нее один аргумент, который обозначен
как A. Как уже отмечалось, предполагается, что это квадратная матрица. Ре-
зультат записывается в переменную, обозначенную в коде как M. Это тоже
будет квадратная матрица. На начальном этапе командой M=A переменной-
результату присваивается значение переменной-аргумента. Затем запу-
скается оператор цикла, в котором командой M=M+(-1)^i*A^(2*i+1)/
factorial(2*i+1) к текущему значению переменной M добавляется оче-
редное слагаемое ряда.
На заметку
Здесь мы использовали встроенную функцию factorial() для вычисления
факториала числа. Для вычисления ряда используется 100 итераций в опера-
торе цикла. Поэтому выражение для матричного синуса получается приближен-
ное. Но если элементы матрицы-аргумента не очень большие, точность будет
вполне приемлемой. Что касается самого алгоритма вычисления результата, то
он не самый оптимальный, зато по сравнению с другими способами расчетов
более наглядный.
Глава 4. Элементы матричной алгебры
179
Программный код функции SinM() в окне редактора m-файлов представ-
лен на рис. 4.23.
Рис. 4 .23. Программный код функции для вычисления матричного синуса
Аналогичным способом будем вычислять и матричный косинус.
Правда, в этом случае в вычислениях используем следующий ряд
24
2
2
1
ˆ
(1)
(1)
ˆ
ˆ
cos( )
...
...
2! 4!
(2 )!
(2 )!
kk
kk
k
AA
A
A
AE
E
kk
∞
=
−−
=−+
−
+
+=+
∑
ˆ
ˆˆ
ˆ
.
Здесь
через ˆ
E обозначена единичная матрица того же ранга, что и матрица ˆ
A. Про-
граммный код функции CosM(), которой по матричному аргументу в каче-
стве результата возвращается матричный косинус, имеет такой вид:
function M=CosM(A)
n=length(A);
E=eye(n);
M=E;
for i=1:100
M=M+(-1)^i*A^(2*i)/factorial(2*i);
end
end
Здесь на начальном этапе командами n=length(A) и E=eye(n) опреде-
ляется размер матрицы-аргумента и создается единичная матрица такого
же размера. Матрица-результат в качестве начального значения получает
единичную матрицу (команда M=E).
На заметку
Функцией length() возвращается количество столбцов в матрице-аргументе.
Если матрица A квадратная, то количество столбцов равняется количеству
строк. Обратите внимание также на то, что в операторе цикла поменялось вы-
ражение для слагаемого-добавки ряда.
Самоучитель Matlab
180
Программный код функции CosM() в окне редактора m-файлов представ-
лен на рис. 4.24.
Рис. 4 .24. Программный код функции для вычисления матричного косинуса
После того, как обе функции созданы, а соответствующие файлы сохра-
нены, функции можно использовать при вычислениях в командном окне.
Для проверки и демонстрации работоспособности созданных функций
в командном окне вводим такой код (жирным шрифтом выделен ввод поль-
зователя):
>> A=[pi/2 pi/3;pi/4 pi]
A=
1.5708
1.0472
0.7854
3.1416
>> SinM(A)
ans =
0.6878 -0.5752
- 0.4314 -0.1750
>> CosM(A)
ans =
0.1750 -0.5752
- 0.4314 -0.6878
>> SinM(A)^2+CosM(A)^2
ans =
1.0000
0.0000
0.0000
1.0000
Сначала создаем квадратную матрицу A размерами 2×2. Затем командами
SinM(A) и CosM(A) последовательно вычисляем матричный синус и ко-
синус. Интересным может показаться результат вычисления выражения
SinM(A)^2+CosM(A)^2. В результате получаем единичную матрицу. Уди-
Глава 4. Элементы матричной алгебры
181
вительного в этом ничего нет, поскольку для любой квадратной матрицы ˆ
A
имеет место тождество ()
()
22
ˆ
ˆ
sin( )
cos( )
AA
E
+=
ˆ
.
На заметку
Операции SinM(A)^2 и CosM(A)^2 имеют смысл, поскольку SinM(A)
и CosM(A) – квадратные матрицы, и к ним, как к обычным матрицам, применим
оператор ^ возведения в целочисленную степень.
Результат вычислений показан в документе на рис. 4.25.
Рис. 4.25. Вычисление матричного синуса и косинуса
Справедливости ради следует отметить, что приведенный способ вычисле-
ния матричного синуса и косинуса далеко не единственный. Существуют
и более простые пути. Например, можно воспользоваться формулой Эй-
лера для экспоненты в комплексной степени: exp( ) cos( )
sin( )
ix
x
ix
=+,
где i - мнимая единица, для которой по определению 2
1
i=−
. Таким об-
разом, cos( ) Re(exp( ))
xi
x
=
и sin( ) Im(exp( ))
xi
x
=
.
Здесь через Re( )
z
иIm()
z обозначены соответственно действительная и мнимая части ком-
плексного числа z . Мы могли бы, например, определить матричный синус
Самоучитель Matlab
182
как
ˆ
sin( ) Im(exp( ))
Ai
A
=
ˆ
, а матричный косинус как
ˆ
cos( ) Re(exp( ))
Ai
A
=
ˆ
.
Примеры таких вычислений приведены ниже:
>> real(expm(A*i))
ans =
0.1750 -0.5752
- 0.4314 -0.6878
>> imag(expm(A*i))
ans =
0.6878 -0.5752
- 0.4314 -0.1750
Несложно заметить, что данный способ вычисления синуса и косинуса от
матричного аргумента дает такой же результат (в пределах точности вычис-
лений), что и с использованием ряда Тейлора.
На заметку
В вычислениях использовалась встроенная функция expm() для расчета ма-
тричной экспоненты. Она справляется с задачей, даже если аргумент комплекс-
ный. Действительная часть вычисляется с помощью функции real(), а мни-
мая – с помощью функции imag().
Окно с результатами вычислений показано на рис. 4.26.
Рис. 4 .26. Альтернативный способ вычисления матричного синуса и косинуса
Как пример использования блочных матриц рассмотрим такую задачу.
Предположим, есть три вектора в декартовом трехмерном пространстве
123
(,,)
kk
k
k
aa
a
a
=
, индекс
1,2,3
k=
. Предполагаем также, что эти векторы
линейно-независимы и образуют базис. Задача состоит в том, чтобы разло-
жить по этому базису некоторый известный вектор
123
(,,)
bb
b
b
=
.
Глава 4. Элементы матричной алгебры
183
Выражение "разложить по базису" означает, что необходимо представить
вектор b в виде линейной комбинации векторов 1
a,2
aи3
a . Другими сло-
вами, необходимо найти такие числа 1
x,2
xи3
x , чтобы имело место равен-
ство
3
11
22
33
1
kk
k
bx
a
x
a
x
a
x
a
=
==
+
+
∑
. Параметры 1
x,2
xи3
x называются
координатами вектора b в базисе из векторов 1
a,2
aи3
a . Если компоненты
1
x,2
xи3
x "спрятать" в вектор
123
(,,)
xx
x
x
=
, то для этого вектора долж-
но выполняться соотношение
ˆ
xAb
⋅=
, где матрица ˆ
A формируется век-
торами 1
a,2
aи3
a : первая строка матрицы ˆ
A-этовектор 1
a , вторая строка
матрицы ˆ
A-вектор 2
a , а третья строка матрицы ˆ
A-вектор 3
a . Другими
словами,
ˆ
A - это блочная матрица.
Что касается вектора x , то чтобы его найти, необходимо в выражении
ˆ
xAb
⋅=правую и левую части умножить справа на матрицу 1
ˆ
A−
, обрат-
ную к матрице ˆ
A. В результате получим
1
ˆ
xbA
−
=⋅
. Именно этим соотно-
шением и воспользуемся для вычисления координат вектора в новом ба-
зисе. Рассмотрим приведенный ниже командный код (жирным шрифтом
выделен ввод пользователя):
>> a1=[1 3 1];
>> a2=[-2 1 0];
>> a3=[0 -1 2];
>> b=[1 3 -2];
>> A=[a1;a2;a3]
A=
1
3
1
-2
1
0
0-1
2
>> x=b/A
x=
0.6250 -0.1875 -1.3125
>> x*A
ans =
1
3-2
Сначала мы создаем три вектора для нового базиса (значения записыва-
ются в переменные a1, a2 и a3), а также вектор (переменная b), который
необходимо разложить по базису. Командой A=[a1;a2;a3] на основе век-
торов нового базиса создается блочная матрица. С помощью этой матрицы,
воспользовавшись командой x=b/A, вычисляем вектор координат вектора
b в базисе векторов a1, a2 и a3. Проверить, корректно ли вычислен резуль-
тат, можно, воспользовавшись командой x*A. В результате должны полу-
чить вектор b, что, собственно, и происходит (рис. 4.27).
Самоучитель Matlab
184
Рис. 4 .27. Вычисление координат вектора в новом базисе
На заметку
Для умножения вектора b справа на обратную матрицу к A мы использовали
оператор /. Хотя реальный алгоритм вычисления результата в этом случае на
самом деле несколько сложнее, в принципе, можно полагать, что команда b/A
вычисляется так: вектор b справа умножается на матрицу, которая обратна к ма-
трице A.
Классической стала задача о вычислении угла между двумя векторами
в пространстве. В Matlab эта задача решается исключительно просто. Рас-
смотрим один из возможных способов решения. Базируется он на том об-
щеизвестном факте, что скалярное ab
⋅
произведение двух векторов a и b
равно произведению модулей этих векторов на косинус угла φ между ними,
то есть
||||cos()
ababφ
⋅=
. Отсюда легко найти cos( )
||||
ab
ab
φ
⋅
=
. Зная
косинус угла, можно вычислить сам угол с помощью функции арккосинуса.
На заметку
В Matlab для вычисления арккосинуса имеется функция acos(). Однако здесь
есть один специфический момент. Дело в том, что если известен косинус угла,
Глава 4. Элементы матричной алгебры
185
то сам угол восстанавливается неоднозначно. Арккосинус дет значение в пре-
делах от 0 до p. Поэтому важно четко представлять, что же именно мы вычисля-
ем. В данном случае вычисляется абсолютное значение угла между векторами –
в плоскости векторов меньший из двух смежных углов между линиями, вдоль
которых направлены векторы.
Пример вычисления угла между векторами представлен в документе на
рис. 4.28.
Рис. 4 .28. Вычисление угла между векторами
Собственно, для вычисления угла между векторами a и b, помимо команд
инициализации векторов, используется всего одна команда phi=180/
pi*acos(dot(a,b)/norm(a)/norm(b)). Угол вычисляется в градусах,
поэтому результат, возвращаемый арккосинусом, умножается на 180 и де-
лится на π. Скалярное произведение векторов вычисляем с помощью функ-
ции dot(), а модуль вектора вычисляется функцией norm().
Похожая в известном смысле задача – вычисление площади и периметра
пространственного треугольника. Задача формулируется так. Заданы три
точки в пространстве. Они образуют треугольник. Необходимо найти пло-
щадь этого треугольника и его периметр.
Решать задачу будем следующим образом. Обозначим через A , B и C
точки, которые заданы. На их основе вычисляем три вектора AB , AC
и BC . Периметр P может быть вычислен как сумма модулей этих векто-
ров, то есть
||||||
PA
BA
CB
C
=+ + . Площадь треугольника равна
1
||
||
s
i
n
()
2
SA
B
A
Cφ
=
, где через φ обозначен между векторами AB и
AC . С другой стороны, если вычислить векторное произведение AB AC
×
,
то результатом будет вектор, и его модуль равен ||
||
s
i
n
()
AB AC
φ,тоесть
в два раза больше площади треугольника.
Самоучитель Matlab
186
На заметку
Если заданы начальная и конечная точка вектора, то координаты вектора можно
рассчитать путем вычитания из координат конечной точки соответствующих ко-
ординат начальной точки.
Ниже приведен командный код, с помощью которого вычисляется площадь
и периметр треугольника (жирным шрифтом выделен ввод пользователя).
>> A=[1 2 1];
>> B=[-2 3 -1];
>> C=[1 -1 2];
>> AB=B-A
AB=
-3
1-2
>> AC=C-A
AC=
0-3
1
>> BC=C-B
BC=
3-4
3
>> P=norm(AB)+norm(AC)+norm(BC)
P=
12.7349
>> S=norm(cross(AB,AC))/2
S=
5.3619
Командами A=[1 2 1], B=[-2 3 -1] и C=[1 -1 2] создаются точ-
ки – вершины треугольника. Затем с помощью команд AB=B-A, AC=C-A
и BC=C-B вычисляются векторы, которые нам нужны для вычисления
периметра и площади треугольника. Периметр вычисляем командой
P=norm(AB)+norm(AC)+norm(BC). Площадь вычисляем командой
S=norm(cross(AB,AC))/2, в которой для вычисления векторного произ-
ведения использована встроенная функция cross(). Результат вычисле-
ний показан на рис. 4.29.
Обращаем внимание, что точки представляются в виде списков из трех эле-
ментов. Это позволяет достаточно просто на основании известных точек
вычислить соответствующие им векторы.
Еще одной классической является задача о решении системы линейных ал-
гебраических уравнений. В общем случае задача формулируется так. Не-
обходимо решить систему уравнений
1
n
ijj
i
j
axb
=
=
∑
(индекс
1, 2, ...,
in
=
)
относительно неизвестных 1
x,2
x,...,
n
x при условии, что параметры ij
a
Глава 4. Элементы матричной алгебры
187
и ib (индексы ,
1, 2, ...,
ij
n
=
) заданы. Именно этой задачей и займемся.
Всякие экзотические случаи, наподобие системы без решений, исследовать
не будем. Предполагаем, что у системы уравнений решение есть, и оно един-
ственно.
Исходную систему уравнений удобно представить в матричном виде, вве-
дя в рассмотрение матрицу ˆA с элементами ij
a (индексы ,1
,
2
,
.
.
.
,
ij
n
=
),
векторы-столбцы b и x с элементами ib и i
x соответственно (индекс
1, 2, ...,
in
=
). В этих обозначениях система уравнений может быть записа-
наввидеˆ
Axb
=
. Решение находится элементарно:
1
ˆ
xAb
−
=
. Таким обра-
зом, для решения системы уравнений достаточно знать матрицу коэффици-
ентов ˆ
A и вектор правых частей уравнений b . Данный подход реализован
в коде, представленном ниже:
Рис. 4 .29. Вычисление периметра и площади треугольника
Самоучитель Matlab
188
>>A=[123;-112;1-25]
A=
1
2
3
-1
1
2
1-2
5
>> b=[10;1;4]
b=
10
1
4
>> x=A\b
x=
3
2
1
Матрица коэффициентов задается командой A=[1 2 3;-1 1 2;1 -2
5]. Вектор коэффициентов правых частей задается командой b=[10;1;4].
Таким образом, решается следующая система уравнений:
123
123
123
231
0
21
254
xxx
xxx
xxx
⎧⎪
++=
⎪
⎪⎪−+ +
=
⎨⎪⎪
−+=
⎪
⎪⎩
Система имеет единственное решение 1
3
x=
,
2
2
x=и3
1
x=
. Именно его
попытаемся найти. Для этого используем команду x=A\b, в результате чего
и получаем нужное решение (рис. 4.30).
На заметку
Вместо вычисления обратной матрицы к матрице A и умножения ее (слева) на
вектор b мы использовали оператор \.
Важная задача, которая встречается достаточно часто, связана с диагона-
лизацией матриц. Вначале краткая предыстория о том, откуда такая задача
вообще может возникнуть. Допустим, мы вместо одного векторного базиса
вводим другой. Единичные орты исходного базиса обозначим как 1
a,2
aи3
a.
На заметку
Далее, если явно не указано, подразумевается, что речь идет о векторах-
столбцах, а все матрицы квадратные размера 3×3 (хотя изложенное далее без
особых проблем применимо и к более общему случаю квадратных матриц про-
извольного размера).
Они единичные и ортогональные, то есть скалярное произведение
iji
j
aaδ
′ ⋅= (индексы ,1
,
2
,
3
ij= ). Здесь штрих обозначает транспониро-
Глава 4. Элементы матричной алгебры
189
вание, а через
1,
0,
ij
ij
ij
δ
⎧
=
⎪
⎪
=⎨
⎪
≠
⎪⎩
обозначен символ Кронекера. Орты в новом
базисе обозначим как 1
b,2
bи3
b . Они также ортогональные и единичные,
то есть имеет место соотношение ij i
j
bbδ
′ ⋅= (индексы ,1
,
2
,
3
ij= ). Никто
и ничто не запрещают нам записать новые орты через старые орты. Это бу-
дет выглядеть так:
3
1
ii
j
j
j
bs
a
=
=
∑ (индекс
1,2,3
i=
). Элементы ij
s с индекса-
ми ,1
,
2
,
3
ij=
формируют матрицу ˆS , которая называется матрицей пере-
хода. У этой матрицы есть ряд интересных свойств. Так, несложно показать,
что для матрицы перехода
1
ˆ
SS
−
′=
ˆ
-
то есть транспонированная матрица
равна обратной. Определитель матрицы ˆ
S (по модулю) равен единице. Для
преобразования базиса достаточно задать матрицу перехода ˆ
S . Все необ-
ходимые преобразования вычисляются на основе этой матрицы. Так, если
в старом базисе задан некоторый вектор x , то в новом базисе получим век-
тор
ˆ
yS
x
=
. Это следует непосредственно из способа определения матрицы
перехода.
Рис. 4 .30. Решение системы линейных уравнений
Самоучитель Matlab
190
На заметку
При преобразовании базиса модуль вектора не меняется. В старом бази-
се модуль вектора вычисляется как xx
′⋅
, а в новом базисе это yy
′⋅
, где
по определению
ˆ
yS
x
=
.
Поскольку в обоих случаях должны получить одно
и то же значение, а также принимая во внимание, что ′′
′
ˆ
yx
S
=
, получаем
′′
′′
ˆ
yy xSS
xxx
⋅=
=⋅
ˆ
. Отсюда, собственно, и находим, что (через ˆ
E обозна-
чена единичная матрица) ˆSS E
′=
ˆˆ
и, следовательно,
1
ˆ
SS
−
′=
ˆ
.
Если в старом базисе задана некоторая матрица ˆ
A, то в новом базисе эта
матрица вычисляется как
1
ˆ
ˆ
BS
A
S
−
=
ˆˆ
.
На заметку
Данное правило можно получить исходя из того обстоятельства, что для лю-
бой матрицы ˆ
A и вектора x выражение
ˆ
xAx
′
является скаляром и не зави-
сит от выбора векторного базиса. Поэтому должно выполняться соотношение
ˆ
ˆ
xAx yBy xSBSx
′′′
′
==
ˆˆˆ
, чтодает ˆ
ˆ
AS
B
S
′
=
ˆˆ
или
1
ˆ
ˆ
BS
A
S
−
=
ˆˆ
.
Очень часто задача состоит в том, чтобы выполнить преобразование базиса,
при котором некоторая матрица (например,
ˆ
A) принимает наиболее про-
стой вид. А что может быть проще диагональной матрицы? Другими сло-
вами, задача может быть сформулирована, например, следующим образом.
Задана симметричная матрица ˆ
A. Необходимо найти матрицу перехода ˆ
S
такую, чтобы матрица
1
ˆ
ˆ
BS
A
S
−
=
ˆˆ
была диагональной.
На заметку
К диагональному виду матрицу ˆA можно привести, если все ее собственные
числа различны. В противном случае удается свести матрицу к жорданову виду,
когда матрица "почти диагональная". Более того, матрица перехода будет удо-
влетворять условию
1
ˆ
SS
−
′=
ˆ
, только если матрица ˆ
A симметрична. Другими
словами, если речь идет не просто о матрице ˆ
S , а именно о матрице перехо-
даˆ
S , то свести к диагональному виду можно только симметричную матрицу ˆA
с разными собственными числами.
В Matlab есть несколько встроенных функций, с помощью которых может
решаться описанная выше задача (или идейно близкая к ней). Здесь оста-
новимся на уже известной функции вычисления собственных чисел eig()
и функции выполнения жорданова преобразования jordan(). Функция
eig() уже описывалась. Что касается функции jordan(), то ее аргумен-
том указывается исходная, преобразуемая, матрица. В качестве результата
возвращается две матрицы. Первая матрица – это матрица, с помощью ко-
торой выполняется преобразование (аналог матрицы перехода, но только
аналог!). Вторая матрица - диагональная или "почти диагональная" (жор-
Глава 4. Элементы матричной алгебры
191
данова форма), которая получается в результате преобразования исходной
матрицы. Пример вычислений приведен ниже (жирным шрифтом выделен
ввод пользователя):
>>A=[5-32;6-44;4-45]
A=
5-3
2
6-4
4
4-4
5
>> [V,D]=jordan(A)
V=
0.5000
1.0000
1.0000
1.0000
2.0000
1.0000
1.0000
1.0000
0
D=
3
0
0
0
1
0
0
0
2
>> inv(V)*A*V
ans =
3
0
0
0
1
0
0
0
2
>> V*D*inv(V)
ans =
5-3
2
6-4
4
4-4
5
>> [U,B]=eig(A)
U=
- 0.4082 -0.7071
0.3333
- 0.8165 -0.7071
0.6667
- 0.4082 -0.0000
0.6667
B=
1.0000
0
0
0
2.0000
0
0
0
3.0000
>> inv(U)*A*U
ans =
1.0000
- 0.0000
- 0.0000
- 0.0000
2.0000
0.0000
0.0000
- 0.0000
3.0000
>> U*B*inv(U)
ans =
5.0000
- 3.0000
2.0000
6.0000
- 4.0000
4.0000
4.0000
- 4.0000
5.0000
Самоучитель Matlab
192
На рис. 4.31 представлена начальная часть документа с командным кодом,
в котором матрица диагонализируется с помощью функции jordan().
Рис. 4 .31. Диагонализация матрицы с помощью функции jordan()
После объявления матрицы A командой [V,D]=jordan(A) вычисляется
матрица преобразования V и диагональная (в данном случае) матрица D –
результат преобразования матрицы A.
На заметку
По определению функцией jordan() на основании матрицы ˆ
A (аргумент
функции) вычисляется матрица ˆ
V такая, что матрица
1ˆ
ˆ
DVA
V
−
=
ˆˆ
диаго-
нальная или, в общем случае, имеет жорданов вид (блочно-диагональная). Из
условия
1ˆ
ˆ
DVA
V
−
=
ˆˆ
следует, что
1
ˆ
ˆ
AV
D
V−
=
ˆˆ
. При этом условие
1
ˆ
VV
−
=
ˆ
′
в общем случае не выполняется. Поэтому не совсем корректно называть матри-
цуˆ
V матрицей перехода в том смысле, как это излагалось выше. Для устране-
ния возможных недоразумений будем называть матрицу ˆ
V матрицей преобра-
зования.
Далее проверяются два соотношения:
1ˆ
ˆ
DVA
V
−
=
ˆˆ
и
1
ˆ
ˆ
AV
D
V−
=
ˆˆ
.
Для
этого используем команды inv(V)*A*V и V*D*inv(V) соответственно.
В первом случае получаем матрицу D, а во втором случае получаем матрицу
A (рис. 4.32).
Глава 4. Элементы матричной алгебры
193
Рис. 4 .32. Проверка результата диагонализации
Практически те же результаты можно получить с помощью функции
eig(). На рис. 4.33 приведен фрагмент документа, в котором командой
[U,B]=eig(A) на основе матрицы A вычисляется диагональная матрица
B и матрица преобразования U.
В результате выполнения команды inv(U)*A*U получаем матрицу B,
а в результате выполнения команды U*B*inv(U) получаем матрицу A. При
этом матрица B фактически совпадает с матрицей D, вычисленной ранее, –
те же собственные числа на диагонали, только в другом порядке. Возникает
естественный вопрос: в чем же разница? Разница есть, и она существенная.
Связана она в основном с матрицей преобразования. Столбцы матрицы
преобразования, возвращаемой функцией eig(), нормированы на едини-
цу, чего не скажешь о матрице преобразования, возвращаемой функцией
jordan().
На заметку
Порядок следования собственных чисел на диагонали у диагональной матри-
цы определяет порядок следования столбцов в матрице перехода. Другими
словами, при диагонализации матрицы конечная диагональная форма содер-
жит на главной диагонали собственные числа исходной матрицы. В принципе,
они могут следовать в разном порядке. Матрицы перехода для разных диа-
гональных форм отличаются порядком следования столбиков. Сами столби-
ки матрицы преобразования представляют собой собственные векторы ис-
ходной матрицы.
Имеет смысл также рассмотреть процедуру диагонализации симметричной
матрицы. Матрицу создаем так:
Самоучитель Matlab
194
>>A=[123;226;36-1]
A=
1
2
3
2
2
6
3
6-1
Матрицу перехода и диагональную форму вычисляем следующей командой:
>> [S,B]=eig(A)
S=
0.1864
0.8842
0.4283
0.5639 -0.4532
0.6904
- 0.8046 -0.1128
0.5831
B=
-5.9000
0
0
0 -0.4080
0
0
0
8.3080
Рис. 4 .33. Диагонализация матрицы с помощью функции eig()
Глава 4. Элементы матричной алгебры
195
В данном случае получена именно матрица перехода, поскольку произведе-
ние этой матрицы на транспонированную дает единичную матрицу:
>> S*S'
ans =
1.0000
0.0000
0
0.0000
1.0000
0
0
0
1.0000
Ее определитель по модулю равен единице:
>> det(S)
ans =
-1.0000
Процесс этих вычислений проиллюстрирован на рис. 4.34.
Рис. 4 .34. Диагонализация симметричной матрицы с помощью функции eig()
Самоучитель Matlab
196
В принципе, похожие результаты можно получить и с помощью функции
jordan(). Правда, процесс более сложный. Например, следующей коман-
дой вычисляем матрицу преобразования и соответствующую ей диагональ-
ную форму:
>> [W,D]=jordan(A)
W=
- 0.2316 - 0.0000i
0.7346 + 0.0000i -7.8362 + 0.0000i
- 0.7009 + 0.0000i
1.1841 - 0.0000i
4.0168 - 0.0000i
1.0000
1.0000
1.0000
D=
- 5.9000 + 0.0000i
0
0
0
8.3080 + 0.0000i
0
0
0
-0.4080 - 0.0000i
На заметку
Формально элементы полученных матриц комплексные. Однако мнимая часть
у них нулевая. Появление нулевых мнимых частей связано со спецификой ис-
пользуемого алгоритма вычисления жордановой формы и матрицы перехода.
Однако транспонированная матрица преобразования не равна обратной,
в чем несложно убедиться, воспользовавшись командой
>> W*W'
ans =
62.0000
- 30.4444 + 0.0000i -7.3333
-
0.0000i
- 30.4444
-
0.0000i 18.0278
4.5000 + 0.0000i
-7.3333 + 0.0000i
4.5000 - 0.0000i 3.0000
Результаты этих вычислений представлены на рис. 4.35.
Причина этой неприятности кроется в том, что хотя столбцы полученной
матрицы преобразования состоят из собственных векторов исходной, пре-
образуемой, матрицы, они не нормированы. В этом все дело! Убедимся.
Переопределяем матрицу преобразования путем нормирования столбца
матрицы на модуль этого столбца. Чтобы нормировать столбец с индек-
сом k (возможные значения 1, 2 или 3), используем команду W(:,k)/
norm(W(:,k)). Здесь мы воспользовались тем, что ссылка на столбец ма-
трицы с данным индексом выполняется в виде W(:,k). Вся команда перео-
пределения матрицы W выглядит так:
>> W=[W(:,1)/norm(W(:,1)),W(:,2)/norm(W(:,2)),W(:,3)/
norm(W(:,3))]
W=
- 0.1864 - 0.0000i
0.4283 + 0.0000i -0.8842 + 0.0000i
- 0.5639 + 0.0000i
0.6904 - 0.0000i
0.4532 - 0.0000i
0.8046
0.5831
0.1128
Глава 4. Элементы матричной алгебры
197
Теперь все изменилось, и произведение матрицы W на транспонированную
дает единичную матрицу:
>> W*W'
ans =
1.0000
- 0.0000 + 0.0000i -0.0000
-
0.0000i
- 0.0000
-
0.0000i
1.0000
0.0000 + 0.0000i
- 0.0000 + 0.0000i
0.0000
-
0.0000i
1.0000
При этом матрица W является матрицей перехода:
>> W*D*W'
ans =
1.0000
-
0.0000i
2.0000
-
0.0000i
3.0000 + 0.0000i
2.0000 + 0.0000i
2.0000 + 0.0000i
6.0000
-
0.0000i
3.0000
-
0.0000i
6.0000 + 0.0000i -1.0000 + 0.0000i
Ее определитель равен единице:
>> det(W)
ans =
1.0000
-
0.0000i
Результаты этих вычислений представлены на рис. 4.36.
Рис. 4 .35. Диагонализация симметричной матрицы с помощью функции jordan()
Самоучитель Matlab
198
Рис. 4 .36. Создание на основе матрицы преобразования матрицы перехода
В заключение отметим, что если необходимо только вычислить конечную
диагональную форму, без вычисления матрицы перехода, можно воспользо-
ваться функцией diag(), которой создается диагональная матрица. Аргу-
ментом функции передается вектор (список) диагональных значений. Так,
если нужно создать диагональную форму для матрицы A, можно воспользо-
ваться командой diag(eig(A)).
199
Глава 5
Решение уравнений и оптимизация
-
Для себя я все решил.
-
Здесь решаю я!
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В этой главе обсуждаются методы решения средствами Matlab алгебраиче-
ских уравнений и систем уравнений, а также задачи оптимизации и матема-
тического (линейного и нелинейного) программирования. Сначала рассмо-
трим методы решения нелинейных алгебраических уравнений. Напомним,
что системы линейных уравнений рассматривались в предыдущей главе
в качестве примера операций с матрицами и векторами, поэтому здесь на
них останавливаться не будем.
Наше изучение методов решения уравнений начнем с краткого мини-
обзора встроенных функций Matlab, предназначенных для этого. Затем
остановимся на некоторых методах реализации поиска корней уравнений
и систем уравнений средствами программирования.
Встроенные функции для решения
уравнений
Курс у нас один – правильный.
В. Черномырдин
Для решения одного, отдельного уравнения можно воспользоваться встро-
енной функцией fzero(). У функции несколько способов вызова. Мы
рассмотрим те, что наиболее востребованы с практической точки зрения.
Допустим, нам необходимо решить уравнение () 0
fx=
.
Функция ()
fx
полностью определяет решаемое уравнение. Ссылку на эту функцию необ-
ходимо передать первым аргументом функции fzero(). Ссылкой может
служить указатель на функцию, имя (без расширения и в одинарных кавыч-
ках) m-файла с кодом функции или заключенное в одинарные кавычки вы-
ражение, определяющее функциональную зависимость ()
fx . В последнем
случае независимая переменная должна называться x , и никак иначе.
Обычно для поиска решения в числовом виде (а именно об этом идет речь)
указывают интервал, на котором ищется решение или, по крайней мере, на-
чальное приближение для корня. Начальное приближение или интервал
поиска (в виде списка из двух элементов – границ интервала) передается
вторым аргументом функции fzero().
Самоучитель Matlab
200
На заметку
Если вторым аргументом передается интервал поиска корня, то на границах ин-
тервала функция уравнения должна принимать значения разных знаков, иначе
функцией fzero() результат вычислен не будет.
Возвращает функция fzero() много полезной информации. Но самое
главное – она возвращает корень уравнения. Рассмотрим пример, представ-
ленный в документе на рис. 5.1.
Рис. 5 .1. Решение уравнения с помощью функции fzero() на интервале
Командой x=fzero('2*sin(x)^2+sin(x)-1',[0 pi/2]) вычисля-
ется корень уравнения
2
2sin( )
sin() 1 0
xx
+−
=
на интервале значений
переменной x от 0 до 2
π (на этом интервале точное решение
6
x
π
=
).
Если воспользоваться командой x=fzero('2*sin(x)^2+sin(x)-1',
[pi/2 pi]), получим решение этого же уравнения на интервале от 2
πдо
π (решение
56
x
π
=
).
На рис. 5.2 приведен фрагмент документа, в котором вместо интервала по-
иска решения указывается начальная точка для поиска решения.
Рис. 5 .2 . При вычислении корня указывается начальное значение для поиска решения
Глава 5. Решение уравнений и оптимизация
201
Предварительно в редакторе m-файлов вводится следующий код для функ-
ции, определяющей решаемое уравнение (оно такое же, как в предыдущем
случае):
function z=f(x)
z=2*sin(x)^2+sin(x)-1;
end
Окно редактора m-файлов с этим кодом представлено на рис. 5.3.
Рис. 5 .3 . Код функции в окне редактора m-файлов
Для решения уравнения с передачей ссылки на функцию двумя разными
способами используем такой код:
>> z=fzero(@f,pi/4)
z=
0.5236
>> z=fzero('f',3*pi/4)
z=
2.6180
В команде z=fzero(@f,pi/4) первым аргументом функции fzero()
передается указатель на функцию. Для получения указателя перед име-
нем функции указываем инструкцию @, в результате получаем @f. Вто-
рым аргументом указывается начальное приближение для корня урав-
нения pi/4. Это означает, что корень ищется в окрестности точки
4
π.
В результате находим (в числовом виде) корень
6
x
π
=
.
В команде
z=fzero('f',3*pi/4) в качестве ссылки на функцию передается имя
файла, в котором описана функция, определяющая уравнение. В качестве
начального для поиска корня здесь указано значение 3*pi/4. Как резуль-
тат, находится корень
56
x
π
=
.
На заметку
Из того, что мы ищем корень в окрестности какой-то точки, еще не означает,
что именно в окрестности этой точки будет найдено решение. Более того, нет
гарантии, что вообще будет найдено хоть какое-то решение.
Самоучитель Matlab
202
При вызове функции fzero() можно узнать не только корень уравнения,
но и ряд других параметров. В частности, помимо корня, в качестве резуль-
тата функцией fzero() возвращается значение функции, определяющей
уравнение, для найденного корня.
На заметку
Кроме того, дополнительными параметрами в результате возвращаются: статус
результата вычисления корня, использованный алгоритм, количество итераций
и так далее.
Еще один пример использования функции fzero() приведен в документе
на рис. 5.4.
Рис. 5 .4 . Функцией fzero() возвращается корень и значение функции в этой точке
Основу кода составляют две команды, которые рассмотрим по отдель-
ности. Первой командой F=@(x)(sin(x)+cos(x)) задается функция
() sin() cos()
Fx
x
x
=+. Специфика этой команды в ее синтаксисе. Такой
синтаксис используется для объявления анонимных функций. Общий
синтаксис такой: инструкция @, в круглых скобках список аргументов,
а в следующей паре круглых скобок указывается выражение, определяю-
щее функцию, то есть @(аргументы)(выражение). Если такую конструк-
цию присвоить в качестве значения переменной, то эта переменная будет
указателем на соответствующую функцию. Собственно, этим правилом мы
и воспользовались при определении функции для уравнения.
На заметку
Пожалуй, главное преимущество в использовании анонимных функций состоит
в том, что с их помощью функции можно объявлять прямо в командном окне.
Глава 5. Решение уравнений и оптимизация
203
Еще одна команда, которую мы использовали,
–
это [z,res]=
fzero(F,[0 pi]). Думается, аргументы функции fzero() особых во-
просов не вызовут. А результат вызова функции fzero() записывается
в две переменные: переменная z в качестве значения получает корень урав-
нения (на интервале от 0 до π - это значение
34
x
π
=
), а в переменную
res записывается значение функции F() в точке - корне уравнения.
На заметку
Если корень уравнения найден точно, то значение функции уравнения в точке
должно равняться нулю. Обычно значение корня является приближенным, по-
этому и функция в соответствующей точке отличается от нуля. Чем ближе зна-
чение функции уравнения в найденной точке решения, тем точнее вычислен
корень. Тем не менее, не следует путать точность вычисления корня с откло-
нением функции уравнения от нулевого значения в найденной точке решения.
Для решения систем уравнений (или отдельных уравнений) используют
функцию fsolve(). Принципиальное отличие функции fsolve() от
fzero() состоит в том, что первым аргументом функции fsolve()мож-
но передавать ссылку не только на скалярную, но и на векторную функ-
цию. Именно это обстоятельство позволяет решать с помощью функции
fsolve() системы дифференциальных уравнений. Все способы вызова
функции fsolve() здесь рассматривать не будем. Ограничимся лишь
основными. Обратимся к примерам. Начнем с отдельного (скалярного
уравнения). Соответствующий документ представлен на рис. 5.5.
Командный код имеет следующий вид (для удобства команды пользовате-
ля выделены жирным шрифтом, а текстовое сообщение, выводимое в ре-
зультате вычисления корня, выделено курсивом):
>> F=@(x)(2*sin(x)^2+sin(x)-1);
>> [x,res]=fsolve(F,pi/5)
Equation solved.
fsolve completed because the vector of function values is near zero
as measured by the default value of the function tolerance, and
the problem appears regular as measured by the gradient.
<stopping criteria details>
x=
0.5236
res =
8.2934e-013
Командой F=@(x)(2*sin(x)^2+sin(x)-1) непосредственно в командном
окне задается функциональная зависимость
2
() 2sin() sin() 1
Fx
x
x
=+
−
.
Уравнение
2
2sin() sin() 10
xx
+−
=
решаем командой [x,res]=fsolve
(F,pi/5). Здесь первым аргументом функции fsolve(F,pi/5) переда-
ется указатель на функцию, определяющую решаемое уравнение. Второй
Самоучитель Matlab
204
аргумент – начальное приближение для корня уравнения. Результат воз-
вращается в виде значения корня уравнения (переменная z) и значения
функции уравнения в найденном корне (переменная res). Помимо непо-
средственно результатов вычислений функцией fsolve() выводится тек-
стовое сообщение с пояснениями, насколько успешно прошли вычисления
и почему функция fsolve() завершила работу.
На заметку
Функция завершает работу, если корень, удовлетворяющий определенным кри-
териям, найден или если, например, функция не может найти корень. Иногда
формальное решение найдено, но нет уверенности, что это правильное реше-
ние. Эту и другую полезную информацию можно получить из текстового сооб-
щения.
Как отмечалось выше, важным преимуществом функции fsolve() яв-
ляется то, что с ее помощью можно решать системы уравнений. Для это-
го необходимо создать векторную функцию, которая описывает систему
уравнений, и передать ее первым аргументом функции fsolve(). Вторым
аргументом передается список начальных значений по каждой из перемен-
ных, относительно которых решается уравнение. Рассмотрим простой при-
мер (рис. 5.6).
Рис. 5.5. Решение скалярного уравнения с помощью функции fsolve()
Глава 5. Решение уравнений и оптимизация
205
Рис. 5 .6. Решение системы уравнений
Сначала командой F=@(x)[(x(1)^2+x(2)^2-25),((x(1)+1)*x(2)-
16)] задается вектор-функция из двух элементов. Эта вектор-функция
определяет решаемую систему уравнений. Определяем ее в командном
окне в виде указателя на анонимную функцию.
На заметку
Анонимную вектор-функцию в командном окне мы определяем так. Сначала, как
обычно, указывается инструкция @, затем в круглых скобках один (векторный!)
аргумент и затем две функциональные зависимости, реализованные в виде
вектор-столбца. Для этого в квадратных скобках указывается два выражения,
разделенные точкой с запятой. Векторный аргумент функции обозначен как x.
Поскольку вектор-функция состоит из двух элементов, то вполне логично, что
аргумент x также состоит из двух элементов (количество уравнений в системе
должно равняться количеству неизвестных, относительно которых решается
система). Поэтому ссылки на неизвестные переменные, относительно которых
решается система уравнений, имеют вид x(1) и x(2). Именно эти ссылки ис-
пользуются в выражениях для элементов вектор-функции.
В соответствии с теми выражениями, которые указаны при определе-
нии вектор-функции, решается система уравнений
22
1225 0
xx
+−=
и12120
xx −=
. У этой системы есть точное решение 1
3
x=и2
4
x=
. Это
решение и пытаемся найти. Чтобы поиск был удачным, желательно указать
начальную точку как можно ближе к точке решения. Мы выбираем в каче-
стве начальной точку 1 0
x=и2
1
x=
.
Самоучитель Matlab
206
На заметку
Поскольку в общем случае решение неизвестно, то задача выбора начальной
точки также представляется нетривиальной. С другой стороны, нередко успех
в поиске решения системы уравнений принципиально зависит от того, насколь-
ко удачно выбрано начальное приближение. Для этого иногда приходится про-
водить дополнительное исследование, более объемное, чем сама процедура
поиска решения.
Чтобы решить систему уравнений, используем команду z=fsolve
(F,[0 1]). В результате получаем текстовое сообщение о результатах по-
иска решения и непосредственно результат вычислений в виде списка из
двух элементов. Список присваивается в качестве значения переменной z.
Элементы списка – решение системы уравнений. Как видим, это именно то
решение, которое мы ожидали получить.
Разумеется, при решении системы уравнений вектор-функцию, определяю-
щую уравнения системы, можно реализовать не только в командном окне,
но и в m-файле. Рассмотрим программный код, представленный в докумен-
те на рис. 5.7.
Рис. 5 .7. Программный код вектор-функции
Этим кодом определяется вектор-функция из трех элементов:
function y=Eqns(x)
y(1)=x(1)+2*x(2)+x(3)-3;
y(2)=2*x(1)^2+3*x(2)^2+x(3)^2-9;
y(3)=x(1)+x(2)*x(3)-1;
end
Эта вектор-функция соответствует следующей системе алгебраиче-
ских уравнений:
123
23
0
xxx
++−
=
,
222
123
23
90
xxx
++−
=и
12
310
xx
x
+−
=
.
У этой системы есть три решения: первое - 1
1
x=−,
2
1
x=
,
3
2
x = ;второе- 1
53
x=
,
2
1
x=
,
3
23
x=−
;третье- 1
17 11
x=
,
2
311
x=−
,
3
2
x=
.
Найдем все три решения с помощью функции
Глава 5. Решение уравнений и оптимизация
207
fsolve() и вектор-функции, определенной выше. Документ представлен
на рис. 5.8.
Рис. 5 .8. Поиск всех корней системы уравнений
Кроме обычных параметров функции fsolve() в данном случае ис-
пользуются дополнительные настройки, отменяющие режим вывода тек-
стовой информации о результатах вычислений. Для этого используем
команду opts=optimset('Display','off'). Затем в команде fsolve
(@Eqns,[-2,2,3],opts) переменная opts указывается третьим аргу-
ментом функции fsolve(). В результате решение системы уравнений вы-
числяется, а текстовое сообщение не выводится.
На заметку
Дополнительные параметры для функции fsolve() задаются с помощью
функции optimset() в обычном для Matlab формате – в одинарных кавыч-
ках указывается опция и через запятую ее значение. Результат вызова функции
optimset() записывается в переменную, которая затем передается аргу-
ментом другой функции – например, функции fsolve().
Передавая разные начальные значения для поиска корней системы уравне-
ний, получаем разные решения. Это иллюстрация к тому, как важно удачно
выбрать начальное приближение для поиска решения.
Еще одна полезная функция, на которую хочется обратить вни-
мание, позволяет находить корни полиномов. Напомним, что по-
линомом степени n от переменной x называется выражение вида
1
12
1
()
...
nn
nn
n
Pxaxax
axa
−
+
=+
+
++. Таким образом, поскольку струк-
Самоучитель Matlab
208
тура полинома жестко фиксирована, для его вычисления достаточно знать
значение переменной x и коэффициенты 1
a,2
a ,...,
1
n
a + .Еслижеречьидет
о полиноме как о функциональной зависимости, то набора коэффициентов
1
a,2
a ,...,
1
n
a + достаточно для однозначного определения соответствующей
функции. Если речь заходит об обработке полинома в Matlab, то, как прави-
ло, речь идет о списке коэффициентов полинома. Это простой, экономный
и эффективный подход.
На заметку
Если полином степени n , то для его однозначного определения необходимо
указать
1
n + коэффициент, то есть на единицу больше, чем степень полино-
ма. Коэффициенты в списке необходимо указывать все, в том числе и нулевые.
Положение коэффициента в списке определяет степень соответствующего сла-
гаемого. Корнями полинома называются решения уравнения () 0
n
Px=
.
Для вычисления корней полинома используют функцию roots(). Аргу-
ментом указывается список коэффициентов полинома. Результатом воз-
вращается список корней полинома. Пример представлен в документе на
рис. 5.9.
Рис. 5 .9. Вычисление корней полинома
Сначала командой a=[1,-10,16,0,-1,10,-16] создаем список коэф-
фициентов полинома. Эти коэффициенты соответствуют полиному шестой
степени
654
2
6()
10
16
10 16
Pxxx
xx
x
=−
+−+
−
. У полинома есть четы-
ре действительных корня
1
x=−,
1
x=
,
2
x=
,
8
x = и два комплексных
xi
=
иxi
=− (здесь i - мнимая единица:
2
1
i =− ). Вычислить эти кор-
ни можно с помощью команды roots(a). В результате появляется список
корней, в том числе и комплексных (см. рис. 5.9).
Глава 5. Решение уравнений и оптимизация
209
Вычисление корней уравнений
в явном виде
Мы, конечно, все что можно, со своей сто-
роны делаем, но не все мы можем. То есть
мы можем, но совесть нам не позволяет.
Б. Ельцин
Несмотря на наличие встроенных функций, иногда полезно писать про-
цедуру поиска решений уравнения или системы уравнений в явном виде.
В этом разделе рассмотрим наиболее простые методы решения уравнений
и систем.
Простой и надежный метод решения уравнений – метод половинного де-
ления. Метод используется для поиска корня уравнения () 0
fx=
на ин-
тервале значений аргумента от a до b . Необходимое условие для примени-
мости метода (кроме непрерывности функции ()
fx) состоит в том, чтобы
функция ()
fx принимала на границах интервала значения разных знаков,
что математически можно записать в виде неравенства ()() 0
fafb≤ .Вэтом
случае на интервале поиска гарантированно находится, по крайней мере,
один корень уравнения.
На заметку
Суть метода состоит в следующем. В центре интервала, на котором ищется ко-
рень, вычисляется значение функции. Интерес представляет знак вычисленно-
го значения, поскольку в центр интервала перемещается та граница, для кото-
рой знак значения функции совпадает со знаком значения функции в центре.
В результате за одну итерацию интервал поиска уменьшается вдвое.
На рис. 5.10 показан документ с кодом функции, предназначенной для ре-
шения уравнений методом половинного деления.
Код функции EqSolve() состоит из группы вложенных условных опера-
торов. В нем также используется рекурсия. Проанализируем этот код:
function x=EqSolve(f,intl,eps)
a=intl(1);
b=intl(2);
if f(a)*f(b)>0
error('Неверно указаны границы интервала поиска корня!');
else
x=(b+a)/2;
if abs(b-a)<2*eps
return;
else
if f(a)*f(x)>0
a=x;
Самоучитель Matlab
210
else
b=x;
end
x=EqSolve(f,[a b],eps);
end
end
end
У функции три аргумента: указатель на функцию f, которая определяет ре-
шаемое уравнение, интервал поиска решения intl, а также точность вы-
числения корня eps. В качестве результата функцией возвращается значе-
ние корня уравнения. Результат записывается в переменную, которая в коде
обозначена как x.
Командами a=intl(1) и b=intl(2) считываются элементы списка
intl и запоминаются в переменных a и b. После этого в условном опера-
торе проверяется условие f(a)*f(b)>0. Если это условие выполняется,
то функция на границах интервала поиска решения принимает значения
одинаковых знаков. В этом случае командой error('Неверно указа-
ны границы интервала поиска корня!') выводится сообщение о том,
что границы диапазона для поиска решения указаны неверно. Если условие
f(a)*f(b)>0 не выполняется, можно начинать поиск решения. Начина-
Рис. 5.10. Окно редактора m-файлов с кодом функции для решения уравнений методом
половинного деления
Глава 5. Решение уравнений и оптимизация
211
ются эти самые вычисления с выполнения команды x=(b+a)/2, которой
переменной x в качестве значения присваивается среднее значение для гра-
ниц интервала. Это соответствует точке в центре интервала поиска реше-
ния. Далее реализуется такой алгоритм.
Проверяется длина интервала, на котором ищется корень. Если длина ин-
тервала не превышает удвоенное значение погрешности, процесс вычисле-
ния корня можно заканчивать. Для этого в условном операторе проверяется
условие abs(b-a)<2*eps и в случае его истинности командой return за-
вершается выполнение кода функции.
На заметку
Очевидно, что любая точка в пределах интервала поиска решения отстоит от
центральной точки интервала не больше, чем на полдлины интервала. Поэто-
му если длина интервала поиска не превышает удвоенной точности вычисления
корня, то поскольку корень находится в пределах интервала поиска, централь-
ная точка отклоняется от центра интервала не больше, чем на погрешность.
Другими словами, необходимая точность в вычислении корня выдержана.
В противном случае необходимо сместить одну из границ интервала поиска
решения. Для этого в очередном условном операторе проверяется условие
f(a)*f(x)>0. Выполнение этого условия означает, что в центре интервала
и на соответствующей границе значения функции имеют одинаковые зна-
ки. Поэтому данная граница смещается в центр, что и реализуется командой
a=x. Если условие f(a)*f(x)>0 не выполнено, в центр нужно смещать
другую границу (команда b=x).
В любом случае длина интервала поиска решения уменьшается вдвое, и за-
дача, фактически, сводится к исходной: нужно найти корень на интерва-
ле, только интервал теперь в два раза меньше. Поэтому смело используем
команду x=EqSolve(f,[a b],eps). Именно с этой командой связан ре-
курсивный вызов функции.
В командном окне вводим и выполняем следующие инструкции (выделены
жирным шрифтом):
>> f=@(x)((x-1)*(x-5)*(x-9));
>> x=EqSolve(f,[0 4],0.0001)
x=
0.9999
>> x=EqSolve(f,[2 4],0.0001)
??? Error using ==> EqSolve at 5
Неверно указаны границы интервала поиска корня!
>> x=EqSolve(f,[2 5.1],0.0001)
x=
5.0000
Самоучитель Matlab
212
>> x=EqSolve(f,[-100 15],0.0001)
x=
9.0000
Командой f=@(x)((x-1)*(x-5)*(x-9)) мы создаем функцию-полином
()(1)( 5)( 9)
fxxxx
=−−
−
и решать будем, соответственно, уравнение
()0
fx=
.
У уравнения три корня:
1
x=
,
5
x=и
9
x=
.
Эти корни бу-
дем искать. Первый корень
1
x = с точностью 0.0001 находим командой
x=EqSolve(f,[0 4],0.0001). Команда x=EqSolve(f,[2 4],0.0001)
дает пример того, как неправильно указывать интервал для поиска реше-
ния: на интервале от 2 до 4 корней нет.
Два других корня находим командами x=EqSolve(f,[2 5.1],0.0001)
и x=EqSolve(f,[-100 15],0.0001). В последнем случае указан интер-
вал, на котором находится все три корня. То, что в результате найден корень
9
x=
, в известном смысле является случайностью. Гипотетически могли
получить любой из трех корней – дело в том, какой корень будет "отсеян"
при делении интервала поиска корня. Результаты вычислений показаны на
рис. 5.11.
Рис. 5 .11. Вычисление корня уравнения методом половинного деления
Глава 5. Решение уравнений и оптимизация
213
На заметку
Алгоритм, реализованный в функции EqSolve(), далеко не самый оптималь-
ный. Он, скорее, отображает наше интуитивное представление о том, в какой по-
следовательности или в соответствии с каким принципом вычисляется корень.
Например, при рекурсивном вызове каждый раз проверяется необходимое
условие для применимости метода, хотя на самом деле это условие нужно про-
верять только самый первый раз. Вообще, что касается использования рекур-
сивных вызовов, то они редко бывают эффективными, но скорее эффектными.
Следующий метод решения алгебраических уравнений, который мы рассмо-
трим, называется методом хорд. Он сильно напоминает метод половинного
деления и состоит в следующем. Для поиска решения уравнения () 0
fx=
необходимо указать начальный интервал поиска. Необходимое условие, как
и в методе половинного деления, состоит в том, чтобы на границах интерва-
ла поиска решения функция ()
fx принимала значения разных знаков. Если
это так, то точки на графике функции ()
fx на границах интервала поиска
решения соединяются отрезком (хордой). Определяется точка пересечения
этой хорды с осью абсцисс, и вычисляется значение функции в этой точке.
В нее смещается та из границ интервала поиска решения, для которой имеет
место совпадение знаков функции. Процесс продолжается до достижения
нужной точности. Процесс графически проиллюстрирован на рис. 5.12.
Рис. 5 .12. Решение уравнения методом хорд
Для решения уравнений методом хорд создадим специальную функцию,
программный код которой приведен ниже:
function x=EqSolve2(f,intl,count,state)
n=100;
a=intl(1);
b=intl(2);
if(state)
l=b-a;
z=a-0.1*l:1.2*l/n:b+0.1*l;
Самоучитель Matlab
214
plot(z,f(z),'LineWidth',3,'Color','red');
grid on;
title('Решение уравнения вида f(x)=0 методом хорд',...
'BackgroundColor','yellow','FontSize',12,'FontWeight','bold',...
'Color','red','EdgeColor','red');
hold on;
end
for i=1:count
if(state)
L1y=[0,f(a)];
L1x=[a,a];
L2y=[0,f(b)];
L2x=[b,b];
Ly=[f(a),f(b)];
Lx=[a,b];
plot(L1x,L1y,'LineWidth',2,'Color','blue');
plot(L2x,L2y,'LineWidth',2,'Color','blue');
plot(Lx,Ly,'LineWidth',2,'Color','green');
end
c=(a*f(b)-b*f(a))/(f(b)-f(a));
if(f(a)*f(c)>0) a=c;
else b=c;
end
end
x=c;
if(state)
plot(intl(1),0,'ks','MarkerFaceColor','k','MarkerSize',5);
plot(x,0,'ko','MarkerFaceColor','k','MarkerSize',7);
plot(intl(2),0,'ks','MarkerFaceColor','k','MarkerSize',5);
hold off;
end
end
Функция называется EqSolve2(), у нее четыре аргумента, и она возвра-
щает в качестве результата корень уравнения (соответствующая перемен-
ная обозначена как x). Функция, которая определяет решаемое уравнение,
передается в виде указателя (обозначен как f) первым аргументом функции
EqSolve2(). Второй аргумент (обозначен intl) функции EqSolve2()
представляет собой список из двух элементов – через него реализуется ин-
тервал поиска корня. Третьим аргументом (переменная count) функции
EqSolve2() передается целое число итераций, выполняемых при поиске
решения уравнения. Четвертый, логический аргумент state, позволяет
переходить в режим, при котором помимо вычисления корня также отобра-
жается график функции уравнения (с некоторыми дополнительными гео-
метрическими построениями).
Глава 5. Решение уравнений и оптимизация
215
На заметку
Обычно задача состоит в том, чтобы найти корень уравнения с определенной
точностью. Оценка точности поиска корня методом хорд выполняется не так
просто, как в случае метода половинного деления. Главное преимущество ме-
тода хорд состоит в том, что он обеспечивает более быструю сходимость. Что-
бы не углубляться в несущественные в данном случае математические подроб-
ности, продолжать итерационный процесс будем не до достижения точности,
а определенное количество раз.
Командой n=100 вводится переменная, определяющая количество точек, на
основании которых будут строиться кривые. Переменным a и b командами
a=intl(1) и b=intl(2) присваиваются начальные значения границ ин-
тервала поиска решения. Затем запускается условный оператор, в котором
в качестве условия проверяется аргумент state. Равенство этого аргумен-
та значению true означает, что помимо вычисления корня будем выпол-
нять еще и геометрические построения. В данном случае строится график
функции, выполняются настройки этого графика, а также выделяются вер-
тикальными отрезками границы интервала поиска решения и первая хорда,
которая соединяет граничные точки на графике функции.
Командой l=b-a вычисляется длина интервала поиска решения. Затем
командой z=a-0.1*l:(b-a+0.2*l)/n:b+0.1*l формируется список
со значениями аргумента функции для уравнения. При этом диапазон из-
менения аргумента для отображения на графике на 20% больше длины
интервала поиска решения. Поэтому начальная точка для диапазона из-
менения аргумента вычисляется как a-0.1*l, а конечная – как b+0.1*l.
Шаг дискретности равен 1.2*l/n. График строится командой plot(z,
f(z),'LineWidth',3,'Color','red'). Опции, указанные при вызо-
ве функции plot(), означают, что толщина линии равна 3 и она красного
цвета. Координатная сетка отображается командой grid on. С помощью
функции title() задается заголовок графика. Первым аргументом функ-
ции передается текст 'Решение уравнения вида f(x)=0 методом
хорд', который и отображается в качестве заголовка. Значение 'yellow'
опции 'BackgroundColor' означает, что заголовок будет отображаться
в области желтого цвета. Опция 'FontSize' со значением 12 задает раз-
мер шрифта для отображения заголовка. О том, что шрифт будет жирным,
свидетельствует значение 'bold' для опции 'FontWeight'. Опцией
'Color' задается цвет шрифта, а опция 'EdgeColor' определяет цвет
рамки вокруг области, в которой отображается заголовок. Значения этих
опций указаны с помощью ключевого слова 'red', что означает красный
цвет. Таким образом, заголовок будет отображаться красным цветом, жир-
ным шрифтом, на желтом фоне в красной рамке.
Самоучитель Matlab
216
На заметку
Три точки ... в программном коде используются для обозначения перехода
к новой строке. Обычно к разбивке кода (в пределах одной команды) на несколь-
ко строк прибегают для повышения его читабельности.
С помощью команды hold on переходим в режим "удержания графика" –
последующие графические построения будут выполняться в том же самом
окне.
Затем запускается оператор цикла, в котором индексная переменная i про-
бегает значения от 1 до count. Эта индексная переменная нумерует ите-
рации в вычислении корня. В первую очередь при выполнении итерации
проверяется значение переменной state. При истинности значения вы-
полняется группа команд, которыми формируются списки точек для ото-
бражения отрезков, выделяющих границы текущего интервала поиска
решения, и хорды, соединяющей граничные точки на графике. Команды
такие: L1y=[0,f(a)] (y - координаты отрезка, выделяющего левую гра-
ницу интервала поиска решения), L1x=[a,a] (x - координаты отрезка,
выделяющего левую границу интервала поиска решения), L2y=[0,f(b)]
(y - координаты отрезка, выделяющего правую границу интервала поис-
ка решения), L2x=[b,b] (x - координаты отрезка, выделяющего правую
границу интервала поиска решения), Ly=[f(a),f(b)] (y - координа-
ты границ хорды, соединяющей крайние точки на графике) и Lx=[a,b]
(x - координаты границ хорды, соединяющей крайние точки на графике).
На заметку
Здесь следует учесть, что отрезки, которыми выделяется диапазон поиска
решения, имеют такие координаты. Левый отрезок соединяет точки с коорди-
натами (,0)
a
и (,())
afa , а правый отрезок соединяет точки (,0)
b и(,())
bfb .
Хорда – это отрезок, который соединяет точки (, ())
afa и (,())
bfb . Чтобы ото-
бразить отрезок, достаточно указать его начальную и конечную точки. Техниче-
ски это сводится к созданию двух списков с координатами начальной и конеч-
ной точек отрезка.
Командами plot(L1x,L1y,'LineWidth',2,'Color','blue'), plot
(L2x,L2y,'LineWidth',2,'Color','blue') и plot(Lx,Ly,'Line
Width',2,'Color','green') отображаются отрезки для выделения гра-
ниц интервала поиска решения и хорда соответственно. Все линии отобража-
ются с толщиной линии 2, вертикальные отрезки синим цветом, а хорда – зеле-
ным. Напомним, что описанные выше построения выполняются в том случае,
если значение аргумента state равно true. Следующая команда выполняется
в любом случае: c=(a*f(b)-b*f(a))/(f(b)-f(a)). Этой командой вычис-
ляется точка пересечения хорды с осью абсцисс. Затем необходимо в эту точ-
ку сместить одну из границ интервала поиска решения. Для этого в условном
Глава 5. Решение уравнений и оптимизация
217
операторе проверяем результат выражения f(a)*f(c)>0. Если результат ис-
тинен, то знак функции слева на границе интервала поиска решения и в "цен-
тре" (точке пересечения хорд с осью абсцисс) и сдвигается левая граница – для
этого выполняем команду a=c. В противном случае сдвигается правая граница
интервала поиска решения с помощью команды b=c. Блок оператора цикла по
реализации итерационного процесса на этом завершается.
На заметку
Стоит обратить внимание на два обстоятельства. Во-первых, в начале выпол-
нения алгоритма по поиску корня не проверяется необходимое условие: знаки
функции на границах интервала поиска решения должны быть разными. Во-
вторых, за каждый итерационный цикл при вычислении корня отображаются оба
отрезка на границах интервала поиска решения, и это при том, что по сравнению
с предыдущей итерацией изменяется положение только одной границы. Это не
очень рациональный подход, но на конечном результате он не сказывается.
В качестве результата функцией EqSolve2() возвращается значение, по-
лученное как значение точки пересечения хорды с осью абсцисс на послед-
ней итерации. Поэтому выполняем команду x=c.
Следующая группа команд выполняется, если значение переменной state
равно true. В частности, на графике на оси абсцисс выделяются точки на-
чального интервала поиска решения и точка, найденная в качестве корня
уравнения. Для отображения левой границы начального интервала поиска
корня уравнения используем команду plot(intl(1),0,'ks','Marker
FaceColor','k','MarkerSize',5. Здесь, поскольку в процессе поиска
корня переменные a и b меняли свое значение, значение левой границы по-
лучаем инструкцией intl(1). Это x -координата отображаемой точки. Ее
y -координата равна нулю. Инструкция 'ks' означает, что график (состоя-
щий в данном случае из одной точки) отображается черным цветом и в ка-
честве маркеров используются квадраты. Цвет заполнения маркера зада-
ется опцией 'MarkerFaceColor', значение 'k' означает черный цвет.
Опцией 'MarkerSize' задается размер маркеров – в данном случае это 5.
Точка, найденная как корень уравнения, выделяется с помощью команды
plot(x,0,'ko','MarkerFaceColor','k','MarkerSize',7). Ис-
пользуется маркер черного цвета круглой формы (инструкция 'ko'). Раз-
мер маркера установлен равным 7. Командой plot(intl(2),0,'ks',
'MarkerFaceColor','k','MarkerSize',5) правая граница интер-
вала поиска решения выделяется так же, как и левая. Наконец, командой
hold off отменяется режим удержания графика.
На рис. 5.13 показано командное окно с командами, которыми проверяется
работоспособность созданного программного кода.
Самоучитель Matlab
218
Рис. 5 .13. Командное окно с вызовом функции EqSolve2()
Рассмотрим команды подробнее. Сначала командой f=@(x)((x-1).*
(x-5).*(x-9)) определяется функция, для которой ищется корень урав-
нения. В данном случае речь идет о функции () ( 1)( 5)( 9)
fxxxx
=−−
−
.
На заметку
Функция EqSolve2() описана так, что ее первый аргумент, являющийся
ссылкой на функцию решаемого уравнения, должен применяться к аргументу-
списку. Такое предположение неявно подразумевалось при использовании
команды plot(z,f(z),'LineWidth',3,'Color','red'), когда ин-
струкцией f(z) вызывалась функция уравнения с аргументом-списком. Поэто-
му при определении функции уравнения мы использовали оператор поэлемент-
ного умножения *.
Командой EqSolve2(f,[0 4],100,false) определяется корень урав-
нения () 0
fx = на интервале от 0 до 4 на основе 100 итераций без создания
графика. В этом интервале находится корень
1
x=
, который, собственно,
и вычисляется. Чтобы увидеть еще и графические построения, используем
команду EqSolve2(f,[0 4],4,true). В данном случае корень вычис-
ляем всего четырьмя итерациями – исключительно чтобы проследить по-
следовательность построений. При большем числе итераций большинство
вспомогательных линий будет на графике неразличимо. Помимо вычис-
ления корня (с небольшой, откровенно говоря, точностью), создается еще
и рисунок, который представлен на рис. 5.14.
Метод, который рассмотрим далее, называется методом Ньютона или ме-
тодом касательных. Он также применяется для решения уравнений вида
()0
fx = и состоит в следующем.
Для поиска корня берется начальное значение для корня. В этой точке для
графика функции ()
fx строится касательная. Точка пересечения этой ка-
Глава 5. Решение уравнений и оптимизация
219
сательной с осью абсцисс выбирается как следующее приближение для ис-
комого корня.
Фактически речь идет о процессе, подразумевающем уточнение значения
корня на основе значения, вычисленного на предыдущей итерации. Чтобы
реализовать этот метод, необходимо знать не только функцию ()
fx,ноиее
производную ()
fx
′
. Кроме того, метод применим далеко не всегда.
На заметку
С математической точки зрения при известной функции можно полагать извест-
ной и производную (если такая производная существует). С автоматическим
вычислением такой производной дела обстоят хуже. Конечно, можно вычислять
производную в числовом виде, но, несмотря на кажущуюся простоту, это не са-
мая тривиальная задача. Желательно, по крайней мере, иметь представление,
к какому классу относится дифференцируемая функция.
Что касается применимости метода, то искать корень методом касательных
можно в той области, для которой знак функции совпадает со знаком произ-
водной.
Если на n -м итерационном шаге получено приближение n
x для корня
уравнения, то на следующей итерации приближение для корня определя-
Рис. 5 .14 . Графика создана в результате вычисления корня методом хорд
Самоучитель Matlab
220
ется как
1
()
()
n
nn
n
fx
xx
fx
+=−
′
. Процедура поиска корня уравнения методом
касательных иллюстрируется на рис. 5.15.
Рис. 5 .15. Решение уравнения методом касательных
Рассмотрим программный код функции, предназначенной для решения ме-
тодом касательных уравнений вида () 0
fx=
, где функция ()
fx является
полиномом. Ниже приведен программный код этой функции:
function x=EqSolve3(a,x0,eps)
z=x0;
b=polyder(a);
dz=-polyval(a,z)/polyval(b,z);
while(abs(dz)>eps)
z=z+dz;
dz=-polyval(a,z)/polyval(b,z);
end
x=z;
end
Функция называется EqSolve3() и у нее три аргумента: массив a с коэф-
фициентами исходного полинома, начальное приближение для корня x0
и параметр eps, имеющий отношение к точности вычисления корня. В каче-
стве результата функцией возвращается корень уравнения (переменная x).
Локальной переменной z командой z=x0 в качестве значения присваивает-
ся начальное приближение для корня уравнения. Командой b=polyder(a)
вычисляется список b, который представляет собой набор коэффициентов
для производной от полинома, заданного списком a. Здесь мы использо-
вали встроенную функцию polyder(), предназначенную для вычисления
производной от полинома.
Глава 5. Решение уравнений и оптимизация
221
На заметку
Производная от полинома также является полиномом. Так, если некоторый
полином
()
n
Px описывается коэффициентами 1
a,2
a,...,
n
a,
1
n
a+ (тоесть
1
12
1
()
...
nn
nn
n
Pxaxax
axa
−
+
=+
+
++), то производная от этого поли-
нома
12
121
()
(1)
.
.
.
2
nn
nn
n
Px nax
nax
axa
−−
−
′
=+
−+
++
.
Это полином
степени на единицу меньшей, чем исходный. Если коэффициенты исходно-
го полинома формируют список
12
1
[,,
.
.
.
,,
]
nn
aa
aa
a
+
=
, то коэффициенты
полинома-производной формируют список
12
1
[ , ,...,
,
]
nn
bbb bb
−
=
, причем име-
ет место соотношение
(1
)
kk
bnka
=−
+ для всех индексов
1, 2, ...,
kn
=
.
Встроенная функция polyder() по списку коэффициентов a исходного по-
линома вычисляет список b коэффициентов полинома-производной.
Командой dz=-polyval(a,z)/polyval(b,z) вычисляется прираще-
ние для переменной z. Это взятое со знаком минус отношение функции
в текущей точке z к значению производной в этой же точке. Для вычис-
ления значения полинома в точке мы использовали встроенную функцию
polyval(). Первым аргументом функции передается список коэффици-
ентов полинома. Второй аргумент функции – точка, в которой вычисляется
значение полинома.
На заметку
Вторым аргументом можно указать список значений. Тогда полином будет вы-
числен для каждого из этих значений.
После этого запускается оператор цикла. Проверяется условие
abs(dz)>eps, которое состоит в том, что добавка dz (по абсолютной ве-
личине) к текущему значению переменной z превышает погрешность eps.
На заметку
Строго говоря, это не означает, что корень вычислен с нужной точностью. Дру-
гим словами, переменная eps в общем случае не определяет точность вычис-
ления корня уравнения. Более того, такой алгоритм не обеспечивает гарантиро-
ванного завершения итерационного процесса – если начальное приближение
для корня выбрать неудачно, можем получить бесконечный цикл. Но такую экзо-
тику здесь исследовать не будем.
В операторе цикла командой z=z+dz вычисляется новое приближение для
корня, а затем командой dz=-polyval(a,z)/polyval(b,z) на основе
этого нового приближения вычисляется добавка для следующего итераци-
онного шага. После завершения оператора цикла в переменную x записыва-
ем полученный результат (команда x=z). На рис. 5.16 показано окно редак-
тора m-файлов с кодом созданной функции.
Самоучитель Matlab
222
Рис. 5 .16. Код функции EqSolve3() в окне редактора m-файлов
Результаты вычисления корней полинома с помощью функции EqSolve3()
приведены в документе на рис. 5.17.
Рис. 5 .17 . Результат вычисления корней полинома с помощью функции EqSolve3()
Здесь командой a=[1,-15,59,-45] создается список для исходного по-
линома – это в терминах переменной x выражение
32
15
59 45
xxx
−+
−
.
Глава 5. Решение уравнений и оптимизация
223
У этого полинома три корня:
1
x=
,
5
x=и
9
x=
. В последнем убедить-
ся несложно – достаточно вычислить полином в соответствующих точках.
Так, в результате выполнения команды polyval(a,[1,5,9]) получаем
список из трех нулей.
Три корня полинома находим последовательно с помощью команд
EqSolve3(a,2,0.001), EqSolve3(a,6,0.001) и EqSolve3(a,12,
0.001). Результат, как видим, вполне приемлемый.
На заметку
Стоит напомнить, что в Matlab есть встроенная функция roots() для вычисле-
ния корней полинома. В этом отношении написание собственных функций для
вычисления корней полиномов представляется малоперспективным.
Не составляет большого труда написать функцию для вычисления корня
уравнения () 0
fx=
в том случае, если общий вид функции ()
fx неизве-
стен. Один из возможных вариантов такого кода приведен ниже:
function x=EqSolve4(f,x0,eps)
z=x0;
h=eps/100;
n=1000;
for i=1:n
df=(f(z+h)-f(z-h))/2/h;
dz=f(z)/df;
z=z-dz;
if(abs(dz)<eps) break;
end
x=z;
end
У функции три аргумента: указатель на функцию уравнения f, начальное
приближение для корня x0, а также параметр eps, влияющий на точность,
с которой вычисляется корень.
Переменной z присваивается в качестве значения начальное приближение
для корня. Переменная h определяет шаг приращения аргумента для вы-
числения производной от функции уравнения. Значение этой переменной
на два порядка меньше значения аргумента eps. Переменная n определяет
максимально возможное количество итераций, выполняемых при поиске
корня уравнения. Именно эта переменная указана в качестве верхней гра-
ницы диапазона изменения индексной переменной.
В операторе цикла выполняется несколько простых команд. Командой
df=(f(z+h)-f(z-h))/2/h вычисляется значение производной для
функции в точке с аргументом z.
Самоучитель Matlab
224
На заметку
Напомним, что по определению производной от функции ()
fz называется
предел
0
()(
)
() lim
dz
fzdzfz
fz
dz
→
+−
′
=
.
В данном случае мы использовали
приближенное выражение для производной
()()
()
2
fzhfzh
fz
h
+−−
′
≈
.
В принципе, чем меньше параметр h , тем точнее выражение для производной.
Командой dz=f(z)/df вычисляется величина декремента для корня
уравнения. Командой z=z-dz вычисляется новое итерационное значе-
ние для корня уравнения. После этого выполняется условный оператор
if(abs(dz)<eps) break. Суть этой команды в том, что если изменение
значения корня на какой-то итерации становится меньше параметра eps,
итерационный процесс прекращается. Таким образом, итерационный про-
цесс продолжается до тех пор, пока изменение корня не станет достаточно
малым или пока не будет выполнено n итераций.
Полученное в качестве итерационного процесса значение z возвращается
результатом функции EqSolve4(). Окно редактора m-файлов с кодом
функции представлено на рис. 5.18.
Рис. 5 .18. Код функции EqSolve4() в окне редактора m-файлов
Примеры вызова функции EqSolve4() представлены в документе на
рис. 5.19.
Командой f=@(x)(x^3-15*x^2+59*x-45) мы определяем функцию
уравнения вида
32
()
15
59 45
fxxxx
=−
+−
. Это все тот же полином, у ко-
торого три корня:
1
x=
,
5
x=и
9
x=
. Находим все три корня этого урав-
нения командами EqSolve4(f,2,0.00001), EqSolve4(f,6,0.00001)
Глава 5. Решение уравнений и оптимизация
225
и EqSolve4(f,12,0.00001). С удовлетворением наблюдаем, что корни
найдены.
Метод Ньютона, с некоторыми модификациями, может быть расширен
для поиска решений систем алгебраических уравнений. Например, допу-
стим, что нам нужно решить систему из n уравнений 112
( , ,...,
)0
n
fxxx=
,
212
( , ,...,
)0
n
fxxx=
, ...,
12
( , ,...,
)0
nn
fxxx=
относительно переменных 1
x,
2
x,...,
n
x . Для поиска решения системы необходимо знать начальные при-
ближения для каждой из переменных. На основе нулевых (начальных)
приближений вычисляется первое приближение, затем второе, и так далее.
Рассмотрим этот процесс подробнее. Допустим, что имеется k -е прибли-
жение для решения системы
()
11
k
xx
=
,
()
22
k
xx
=
, ...,
()k
nn
xx
=
. Для расчета
следующего приближения необходимо вычислить матрицу производных:
11 12
111
21 22
212
11 12
111
12
1
...
...
ˆ
...
...
...
...
...
...
...
nn
nn
nn
n
n
n
n
nn
n
n
n
n
fx fx
fx fx
fx fx
fx fx
A
fxfx fx fx
fx fx
fx fx
−
−
−−
−
−
−
−
⎛⎞
∂∂ ∂∂
∂∂
∂∂⎟
⎜
⎟
⎜
⎟
⎜
⎟
∂∂ ∂∂
∂∂
∂∂
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
=
⎟
⎜
⎟
⎜
⎟
⎜
⎟
∂∂∂∂ ∂∂ ∂∂
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
∂∂ ∂∂
∂∂
∂∂⎟
⎜⎝⎠
Матрица вычисляется в точке k -го приближения. Другими словами, мы вы-
числяем квадратную матрицу, элементы которой
()() ()
12
( , ,...,
)
kkk
in
ij
j
fxx x
a
x
∂
=
∂
.
Рис. 5 .19. Решение уравнения с помощью функции EqSolve4()
Самоучитель Matlab
226
Введем в рассмотрение вектор
()
1
()
()2
()
...
k
k
k
k
n
x
x
x
x
⎛⎞
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
=
⎜
⎟
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎝⎠
Это вектор задает значение решения на k -м итерационном шаге. Следую-
щую итерацию можно вычислить так:
+−
(1) ()
1()
ˆ
()
kkk
xx
A
f
x
=−
. Здесь че-
рез
1
ˆ
A−
обозначена матрица, обратная к матрице ˆ
A. Через ()
()
k
fx обозначе-
на вычисленная в точке
()k
x
вектор-функция
()() ()
112
()() ()
()
212
()() ()
12
(,,
.
.
.
,)
( , ,...,
)
()
...
(,,
.
.
.
,)
kkk
n
kkk
k
n
kkk
nn
fxx x
fxx x
fx
fxx x
⎛⎞
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
=
⎜
⎟
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜⎝⎠
Ниже приведен код функции, в которой реализуется описанный выше ал-
горитм для решения системы алгебраических уравнений методом Ньютона.
Для удобства программный код снабжен комментариями.
function x=NSolve(f,x0,N)
% Начальные приближения для поиска корней:
z=x0';
% Шаг изменения аргумента для вычисления производной:
h=0.00001;
% Количество независимых переменных:
n=length(x0);
% Единичная матрица:
E=eye(n);
% Нулевой вектор-столбец:
func=zeros(n,1);
% Нулевая матрица:
A=zeros(n);
% Вложенные операторы цикла:
for k=1:N
for i=1:n
F=f{i}; % указатель на функцию получаем из списка указателей
func(i,1)=F(z'); % вычисление значения функции
for j=1:n
A(i,j)=(F(z'+h*E(:,j)')-F(z'))/h; % заполнение матрицы производных
end
end
Глава 5. Решение уравнений и оптимизация
227
% Новое приближение для вычисления корня:
z=z-A\func;
end
x=z'; % результат вычислений
end
У функции NSolve() три аргумента:
• Список f с указателями на функции, которые задают систему алгебра-
ических уравнений. Это особый список – список ячеек. Его мы будем
обсуждать отдельно. Пока же для нас важно, что элементами списка f
являются указатели на функции.
• Список x0 представляет собой набор с начальными значениями пере-
менных, относительно которых решается система уравнений.
• Аргумент N задает количество итераций, которые выполняются при по-
иске решения уравнения.
Результатом функцией возвращается список x, элементами которого явля-
ются значения переменных, полученные как решение системы уравнения.
Первой командой в функции мы объявляем локальную переменную и при-
сваиваем ей значение: z=x0'. Переменная z получает в качестве значения
транспонированный вектор (список) начальных значений x0. При присва-
ивании значения вектор x0 транспонируется.
На заметку
При вычислениях мы используем векторы-столбцы – например, вектор значе-
ний независимых переменных z или вектор значений функций func (описы-
вается далее). Вместе с тем, аргументами функции NSolve() передаются
векторы-строки. Это делается для удобства ввода команд при вызове функции
NSolve(). Поэтому периодически при вычислениях используется процедура
транспонирования векторов.
Переменная h задает значение приращения аргумента при вычислении про-
изводной.
На заметку
С одной стороны, значение переменной должно быть достаточно маленьким,
чтобы повысить точность вычисления производной. С другой стороны, всегда
следует помнить о конечной точности машинных вычислений.
Командой n=length(x0) в переменную n записывается размер списка
начальных значений, то есть количество независимых переменных, отно-
сительно которых решается система уравнений. При этом неявно предпо-
лагается, что количество уравнений в системе такое же, как и количество
независимых переменных.
Самоучитель Matlab
228
Командой E=eye(n) создаем единичную матрицу, размер которой опреде-
ляется количеством независимых переменных системы. Из этой единич-
ной матрицы мы при вычислении частных производных будем извлекать
векторы-столбцы (с единицей в соответствующей позиции). Также нам
придется создать вектор-столбец со значениями функций системы урав-
нений. В качестве нулевого приближения создаем вектор-столбец, запол-
ненный нулями. Достигается это командой func=zeros(n,1). Командой
A=zeros(n) создается нулевая матрица – квадратная, размер задается
количеством независимых переменных системы. После этого запускаются
вложенные операторы цикла. Индексная переменная внешнего цикла про-
бегает значения от 1 до N и нумерует итерации вычисления корня. Первым
внутренним циклом, индексная переменная которого пробегает значения от
1 до n (количество независимых переменных и характерный размер векто-
ров и матриц, используемых в вычислениях), заполняется вектор-столбец
со значениями функций системы и матрицы частных производных.
Во внутреннем операторе цикла командой F=f{i} переменной F в качестве
значения присваивается указатель на функцию, индекс которой в списке ука-
зателей определяется значением индексной переменной i внутреннего цикла.
Обратите внимание: вместо круглых скобок для индексирования элементов
списка f используются фигурные скобки. Поступаем так, поскольку предпо-
лагаем (и не без оснований), что список f представляет собой список ячеек.
На заметку
Главная особенность списка ячеек состоит в том, что элементами такого спи-
ска могут быть объекты разной природы – текст, числа, другие списки, и так
далее – в том числе и указатели на функции. Другими словами, список ячеек
представляет собой список, элементами которого являются ячейки. В ячейку,
в свою очередь, записывается то или иное значение. Таким образом, реаль-
ное содержимое оказывается как бы упакованным в ячейку. Такой подход не-
обходим при работе со сложными типами данных. Создание списка указателей
также предполагает создание списка ячеек. Доступ к элементам такого списка
осуществляется путем индексирования, но индекс указывается не в круглых,
а в фигурных скобках. В этом случае получаем доступ к реальному содержимо-
му соответствующей ячейки. Если выполнить индексирование с использовани-
ем круглых скобок, получим доступ к ячейке.
С помощью команды func(i,1)=F(z') вычисляется значение соответ-
ствующей функции системы при заданных значениях независимых пере-
менных. При этом аргумент, который представляет собой список значений
независимых переменных, необходимо транспонировать. Полученный ре-
зультат записывается в качестве соответствующего элемента списка func.
Затем запускается еще один внутренний оператор цикла, в рамках которого
заполняется матрица частных производных.
Глава 5. Решение уравнений и оптимизация
229
Основу тела цикла составляет команда A(i,j)=(F(z'+h*E(:,j)')-
F(z'))/h. Здесь для вычисления частной производной
12
( , ,...,
)n
j
Fxx x
x
∂
∂
от функции
12
( , ,...,
)n
Fxx x
использована приближенная формула
11
12
( ,...,
, ...,
) ( ,...,
, ...,
)
(,,
.
.
.
,)
jnj
n
n
j
FxxhxFx
x
x
Fxx x
xh
+−
∂
≈
∂
.
Другими
словами, для вычисления частной производной по аргументу jx вычисляем
значение функции с этим аргументом, увеличенным на шаг приращения h
(и фиксированными прочими аргументами), отнимаем значение функции
при всех фиксированных аргументах и полученный результат делим на шаг
приращения h .
Чтобы решить первую задачу – вычислить значение функции с увели-
ченным на шаг дискретности одним аргументом, используем инструкцию
F(z'+h*E(:,j)'). Здесь интерес представляет аргумент функции, кото-
рый представляет собой сумму z'+h*E(:,j)'. Первое слагаемое триви-
ально – это транспонированный вектор текущих значений независимых
переменных. Второе слагаемое – результат транспонирования вектора
h*E(:,j). Инструкцией E(:,j) возвращается j-й столбец единичной ма-
трицы E. У этого вектора-столбца все элементы нулевые, кроме j-го, ко-
торый равен 1. После умножения на h получаем вектор-столбец со всеми
нулевыми элементами, кроме j-го, который равен h. Поэтому в результате
выполнения инструкции z'+h*E(:,j)' получаем вектор-столбец, у кото-
рого по сравнению с вектором z' элемент в j-й строке получает прираще-
ние h, чего мы и добивались. Прочие вычисления тривиальны.
Наконец, зная вектор значений функции и матрицы производных, можем
вычислить следующее приближение для вектора значений независимых
переменных. Этой цели служит команда z=z-A\func. После того, как все
необходимые итерации выполнены, результат, после транспонирования,
записываем в переменную x с помощью команды x=z'. На этом вычисле-
ние решения системы уравнений заканчивается. Окно редактора m-файлов
с кодом созданной функции представлено на рис. 5.20.
Теперь воспользуемся созданной функцией для решения системы из двух
уравнений:
2
21
4
0
xx
yx
+−−
=
и
2
32
7
0
yxy
+−=
.
У этого уравне-
ния есть два решения. Первое
2
x=и
3
y=
, а также еще одно
7.2353
x≈
и
2.1502
y≈−
. Эти решения и попытаемся найти. На рис. 5.21 представ-
лено командное окно с примером создания списка указателей на функции
и вызовами функции NSolve() для решения соответствующей системы
нелинейных алгебраических уравнений.
Самоучитель Matlab
230
Рис. 5 .20. Окно редактора m-файлов с кодом функции
Рис. 5 .21. Командное окно с примерами использования функции NSolve() для решения
системы нелинейных уравнений
Глава 5. Решение уравнений и оптимизация
231
Вот эти команды (жирным шрифтом выделен ввод пользователя):
>> f1=@(x)(x(1)^2+2*x(1)*x(2)-x(1)-14);
>> f2=@(x)(3*x(2)+x(1)*x(2)^2-27);
>> f={f1 f2};
>> NSolve(f,[6,10],100)
ans =
23
>> NSolve(f,[8,-5],100)
ans =
7.2353
-2.1502
Командами f1=@(x)(x(1)^2+2*x(1)*x(2)-x(1)-14) и f2=@(x)
(3*x(2)+x(1)*x(2)^2-27) задаются функции уравнений системы, а пе-
ременные f1 и f2 являются указателями на эти функции.
На заметку
Функции системы уравнений определяются так, что у них один аргумент – спи-
сок значений независимых переменных. При описании функции NSolve() не-
явно предполагалось, что обрабатываются именно такие функции.
Список указателей создается командой f={f1 f2}. Как отмечалось выше,
указатели на функции формируют список ячеек. Список ячеек создается
с использованием фигурных скобок.
Командой NSolve(f,[6,10],100) пытаемся найти решение систе-
мы уравнений. Здесь мы используем 100 итераций, а в качестве на-
чальных приближений указаны значения 6 для первой переменной (т.е.
переменной x ) и 10 для второй переменной (т.е. переменной y ). В резуль-
тате находим решение
2
x=
и
3
y=
.
Если воспользоваться командой
NSolve(f,[8,-5],100), в которой указаны иные начальные приближе-
ния для поиска решения системы уравнений, в результате получаем реше-
ние
7.2353
x≈
и
2.1502
y≈−
.
Видим, что результат поиска решения существенно зависит, кроме про-
чего, от начальной точки, или начального приближения для переменных,
относительно которых решается система уравнений. Это принципиальная
зависимость, причем не связанная с конкретным рассмотренным методом
решения. Другими словами, если бы вместо метода Ньютона использовали,
например, метод градиентного спуска, также важно было бы удачно указать
начальное приближение для решения.
Самоучитель Matlab
232
Оптимизация
Денег мало, а любить людей нужно много.
Б. Ельцин
Задача по решению системы алгебраических уравнений тесно связана с за-
дачей поиска экстремума. Внесем ясность в этот вопрос. Для чего пред-
ставим, что нужно решить систему уравнений вида
12
( , ,...,
)0
kn
fxxx=
относительно переменных k
x (индекс
1, 2, ...,
kn
=
). Как часто бывает в ма-
тематике, вместо того, чтобы решать одну задачу, решим другую. А имен-
но, рассмотрим такую функцию
2
12
12
1
( , ,...,
)
( , ,...,
)
n
nkn
k
xxx
fxx x
=
Φ=
∑
.
Функция
12
( , ,...,
)n
xxx
Φ
представляет собой сумму квадратов функций
12
( , ,...,
)
kn
fxx x (индекс
1, 2, ...,
kn
=
), определяющих систему уравнений.
Что можно сказать о функции
12
(,,
.
.
.
,)
n
xxx
Φ
? Очевидно, что она неотрица-
тельна, поскольку равна сумме неотрицательных значений. Ее гипотетиче-
ское минимальное значение равняется нулю – меньше быть не может. При-
чем в ноль функция
12
(,,
.
.
.
,)
n
xxx
Φ
обращается, если все ее слагаемые равны
нулю, то есть если для всех индексов
1, 2, ...,
kn
=
выполняется условие
12
( , ,...,
)0
kn
fxxx=
. Другими словами, если мы найдем такие значения k
x
(индекс
1, 2, ...,
kn
=
), при которых
12
(,,
.
.
.
,)0
n
xxx
Φ=
(это минимальное
значение функции
12
( , ,...,
)n
xxx
Φ
), тем самым решим систему уравнений.
На заметку
Мало найти минимум функции
12
( , ,...,
)n
xxx
Φ
.
Необходимо, чтобы это был
нулевой минимум.
Рассмотрим те средства, которые представлены в Matlab для поиска экс-
тремумов функций. Сразу отметим, что существует несколько типов или
классов задач, подразумевающих поиск экстремумов (локальных или абсо-
лютных). Здесь мы рассмотрим только несколько основных задач в контек-
сте тех встроенных утилит, которые есть в Matlab.
Для поиска локального минимума скалярной функции одного аргумента на
конечном интервале используется функция fminbnd(). Функция имеет
несколько вариантов вызова. Наиболее типичный – с тремя аргументами.
Пример использования функции приведен в документе на рис. 5.22.
Командой f=@(x)(x.*(x-2).*(x-5).*(x-10)) создается функция для
вычисления экстремумов. Чтобы представить, какая это функциональная
зависимость, командами ezplot(f,[-1 11]) и grid on отображаем гра-
фик функции и координатную сетку. Результат построения представлен на
рис. 5.23.
Глава 5. Решение уравнений и оптимизация
233
Для создания графика мы использовали функцию быстрого создания
графики ezplot(). Первым аргументом функции ezplot() переда-
ется указатель на отображаемую на графике функцию, а второй аргу-
мент – список из двух элементов, определяющий диапазон изменения ар-
гумента. Функциональная зависимость ( )
( 2)( 5)( 10)
fxxxxx
=−−−
имеет два минимума и два максимума. Если воспользоваться командой
[x y]=fminbnd(f,-1,11), будет выполняться поиск минимума для
функции, определенной через указатель f, а поиск минимума выполняется
на интервале от -1 до 11. Хотя минимумов на этом интервале два, нахо-
дится только один из них – тот, что находится в интервале между точками
5
x=и
10
x=
. Чтобы найти локальный минимум, попадающий в интер-
Рис. 5.22. Поиск экстремума скалярной функции одного аргумента
Самоучитель Matlab
234
вал между точками
0
x=и
2
x=
, нужно изменить границы диапазона по-
иска минимума, как, например, в команде [x y]=fminbnd(f,-1,2).
С поиском локальных максимумов дело обстоит еще хуже. Чтобы найти
локальный максимум функции
()
yf
x
=
, достаточно найти локальный ми-
нимум функции
()
yf
x
=−
. В данном случае для поиска максимума исхо-
дной функции на интервале от 2 до 6 используем команду [x y]=fminbnd
(@(x)(-f(x)),2,6). Первым аргументом функции fminbnd() указана
инструкция @(x)(-f(x)). Это указатель на анонимную функцию, дей-
ствие которой на аргумент x состоит в вычислении значения f(x), где f
есть указатель на исходную функцию.
На заметку
Обратите внимание, что в последнем случае вычисляется минимум функции
()
yf
x
=−
. Точка минимума этой функции совпадает со значением точки мак-
симума функции
()
yf
x
=
. Соответствующий аргумент возвращается как ре-
зультат. Что касается возвращаемого значения функции, то это значение функ-
ции
()
yf
x
=−
.
Для поиска минимума функции нескольких аргументов используют функ-
цию fminsearch(). Аргументами функции указывают указатель на иссле-
Рис. 5 .23. График функции для поиска экстремума
Глава 5. Решение уравнений и оптимизация
235
дуемую функцию и список с начальными приближениями для аргументов
функции. Пример использования этой функции приведен в документе на
рис. 5.24.
Рис. 5 .24. Поиск экстремума функции нескольких переменных
Здесь ищется минимум функции
22
(,)
224
fxy x
xyy
x
=−+
−
. У функции
минимум один, и это точка
4
x=и
2
y=
. Для поиска минимума командой
f=@(x)(x(1)^2-2*x(1)*x(2)+2*x(2)^2-4*x(1)) задаем функцию
для поиска минимума, а командой [x z]=fminsearch(f,[3,1]) этот
минимум вычисляется. В качестве начальной указана точка
3
x=и
1
y=
.
Как видим, решение найдено правильно. Однако обольщаться не стоит –
просто в данном случае пример достаточно тривиальный.
На заметку
Помимо приведенных выше, в Matlab есть еще достаточно большое количе-
ство встроенных функций для решения специальных задач по оптимизации –
в основном из пакета инструментов Optimization Toolbox. Этот пакет инструмен-
тов содержит множество полезных утилит для решения задач по оптимизации
(в широком смысле этого понятия). Однако описание этой темы требует серьез-
ного углубления в математическую суть вопроса, а это выходит за рамки книги.
236
Глава 6
Интегрирование
и дифференциальные уравнения
Ваше Высочество, здесь Вам никто ничего
не скажет.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
В этой главе речь пойдет о решении (в числовом виде) дифференциальных
уравнений и вычислении определенных интегралов. В первую очередь нас
будут интересовать дифференциальные уравнения. Но начнем с вычисле-
ния интегралов. Хотя на первый взгляд может показаться, что это не очень
связанные между собой задачи, на самом деле это не совсем так.
Задача о вычислении определенного интеграла возникает, кроме прочего,
при решении дифференциального уравнения
(,)
dy
fxy
dx
=
специального
вида с функцией (, )
fxy в правой части, не зависящей от неизвестной функ-
ции ()
yx , то есть когда (,) ()
fxy fx
=
. В этом случае имеем дифференциаль-
ное уравнение вида
()
dy
fx
dx
=
. Это задача по определению первообразной
функции, если известна ее производная. Добавив сюда начальное условие
вида
00
()
yxy
=
, получим задачу Коши. Ее решение может быть представ-
лено в виде
0
0
()
()
x
x
yxy
f zdz
=+
∫ . Таким образом, задача сводится к вычис-
лению определенного интеграла
0
()
x
x
fzdz
∫ . Именно такого типа задачи рас-
смотрим для начала.
Вычисление определенных интегралов
И силой нельзя, и отступать нельзя...
Б. Ельцин
Существуют разные алгоритмы вычисления в числовом виде определенных
интегралов. Применимость того или иного метода во многом зависит от
свойств подынтегральной функции на интервале интегрирования. В Matlab
для вычисления определенных интегралов используется несколько функ-
ций, каждая из которых реализует тот или иной алгоритм. Список этих
функций приведен в табл. 6.1.
Глава 6. Интегрирование и дифференциальные уравнения
237
Табл. 6.1. Функции для выполнения численного интегрирования
Функция
Описание
quad()
Вычисление интеграла методом квадратур Симпсона. Аргумен-
тами функции обычно указывают: указатель на подынтеграль-
ную функцию и границы интегрирования. Также можно в явном
виде указать точность результата (по умолчанию составляет ве-
личину
6
10− )
quadl()
Вычисление интеграла методом квадратур Лобатто. Первым ар-
гументом передается указатель на подынтегральную функцию.
Кроме этого, указываются границы диапазона интервала инте-
грирования. Можно явно указать точность вычислений, равную
по умолчанию
6
10−
quadgk()
Вычисление интеграла методом квадратур Гаусса-Кронрода.
Аргументами методу передаются: указатель на подынтеграль-
ную функцию, нижняя граница интегрирования и верхняя грани-
ца интегрирования. Также может указываться до четырех опций
(в формате опция-запятая-значение)
quadv()
Вычисление интеграла методом квадратур Симпсона для век-
торных функций скалярного аргумента. Аргументы такие же, как
у функций quad() и quadl()
quad2d()
Вычисление двойного интеграла на плоскости. Первый аргу-
мент функции – указатель на подынтегральную функцию (двух
переменных). Кроме того, указываются пределы интегрирова-
ния (четыре аргумента) по внешней (второй и третий аргументы)
и внутренней (четвертый и пятый аргументы) переменным. Если
по внутренней переменной пределы интегрирования непосто-
янные, четвертый и/или пятый аргументы могут быть указателя-
ми на функции, определяющими уравнение границ области ин-
тегрирования. Также в формате опция-запятая-значение могут
задаваться дополнительные аргументы
dblquad()
Вычисление двойных интегралов по прямоугольной области.
Аргументами функции указываются указатель на подынтеграль-
ную функцию двух переменных, а также постоянные пределы
интегрирования по внешней и внутренней переменным. Также
можно указать точность вычислений (значение по умолчанию
6
10− ), а также метод вычислений (по умолчанию это метод ква-
дратур Симпсона)
triplequad()
Вычисление тройных интегралов по прямоугольному паралле-
лепипеду. Аргументы функции: указатель на подынтегральную
функцию трех переменных и постоянные границы интегриро-
вания по каждой из трех переменных. Можно явно указать точ-
ность (по умолчанию
6
10− ) и метод вычислений (по умолчанию
метод квадратур Симпсона)
Далее рассмотрим применение некоторых из этих функций для вычисле-
ния в числовом виде однократных, двукратных и трехкратных интегралов.
В первую очередь стоит обратить внимание на функцию quad(). Первым
аргументом этой функции передается ссылка на подынтегральную функ-
Самоучитель Matlab
238
цию (указатель на эту функцию или имя соответствующего файла). Второй
и третий аргументы – пределы интегрирования. Также может указываться
еще и точность вычислений (четвертый аргумент функции quad()). При-
мер использования этой функции для вычисления определенного интегра-
ла
4
0
ln(2)
()2
tgxdx
π
=
∫
приведен в документе на рис. 6.1.
Рис. 6 .1. Вычисление определенного интеграла с помощью функции quad()
Интеграл вычисляется командой quad(@tan,0,pi/4). Первым аргумен-
том функции quad() передается указатель на встроенную функцию вы-
числения тангенса. Второй и третий аргументы функции quad() – соот-
ветственно нижняя и верхняя границы интегрирования.
На заметку
Чтобы создать указатель на функцию, перед именем функции добавляем символ @.
Для сравнения приведен точный результат для интеграла (команда
log(2)/2). Как видим, функция quad() в данном случае с задачей спра-
вилась. К сожалению, не всегда есть возможность так просто проверить ре-
зультат вычислений.
В качестве примера применения встроенных функций интегриро-
вания рассмотрим задачу о вычислении несобственного интеграла
2
0
exp( )
2
xd
x
π
∞
−=
∫
(интеграл Пуассона). Для вычисления интеграла
используем такую последовательность команд: f=@(x)(exp(-x.^2))
(определение подынтегральной функции) и quadgk(f,0,Inf) (непо-
средственное вычисление интеграла).
Глава 6. Интегрирование и дифференциальные уравнения
239
На заметку
Функции quad() и quadl() с таким интегралом не справляются.
Кроме того, для сравнения командой sqrt(pi)/2 вычисляется (в формате
числа с плавающей точкой) точное значение для интеграла Пуассона. Ре-
зультат вычислений представлен на рис. 6.2.
Рис. 6.2. Вычисление интеграла Пуассона
Стоит обратить внимание на то, что верхняя граница интегрирования ука-
зана как Inf.
На заметку
Нередко при вычислении несобственных интегралов в качестве верхней гра-
ницы указывают большое, но конечное значение. Такой подход не гарантиру-
ет получение корректного результата. Если не углубляться в подробности, то
причина кроется в том, что понятие "большой" определяется в контексте под-
ынтегральной функции. Другими словами, чтобы узнать, какой верхний предел
интегрирования установить вместо бесконечности, необходимо исследовать
подынтегральную функцию. В рассмотренном примере эта задача, образно
выражаясь, переложена на плечи функции, с помощью которой вычисляется
интеграл.
Еще один пример связан с вычислением двойного интеграла. Задача форму-
лируется так: необходимо вычислить площадь области, ограниченной кри-
выми yx
=
и
2
yx
=
.
Сразу отметим, что точное значение для площади
этой области равно 16. Эта область находится между соответствующими
кривыми. Кривые пересекаются в точках
0
x=и
1
x=
. Область интегри-
рования представлена на рис. 6.3.
Самоучитель Matlab
240
Рис. 6 .3. Область интегрирования
Рис. 6.4 . Вычисление площади области
Глава 6. Интегрирование и дифференциальные уравнения
241
Площадь этой области можно вычислять по-разному. Командное окно с ил-
люстрацией того, как это можно делать, представлено в документе на рис. 6.4.
Площадь области вычислялась двумя разными способами – через двой-
ной и обычный интеграл. При этом для вычисления интегралов и создания
графика использовались следующие команды (ввод пользователя выделен
жирным шрифтом):
>> y1=@(x)(x.^2);
>> y2=@(x)(x);
>> quad2d(@(x,y)(x>0&x<1),0,1,y1,y2)
ans =
0.1667
>> quad(@(x)(y2(x)-y1(x)),0,1)
ans =
0.1667
>> x=0:0.01:1.1;
>> plot(x,x,'LineWidth',2)
>> hold on
>> plot(x,x.^2,'LineWidth',2)
>> grid on
>> title('Область интегрирования')
На заметку
Через двойной интеграл площадь области вычисляется как
2
2
1
01
0
1
6
x
x
x
xyx
dxdy
dx dy
<<
<<
==
∫∫∫∫.
То же значение можно получить, вычислив интеграл
1
2
0
1
()6
xxd
x
−=
∫
.
Командами y1=@(x)(x.^2) и y2=@(x)(x) задаются указатели на функ-
ции, которыми определяются кривые, ограничивающие область инте-
грирования. Двойной интеграл вычисляется командой quad2d(@(x,y)
(x>0&x<1),0,1,y1,y2). Первым аргументом функции quad2d() пере-
дается указатель на подынтегральную функцию. Подынтегральная функ-
ция в данном случае специфическая. У нее два формальных аргумента,
и возвращает она единицу (во всяком случае, в области интегрирования).
Здесь мы первым аргументом функции quad2d() передаем анонимную
функцию (@(x,y)(x>0&x<1), у которой два аргумента и которая прини-
мает два значения (единичное, если первый ее аргумент попадает в интервал
от 0 до 1, и ноль во всех прочих случаях). Второй и третий аргументы функ-
ции quad2d() – границы интервала интегрирования по переменной x .
Самоучитель Matlab
242
В качестве пределов интегрирования по переменной y передаются указате-
ли на функции, определяющие границы диапазона интегрирования по этой
переменной (четвертый и пятый аргументы). В результате получаем значе-
ние для площади области.
Командой quad(@(x)(y2(x)-y1(x)),0,1) вычисляется та же площадь,
но уже через однократный интеграл. Первым аргументом функции quad()
передается указатель на подынтегральную функцию. Указатель (инструк-
ция @(x)(y2(x)-y1(x))) создается через анонимную функцию, в кото-
рой использованы указатели y1 и y2 на функции, определяющие уравнения
кривых, ограничивающих область. Диапазон изменения подынтегральной
переменной – от 0 до 1 (второй и третий аргументы функции quad()). Ре-
зультат получаем тот же. Прочие команды предназначены для отображения
границ области, для которой вычисляется площадь. Результатом их выпол-
нения является график на рис. 6.3. Подобные команды уже использовались
ранее, поэтому особых комментариев они не требуют.
В заключение раздела рассмотрим еще одну небольшую задачу, в ко-
торой используется вычисление интеграла. Речь идет об определении
интегралов с параметрами. Здесь в качестве иллюстрации мы опреде-
лим гамма-функцию Эйлера, которая по определению вычисляется как
1
0
()
exp( )
tt
d
t
α
α
∞
−
Γ=
−
∫
.
На заметку
У гамма-функции есть ряд интересных свойств. Например, для целочислен-
ного значения n имеет место соотношение () ( 1)!
nn
Γ=−.
Для аргумента
01
α
<<имеет место соотношение ()(1 ) sin( )
αα
π
α
π
ΓΓ− =
.
Отсюда
при
12
α=
получаем (1 2)
π
Γ=.
Документ, в котором определяется гамма-функция и приводятся примеры
ее использования, приведен на рис. 6.5.
Мы использовали следующие команды (жирным шрифтом выделен ввод
пользователя):
>> Gamma=@(alpha)quadgk(@(t)t.^(alpha-1).*exp(-t),0,Inf);
>> Gamma(6)
ans =
120.0000
>> factorial(5)
ans =
120
>> Gamma(0.5)
Глава 6. Интегрирование и дифференциальные уравнения
243
ans =
1.7725
>> sqrt(pi)
ans =
1.7725
Непосредственно гамма-функция определяется командой Gamma=@(alpha)
quadgk(@(t)t.^(alpha-1).*exp(-t),0,Inf). Здесь в инструкции
вычисления интеграла quadgk(@(t)t.^(alpha-1).*exp(-t),0,Inf)
присутствует параметр alpha, который является аргументом для внешней
функции.
После определения функции ее можно использовать. В документе приведе-
но две команды вызова созданной функции. Сначала командой Gamma(6)
вычисляется значение гамма-функции с целочисленным аргументом. Ре-
зультат равен 5!=120. Именно это значение (для контроля) вычисляется
командой factorial(5). Еще одно значение гамма-функции вычисля-
ется командой Gamma(0.5). Для сравнения также приведено значение
sqrt(pi). Как видим, результаты совпадают.
Рис. 6.5 . Определение интеграла с параметром
Самоучитель Matlab
244
Дифференциальные уравнения
Вы знаете, что это будет сложнее,
чем простой ответ.
М. Горбачев
В числовом виде дифференциальные уравнения решаются, как правило,
в контексте задачи Коши (заданы начальные значения) или задачи на гра-
ничные значения (заданы значения функции и/или ее производных на гра-
ницах интервала поиска решения). В первую очередь рассмотрим задачу на
граничные значения, то есть способы решения задачи Коши.
В Matlab существует несколько функций для решения задачи Коши. Они
перечислены в табл. 6.2 с кратким описанием их главных особенностей.
Табл. 6.2. Функции для решения задачи Коши
Функция
Описание
ode45() Функция для решения нежестких дифференциальных уравнений яв-
ным методом Рунге-Кутты порядка 4 и 5
ode23() Функция для решения нежестких дифференциальных уравнений яв-
ным методом Рунге-Кутты порядка 2 и 3
ode113() Функция для решения нежестких дифференциальных уравнений
методом Адамса типа предиктор-корректор переменного порядка
ode15s() Функция для решения жестких дифференциальных уравнений ме-
тодом обратного дифференцирования
ode23s() Функция для решения жестких задач модифицированным одноша-
говым методом Розенброка
ode23t() Функция для решения жестких задач неявным методом трапеций
ode23tb() Функция для решения жестких задач с помощью неявного метода
Рунге-Кутты
ode15i() Функция для решения неявных (не разрешенных относительно про-
изводной) дифференциальных уравнений и систем
Кроме этих функций, используемых непосредственно для поиска реше-
ния дифференциальных уравнений (с начальными условиями), существу-
ет также ряд вспомогательных функций, предназначенных для обработки
и визуализации полученных результатов.
На заметку
Несколько слов об основных подходах, используемых при решении дифферен-
циальных уравнений (и их систем) в числовом виде. Одним из наиболее простых
в реализации является метод Эйлера. Суть его рассмотрим на примере решения
уравнения вида () (, )
yx fxy
′
=
с начальным условием
00
()
yxy
=
. В методе
Эйлера решение ищется по такой схеме. Выбирается достаточно малый шаг при-
ращения аргумента h . Значения функции вычисляются в узлах
0
k
xxk
h
=+
Глава 6. Интегрирование и дифференциальные уравнения
245
(то есть
1
kk
xx
h
+ =+). Значения функции в узловых точках вычисляются
по формуле
1
(,)
kkk
k
yy
h
f
x
y
+=+
.
Эта формула является следствием при-
ближенного выражения для производной
1
1
()()
() kk
k
yx
yx
yx
h
+
+
−
′
≈
.
Это
так называемый явный метод Эйлера. Здесь для оценки производной в сле-
дующем узле используются значение функции в текущем узле. Такой подход
удобен с точки зрения его практической реализации, но далеко не всегда обе-
спечивает требуемый уровень точности. Более эффективным может быть не-
явный метод, в котором значение функции в новом узле вычисляется по фор-
муле
11
(,)
kkk
k
yy
h
f
x
y
++
=+
.
Это соотношение является алгебраическим
уравнением, которое необходимо решить относительно
1
k
y + . К сожалению,
даже этот подход не является панацеей. Часто приходится использовать более
точные методы. Например, достаточно популярны методы Рунге-Кутты. Мето-
ды базируются на использовании ряда Тейлора (по переменной шага прира-
щения h ):
()
1
()()()()...
() ...
!
m
m
kk kk
k
h
yx
yxhyxhyx
yx
m
+
′
=+
=+
+
+
+
.
Это позволяет записать добавку для функции в новой узловой точке в виде
()
1
() ...
() ...
!
m
m
kkk
k
h
yyh
y
x
y
x
m
+
′
−=
++
+. В явном методе порядка
N значение функции в новой узловой точке вычисляется в виде
1
(, ,)
kkk
k
yy
h
F
y
x
h
+=+
, где функция (, ,)
kk
Fy x h является приближением
для выражения
1
()
() () ...
()
2!
!
N
N
kk
k
hh
yx
yx
yx
N
−
′′
′
++
+ . Другими словами,
в ряде Тейлора оставляют слагаемые до степени N включительно, после чего
для добавки
1
kk
yy
+−
строится аппроксимация. В неявных методах эта добав-
ка зависит не только от k
y ,ноиот
1
k
y + . Для более детальной справки отсыла-
ем читателя к специальной литературе.
Описанные методы относятся к так называемым одношаговым. В этих методах
для определения значения функции
1
k
y+ вузле
1
k
x + достаточно знать значе-
ние функции k
y в соседнем узле k
x . Многошаговые методы подразумевают вы-
числение значения функции
1
k
y+ вузле
1
k
x + на основании значений функции
в нескольких соседних узлах. К многошаговым методам относятся, например,
методы Адамса (в разных реализациях).
Выше использовалось понятие жестких и нежестких задач. Для жестких задач
характерно быстрое нарастание погрешности в процессе вычисления резуль-
тата. Такие системы чувствительны к величине шага. Поэтому при их решении
приходится применять особую изворотливость и изобретательность. К счастью,
на все эти случаи в Matlab предусмотрены встроенные функции.
Рассмотрим некоторые методы решения дифференциальных уравнений
и их систем с помощью встроенных функций Matlab. Начнем со следующей
задачи: необходимо решить дифференциальное уравнение
22
2
yyx
′=−
с начальным значением (1) 1
y=
.
Самоучитель Matlab
246
На заметку
Общее решение уравнения
22
2
yyx
′=−
имеет вид
3
32
()
(1)
yx
x
Cxx
=−
+
,
где константа C определяется исходя из начальных условий. В частности, для
начального значения (1) 1
y = получаем решение
1
()
yx
x
=
.
Для решения этой задачи используем следующую последовательность
команд:
>> f=@(x,y)(y.^2-2./x.^2);
>> [x,y]=ode45(f,1:0.1:10,1);
>> plot(x,y,'r-','LineWidth',2)
>> hold on
>> plot(x,1./x,'b:','LineWidth',2)
>> grid on
На рис. 6.6 приведен документ с командным кодом, представленным выше.
Рис. 6.6. Решение дифференциального уравнения с помощью функции ode45()
Инструкцией
f=@(x,y)(y.^2-2./x.^2)
задается
функция
22
(,)
2
fxy y
x
=− , определяющая правую часть решаемого уравнения
(,)
yf
x
y
′=
.
Указатель на эту функцию передается первым аргументом
функции ode45() в команде [x,y]=ode45(f,1:0.1:10,1). Вторым
аргументом функции ode45() передается список значений аргумента x ,
для которых вычисляются значения функции y . Третий аргумент функции
ode45() определяет начальное значение функции.
На заметку
Точка начального значения по аргументу определяется по первому элементу
списка – второго аргумента функции ode45().
В качестве результата функцией возвращается список узловых точек и вы-
численных значений функции в этих точках. Таким образом, в результате
выполнения команды [x,y]=ode45(f,1:0.1:10,1) в переменную x за-
Глава 6. Интегрирование и дифференциальные уравнения
247
писываются узловые точки (определяются вторым аргументом функции
ode45()), а в переменную y записываются значения функции, вычислен-
ные в узловых точках. Эти переменные можно использовать для создания
графика, что собственно и делается с помощью команды plot(x,y,'r-',
'LineWidth',2). Кривая для вычисленной в результате решения диф-
ференциального уравнения зависимости отображается сплошной лини-
ей красного цвета толщины 2. Для сравнения командой plot(x,1./x,
'b:','LineWidth',2) пунктирной кривой синего цвета отображается
точная аналитическая зависимость для решения рассмотренной задачи. На
рис. 6.7 показаны графики, построенные на основе точного решения диф-
ференциального уравнения и вычисленного с помощью функции ode45().
Рис. 6 .7. Результат решения дифференциального уравнения в числовом виде
Как видим, на интервале значений аргумента от 1 до 10 совпадение более
чем приемлемое. Правда, в данном случае зависимость монотонная. Если из-
менить начальное значение для функции, можно получить не такое триви-
альное решение. На рис. 6.8 представлен документ (продолжение предыду-
щего), в котором решается то же самое уравнение, но с начальным условием
(1)
0.5
y=−
.
Все практически так же, как в предыдущем случае, только внесены соот-
ветствующие изменения в начальном условии и для сравнения создается
Самоучитель Matlab
248
график функции
3
32
()
(1)
yx
x
xx
=−
+
, которая является решением соот-
ветствующей задачи. График приведен на рис. 6.9.
Рис. 6.9. Еще одно решение дифференциального уравнения
Как и в предыдущем случае, совпадение результатов хорошее.
На заметку
Описанный выше способ передачи аргументов функции ode45() характерен
и для других функций, используемых для решения дифференциальных уравне-
ний. Кроме описанных аргументов, могут использоваться также и дополнитель-
ные опции.
Рис. 6.8. Решение уравнения с новым начальным условием
Глава 6. Интегрирование и дифференциальные уравнения
249
Решение системы
дифференциальных уравнений
Ну что Вы теперь на это скажете, мой
дорогой психолог?
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
Системы дифференциальных уравнений решаются практически так же,
как и отдельные дифференциальные уравнения, с той лишь поправкой,
что придется иметь дело с векторными функциями (списком функций).
В качестве примера рассмотрим систему дифференциальных уравне-
ний () () 2exp()
xt yt
t
′
=+
и
2
() ()
ytxtt
′
=+с начальными значениями
(0)
2
x
=−
и (0)
1
y=−.
Сразу отметим, что точное решение имеет вид
2
() exp()
2
xt
ttt
=−
−
и()(1)exp()2
ytt
tt
=−
−. Для решения этой сис-
темы предварительно определяем в редакторе m-файлов следующую век-
торную функцию:
function f=DESyst(t,y)
f=[y(2)+2*exp(t);y(1)+t.^2];
end
Это функция, которая определяет правую часть уравнений системы.
А именно, речь идет о функции
2
2exp( )
(,,)
yt
ftxy
xt
⎛⎞
+
⎟
⎜
⎟
⎜
=
⎟
⎜
⎟
+
⎜
⎟
⎝⎠
.
Программный
код функции в окне редактора m-файлов представлен на рис. 6.10.
Рис. 6.10. Код векторной функции
Что касается определения функции DESyst(), то у нее два аргумента – не-
зависимая переменная t (значение переменной t ) и переменная y, которая,
как предполагается, содержит два значения – для функции ()
xt и для функ-
ции ()
yt (в момент времени t ). Ссылка на значение функции ()
xt выглядит
как y(1), а ссылка на значение функции ()
yt выглядит как y(2). Именно
эти ссылки использованы при вычислении результата функции DESyst().
Возвращаемое значение является списком (вектор-столбец). Значения
Самоучитель Matlab
250
элементов вычисляются в соответствии с уравнениями (правыми частями
уравнений), формирующими систему.
После того, как определена функция DESyst(), решение системы уравне-
ний может быть найдено с помощью такой последовательности команд:
>> [t,y]=ode45('DESyst',0:0.01:2,[-2;-1]);
>> plot(t,y,'LineWidth',2)
>> grid on
>> hold on
>> plot(t,t.*exp(t)-t.^2-2,'r:')
>> plot(t,(t-1).*exp(t)-2*t,'k--')
>> title('Решение системы дифференциальных уравнений')
Интерес
здесь
представляет
команда
[t,y]=ode45('DESy
st',0:0.01:2,[-2;-1]). Она по форме мало отличается от тех, что ис-
пользовались ранее для решения отдельного дифференциального уравне-
ния. Но поскольку первый аргумент (ссылка 'DESyst') передает вектор-
функцию, то в переменную y также записывается несколько функций:
первый столбец этой переменной определяет зависимость ()
xt , а второй
столбец определяет зависимость ()
yt . Соответствующие узловые точки
(значения независимой переменной t ) записываются в переменную t. Про-
чие команды предназначены для иллюстрации полученного решения в гра-
фическом виде. На рис. 6.11 показано командное окно с использованными
инструкциями.
Рис. 6.11. Решение системы дифференциальных уравнений
На заметку
Командой plot(t,y,'LineWidth',2) отображаются сразу две кри-
вые, для функций ()
xtи()
yt . Соответствующие данные "спрятаны" в пере-
менной y. Кроме этого, командами plot(t,t.*exp(t)-t.^2-2,'r:')
и plot(t,(t-1).*exp(t)-2*t,'k--') строятся кривые для точных ре-
шений. На рис. 6.12 числовое и аналитическое решения неразличимы.
Глава 6. Интегрирование и дифференциальные уравнения
251
Рис. 6.12. Графическое представление системы уравнений
Выше мы рассматривали уравнения и системы первого порядка. Последние
имеют особое значение, поскольку решение дифференциальных уравнений
(и их систем) более высокого порядка обычно осуществляется путем их
преобразования в систему уравнений первого порядка.
Уравнения высоких порядков
Слушайте, что это Вы со мной загадками
разговариваете? Честное слово, мне ничего
не ясно!
К/ф "Семнадцать мгновений весны"
Общая идея, которая позволяет свести уравнение высокого порядка
к системе уравнений первого порядка, состоит в том, что вместо всех
производных, кроме самой старшей, вводятся новые функции. В этих
новых обозначениях самая старшая производная будет записана как пер-
вая производная от некоторой функции. Исходное уравнение при этом
дополняется тождествами, определяющими правила введения новых
функций. Все эти соотношения содержат производные порядка не бо-
лее первого. Проиллюстрируем описанный подход на примере решения
дифференциального уравнения второго порядка. В частности, решим
Самоучитель Matlab
252
следующую задачу: () 2 () 2() 0
yxyxyx
′′
′
++=
с начальными условиями
(0) 2
y=и(0)1
y′
=
.
На заметку
У этой задачи есть точное решение () exp( )(3sin() 2cos())
yx
x
x
x
=−
+ .Его
и попытаемся найти.
Для решения этого уравнения сведем его к равноценной системе дифферен-
циальных уравнений первого порядка. Для этого переобозначим для удобства
функцию ()
yx как 1()
yx (то есть положим по определению 1() ()
yx yx
=
),
а также вводим функцию 21
() ()
yx yx
′
=
.
В этих новых обозначениях мо-
жем записать исходное уравнение в виде 21
2
() 2(() ())
yx
yx yx
′
=−
+
(здесь
мы учли, что
2
() ()
yx yx
′′
′
=
). Если дополнить это уравнение тождеством
12
() ()
yx yx
′
=
, получаем нужную систему дифференциальных уравнений. Ее
необходимо дополнить начальными условиями. Они в новых обозначениях
запишутся так: 1(0) 2
y = (следствие условия (0) 2
y=)и2(0)2
y = (след-
ствие условия (0) 1
y′
=
). На этом математические формальности заканчи-
ваются, и можно приступить непосредственно к поиску решения в Matlab.
Как и в предыдущем случае, начинаем с определения векторной функции,
которая определяет систему уравнений. Вот этот код:
function f=LDE(t,y)
f=[y(2);-2*(y(1)+y(2))];
end
Здесь все достаточно просто. Результатом функции LDE() возвращается
вектор-столбец из двух элементов, каждый из которых задает правую часть
соответствующего уравнения. При этом независимая переменная в явном
виде не используется. Окно редактора m-файлов с данным программным
кодом представлено на рис. 6.13.
Рис. 6.13. Программный код функции, определяющей систему уравнений
Для решения уравнения (системы уравнений) воспользуемся следующими
командами:
Глава 6. Интегрирование и дифференциальные уравнения
253
>> [x,y]=ode45('LDE',0:0.01:7,[2;1]);
>> plot(x,y)
>> grid on
>> hold on
>> plot(x,exp(-x).*(3*sin(x)+2*cos(x)),'r:','LineWidth',3)
>> title('Решение уравнения второго порядка')
>> legend('функция y(x)','производная y''(x)','точное решение')
Здесь командой [x,y]=ode45('LDE',0:0.01:7,[2;1]) решается сис-
тема уравнений, а результат записывается в переменную y. При этом эле-
мент y(1) содержит значение функции ()
yx (или, что то же самое, функ-
ции 1()
yx), а элемент y(2) содержит значение производной ()
yx
′
(функции
2()
yx). Кроме этой команды, инструкцией plot(x,y) строится график
функции ()
yx и ее производной ()
yx
′
.
Командой plot(x,exp(-x).*
(3*sin(x)+2*cos(x)),'r:','LineWidth',3) строится график функ-
ции ()
yx на основе точного (аналитического) выражения для решения диф-
ференциального уравнения. Используется пунктирная кривая красного
цвета толщины 3. Командное окно с соответствующими командами пока-
зано на рис. 6.14.
Рис. 6.14 . Команды для решения системы уравнений
Графики для полученного числового решения (функция ()
yx,атакжеее
производная ()
yx
′
) и точного решения представлены на рис. 6.15.
Для удобства на графике отображается также и легенда. Это позволяет за-
метить, что найденное числовое решение практически не отличается (на ис-
пользованном интервале значений аргумента) от аналитического решения.
На заметку
Как уже отмечалось, функции для решения дифференциальных уравнений,
называние которых начинается с аббревиатуры ode (сокращение от ordinary
differential equation, что означает обыкновенное дифференциальное уравне-
ние), используются аналогично тому, как это делается для функции ode45().
Самоучитель Matlab
254
Кроме того, следует помнить, что, помимо описанного способа передачи аргумен-
тов встроенным функциям для решения дифференциальных уравнений, могут пе-
редаваться и дополнительные параметры – например, допускается в точном виде
задавать точность вычислений. Что касается использования той ли иной функции,
то обычно выбирают ту, которая позволяет получить приемлемой точности резуль-
тат за оптимальное время. К сожалению, нередко единственным способом прове-
рить эффективность разных функций является метод "проб и ошибок".
Снова об интегралах
Я просто не предполагал, что моя догадка
настолько попадет в цель.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Кровавая надпись"
В начале главы отмечалось, что процедуру вычисления интеграла можно
рассматривать как частный случай решения дифференциального уравне-
ния. Здесь этой особенностью воспользуемся, чтобы вычислить интеграл.
Другими словами, в этом разделе покажем, как вычислять интегралы с по-
мощью встроенных функций для решения дифференциальных уравнений.
Для решения поставленной задачи можно использовать разные подходы.
Здесь мы создадим специальную функцию, в которой при вычислении
Рис. 6.15. Графическое представление числового решения и точного результата
Глава 6. Интегрирование и дифференциальные уравнения
255
интеграла вызывается одна из встроенных функций для решения диффе-
ренциальных уравнений (а именно, уже знакомая нам функция ode45()).
Окно редактора m-файлов с кодом этой функции показано на рис. 6.16.
Рис. 6.16. Код функции для вычисления интегралов
Функция вычисляет интеграл на указанном интервале и, кроме этого, в ре-
зультате ее выполнения строится график исходной функции и кривая для
функции-первообразной. Код функции следующий:
function res=Int(F,a,b)
f=@(x,y)F(x);
[x,y]=ode45(f,a:(b-a)/100:b,0);
res=y(length(y));
plot(x,F(x),'b-','LineWidth',2);
hold on;
plot(x,y,'r:','LineWidth',3);
plot(b,res,'rs','LineWidth',4);
plot([a,b],[res,res],'r-');
plot([b,b],[0,res],'r-');
grid on;
title('Вычисление интеграла','FontWeight','Bold','FontSize',12);
legend('функция','первообразная','результат',2);
text(a,res,num2str(res),'VerticalAlignment','bottom',...
'EdgeColor','red','BackgroundColor','yellow','FontWeight','BOLD');
hold off;
end
Самоучитель Matlab
256
Проанализируем код функции Int(). У функции три аргумента: указатель
F на подынтегральную функцию (предполагается, что это функция одного
аргумента), а также пределы интегрирования (переменные a и b в списке
аргументов функции Int()). Возвращаемое в качестве результата число-
вое значение для вычисляемого интеграла обозначено как res.
Поскольку для вычисления интеграла предполагается использовать функ-
цию ode45(), аргументом которой передается указатель на функцию двух
переменных, командой f=@(x,y)F(x) задаем такую функцию. От функ-
ции F она отличается тем, что формально у нее два аргумента (второй аргу-
мент не используется). Командой [x,y]=ode45(f,a:(b-a)/100:b,0)
вычисляется решение дифференциального уравнения вида () ()
yx fx
′
=
,
где ()
fx - подынтегральная функция. Уравнение решается на интерва-
ле значений аргумента, определяемых переменными a и b. В качестве на-
чального значения используется условие () 0
fa=
.
Это условие является
необходимым для того, чтобы вычисленное значение ()
yb давало значение
интеграла
()
b
a
fxdx
∫.
На заметку
Определенный интеграл
()()()
b
a
fxdx b
a
=Φ
−
Φ
∫
, где через ()
x
Φ обозначена
любая из первообразных для функции ()
fx (то есть ()
()
xf
x
′
Φ= ). Первообраз-
ная функция вычисляется с точностью до аддитивной константы. Если константу
выбрать так, чтобы () 0
a
Φ=
, то получим ()
()
b
a
fxdx b
=Φ
∫
. С другой стороны,
при решении дифференциального уравнения ()
()
yx fx
′
=
с начальным усло-
вием
0
()
yay
=
фактически ищем функцию ()
yx , которая является первооб-
разной для функции ()
fx . Поэтому
0
()()()()
b
a
fxdxybyayby
=− =−
∫
. Что-
бы выполнялось соотношение ()
()
b
a
yb
f xdx
=
∫ , достаточно положить 0
0
y=
.
Результат вычисляется командой res=y(length(y)). Здесь из вектора y,
который содержит значения для решения дифференциального выражения
и который вычислялся предыдущей командой, выбираем самый последний
элемент. Этот элемент имеет индекс, равный размеру списка y (инструкция
Глава 6. Интегрирование и дифференциальные уравнения
257
length(y)). Следующая далее группа команд предназначена для графиче-
ской иллюстрации результата.
На заметку
Доступ к последнему элементу списка можно получить, указав в качестве индек-
са ключевое слово end – например, y(end).
График подынтегральной функции строится с помощью команды
plot(x,F(x),'b-','LineWidth',2) (синяя линия толщины 2).
Команда hold
on нужна для перехода в режим удержания гра-
фика. Кривая для первообразной строится с помощью команды
plot(x,y,'r:','LineWidth',3) (красная пунктирная кривая толщи-
ны 3). Отдельно отображается граничная точка на кривой для первообраз-
ной, которая соответствует числовому значению вычисляемого интеграла.
Делается это командой plot(b,res,'rs','LineWidth',4). Точка вы-
деляется красным квадратом с жирными краями. Кроме этого, отображают-
ся две вспомогательные прямые: горизонтальная красная прямая строится
командой plot([a,b],[res,res],'r-') (соединяет точки с координа-
тами (a,res) и (b,res)), а вертикальная красная прямая строится коман-
дой plot([b,b],[0,res],'r-') ((соединяет точки с координатами
(b,0) и (b,res))). Координатная сетка отображается командой grid on.
Также добавляем заголовок (инструкция title('Вычисление интегра
ла','FontWeight','Bold','FontSize',12)) и легенду (инструкция
legend('функция','первообразная','результат',2)). Легенда
отображается только для первых трех кривых (подынтегральная функ-
ция, ее первообразная и отдельная точка решения). Аргумент 2 у функции
legend() означает, что легенда отображается в левом верхнем углу области
графика. Также на графике отображается текстовая метка с вычисленным
значением интеграла. Для этого используем команду на основе функции
text(). Первые два аргумента функции (a и res) – координаты точки, где
выводится текст. Третий аргумент содержит отображаемое значение. Чтобы
преобразовать число res в текст, используем команду num2str(res) на
основе встроенной функции num2str(), специально предназначенной для
таких целей. Опция 'VerticalAlignment' определяет способ выравни-
вания по вертикали позиции текстовой метки относительно точки отобра-
жения. Значение 'bottom' соответствует размещению метки над точкой
отображения. Опция 'EdgeColor' определяет цвет рамки вокруг метки
(значение 'red' означает красный). Опция 'BackgroundColor' задает
цвет фона метки (значение 'yellow' означает желтый). Для того, чтобы
использовался полужирный шрифт, для опции 'FontWeight' указывает-
ся значение 'BOLD'. Такая же опция использовалась при отображении за-
головка графика. Наконец, благодаря инструкции hold off выполняется
Самоучитель Matlab
258
выход из режима удержания графика. Поэтому если после вызова функ-
ции Int() будет строиться новый график, он заменит тот, что создан этой
функцией. На рис. 6.17 показано командное окно с выполненной командой
Int(@tan,0,pi/4), что соответствует вычислению интеграла
4
0
()
tgxdx
π
∫.
Рис. 6.17. Команда для вычисления интеграла от функции ()
()
fx tgx
=
Помимо правильного результата, также будет построен и график, представ-
ленный на рис. 6.18.
Рис. 6.18. График построен при вычислении интеграла от функции ()
()
fx tgx
=
Глава 6. Интегрирование и дифференциальные уравнения
259
Если, например, воспользоваться командой Int(@(x)x.^2.*cos(x),
0,pi/2) (рис. 6.19), получим результат, как на рис. 6.20.
Рис. 6.19. Команда для вычисления интеграла от функции
2
() cos()
fxxx
=
Рис. 6.20. График построен при вычислении интеграла от функции
2
() cos()
fxxx
=
В данном случае найдено решение для интеграла
2
2
0
cos( )
xx
d
x
π
∫
.
Самоучитель Matlab
260
Решение неявных уравнений
Дорогой Ватсон! Вы в совершенстве познали
мой дедуктивный метод. Но, увы! Ваши вы-
воды в большинстве ошибочны.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Собака Баскервилей"
Дифференциальные уравнения (первого порядка) далеко не всегда предста-
вимы в виде () (,())
yx fxyx
′
=
. Более общая форма записи дифференциаль-
ного уравнения первого порядка имеет вид (, (), ()) 0
fxyxyx
′
=
. Уравнения
вида () (,())
yx fxyx
′
=
называют уравнениями первого порядка, разрешен-
ными относительно производной. Уравнения вида (, (), ()) 0
fxyxyx
′
=
на-
зывают неявными дифференциальными уравнениями первого порядка.
Для решения неявных уравнений первого порядка в Matlab использует-
ся функция ode15i(). В качестве иллюстрации рассмотрим уравнение
()
2
2
()()
0
yxyx
x
′
− =с начальным условием (0) 1
y=
. У этой задачи есть
два решения:
2
()1
yx
x
=−и
2
()1
yx
x
=+. Первое решение, очевид-
но, применимо только для значений ||1
x < . Для решения этого уравнения
используем функцию ode15i(). Полезным будет следующий командный
код:
>> f=@(x,y,dy)(dy.*y).^2-x.^2;
>> [x,y]=ode15i(f,0:0.1:1.5,1,0);
>> plot(x,y,'b-','LineWidth',2)
>> grid on
>> hold on
>> plot(x,sqrt(1+x.^2),'r:','LineWidth',3)
Командой
f=@(x,y,dy)(dy.*y).^2-x.^2
задается
функция
22
(,,)()
fxyy yy
x
′′
=⋅−
, которая определяет неявное дифференциаль-
ное уравнение. У функции три аргумента: независимая переменная (аргу-
мент x), неизвестная функция (аргумент y) и ее производная (аргумент dy).
Все три параметра при определении функции f рассматриваются как не-
зависимые. Поиск решения дифференциального уравнения выполняется
командой [x,y]=ode15i(f,0:0.1:1.5,1,0). Особенность передачи
аргументов функции ode15i() по сравнению с прочими функциями для
решения дифференциальных уравнений состоит в следующем. Во-первых,
первым аргументом передается указатель на функцию от трех (а не двух,
как было ранее) переменных. Во-вторых, кроме списка значений независи-
мой переменной (второй аргумент функции ode15i()) и начального зна-
чения для неизвестной функции (третий аргумент функции ode15i()),
указывается также начальное значение для производной (четвертый аргу-
мент функции ode15i()). Помимо этого, могут быть и другие опции.
Глава 6. Интегрирование и дифференциальные уравнения
261
На заметку
Для уравнения первого порядка указание не только начального значения для
функции, но еще и производной означает переизбыток информации. Поэтому
все эти параметры должны быть согласованы: если в выражение, определяе-
мое функцией - первым аргументом функции ode15i(), подставить началь-
ное значение независимого аргумента, функции и ее производной, выражение
должно быть равно нулю. Здесь указаны значения (0) 1
y=и(0)0
y′
=
, что
находится в полном согласии с выражением
22
()0
yyx
′ ⋅−=
при
0
x=
.
В результате выполнения команды [x,y]=ode15i(f,0:0.1:1.5,1,0)
в переменную x записывается список значений аргумента функции на
интервале от 0 до 1.5, а в переменную y записываются значения вычис-
ляемой функции в соответствующих точках. Полученная функциональ-
ная зависимость отображается графически командой plot(x,y,'b-',
'LineWidth',2) (сплошная синяя линия). Для сравнения приводится
кривая для функции
2
()1
yx
x
=+, являющейся аналитическим реше-
нием исходного уравнения. В этом случае используем команду plot(x,
sqrt(1+x.^2),'r:','LineWidth',3) (красная пунктирная линия).
Командное окно с инструкциями для решения неявного дифференциаль-
ного уравнения показано на рис. 6.21.
Рис. 6 .21. Решение неявного дифференциального уравнения
График для полученного решения представлен на рис. 6.22.
Стоит отметить два обстоятельства. Во-первых, кривые для аналитического
и числового решений практически совпадают. Во-вторых, в процессе поис-
ка решения мы не получили никакого намека на второе решение. Хотя оно
в данном случае для всего интервала аргумента от 0 до 1.5 не подходит, оно
все же существует. К сожалению, ситуация типична для нелинейных урав-
нений (а именно к таким уравнениям обычно относятся неявные диффе-
ренциальные уравнения). При наличии нескольких независимых решений
для их поиска приходится применять более изощренные методы, чем вызов
встроенной функции.
Самоучитель Matlab
262
Краевые задачи
Меня не проведешь. Приемы сыщиков я вижу
на пять футов вглубь.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Собака Баскервилей"
При решении краевой задачи условия на функцию и/или производные за-
даются в разных точках – на границах некоторого интервала. Несмотря на
кажущуюся незначительность этого отличия по сравнению с задачей Коши,
ситуация меняется качественно. Причем настолько, что для решения крае-
вой задачи используются совершенно другие алгоритмы.
На заметку
Краевая задача подразумевает наличие как минимум двух условий, что автома-
тически означает, что порядок дифференциального уравнения должен быть не
ниже второго. Другими словами, краевая задача для дифференциального урав-
нения первого порядка не ставится. При этом решение краевой задачи подраз-
умевает сведение уравнения (системы уравнений) высокого порядка к системе
уравнений первого порядка. Поэтому в этом разделе мы будем фактически рас-
сматривать краевые задачи для систем уравнений первого порядка.
Рис. 6.22 . Графическое представление для решения
неявного дифференциального уравнения
Глава 6. Интегрирование и дифференциальные уравнения
263
Для решения краевых задач (систем) вида
(,)
dy
fxy
dx
=
в Matlab исполь-
зуются встроенные функции bvp4c() и bvp5c(). Функции практически
идентичны. Главное различие заключается в способе контроля ошибок
в процессе вычислений. В функции bvp4c() контролируется точность
выполнения соотношения исходного
(,)
dy
fxy
dx
=
,втовремякаквфунк-
ции bvp5c() контролируется реальная погрешность вычисления вектор-
ной функции ()
yx . Аргументы функциям bvp4c() и bvp5c() передают-
ся схожим образом. Так, первый и второй аргументы функций bvp5c()
и bvp4c() передаются в виде указателей на функции, которые соответ-
ственно определяют решаемое уравнение (систему уравнений) и гранич-
ные условия. Рассмотрим некоторые простые примеры.
Решим следующую краевую задачу: дифференциальное уравнение вто-
рого порядка () () 2 0
yxyx x
′′
−+
=
с граничными условиями (0) 0
y=и
(1)
1
y=−
. Задача имеет аналитическое решение () 2 3 () (1)
yx xshxsh
=−
.
Для решения этой задачи в Matlab сводим дифференциальное уравнение
второго порядка к системе уравнений первого порядка: () ()
yx zx
′
=
и
() ()2
zx yx
x
′
=−
. Граничные условия в общем случае также следует запи-
сать в новых обозначениях, но в данном случае граничные условия оста-
ются неизменными: (0) 0
y=и(1)
1
y=−
. После этого можно приступить
к процессу поиска решения краевой задачи в Matlab. В первую очередь
создаем векторную функцию, которая определяет правую часть системы
(,)
dy
fxy
dx
=
. Код этой функции приведен ниже:
function res=MyBVP(x,y)
res=[y(2) y(1)-2.*x];
end
Окно с кодом функции показано на рис. 6.23.
Рис. 6.23. Программный код функции, определяющей систему уравнений
Самоучитель Matlab
264
На заметку
Обратите внимание, что вектор-функция для системы уравнений определяется
в виде вектора-строки, а не вектора-столбца, как это было при решении задачи
Коши. Но это не принципиально.
Кроме функции, определяющей систему уравнений, необходимо задать еще
и функцию, которая определяет граничные условия. Функция для определе-
ния граничных условий должна соответствовать таким критериям. У нее два
аргумента. Первый аргумент является вектором значений функций системы
на левой границе, а второй аргумент является вектором значений функций
системы на правой границе. В качестве значения функцией, определяющей
граничные условия, возвращается список с элементами, каждый из которых
определяет граничное условие. Эти элементы представляют собой выраже-
ния, в которые входят значения функций на соответствующей границе. Что-
бы получить граничное условие, необходимо приравнять выражение к нулю.
На заметку
Обычно в граничные условия входят неизвестные функции и/или их произво-
дные. При этом максимально возможная степень производной в граничных
условиях на единицу меньше максимальной степени производной, входящей в
уравнение. Поэтому если уравнение/система сводится путем введения новых
функций к системе уравнений первого порядка, граничные условия будут со-
держать только функции, но не их производные.
Для данной задачи функция, определяющая граничные условия, задается
в таком виде:
function res=MyBC(ya,yb)
res=[ya(1) yb(1)+1];
end
У функции, как и указывалось выше, два аргумента, которые обозначены
как ya и yb. Первый аргумент ya представляет собой список значений ис-
комых функций на левой границе интервала поиска решения. Второй ар-
гумент yb представляет собой список значений искомых функций на пра-
вой границе интервала поиска решения. Ссылки ya(1) и yb(1) означают
первую функцию в системе уравнений (в данном случае это ()
yx ) соот-
ветственно на левой и правой границах. Ссылки ya(2) и yb(2) означают
вторую функцию в системе уравнений (в данном случае это ()
zx ) соответ-
ственно на левой и правой границах. В качестве результата возвращается
список из двух элементов: ya(1) и yb(1)+1. Первый элемент означает ра-
венство нулю выражения ya(1), то есть условие () 0
yx = на левой грани-
це. Второй элемент означает равенство нулю выражения yb(1)+1, то есть
условие () 1 0
yx += на правой границе. Окно с кодом функции, задающей
граничные условия, показано на рис. 6.24.
Глава 6. Интегрирование и дифференциальные уравнения
265
Рис. 6.24. Функция для определения граничных условий
После этого можно переходить к решению краевой задачи. На рис. 6.25 по-
казано командное окно с инструкциями, позволяющими найти это решение.
Рис. 6.25. Команды для вычисления решения краевой задачи
В первую очередь определяется начальное распределение для искомых
функций. Дело в том, что в алгоритме решения краевой задачи важно знать
"хорошее" (или не очень) приближение для искомой функции или функ-
ций. Именно такое начальное приближение нужно создать для набора
функций, используемых в уравнении. Причем реализуется все это в виде
специальной структуры.
На заметку
Структуры кратко обсуждаются в Приложении Б.
Структура, в свою очередь, создается с помощью встроенной функции
bvpinit(). Нужная нам структура возвращается функцией bvpinit() в ка-
честве результата. Аргументом этой функции передаются два списка. Первый
определяет набор узловых точек по независимой переменной, а второй являет-
ся списком начальных приближений каждой из неизвестных функций в узло-
вых точках. Есть разные способы передать аргументы функции bvpinit().
В рассматриваемом примере список узловых точек независимой перемен-
ной формируется с помощью еще одной встроенной функции linspace().
Функцией создается список значений. У функции три аргумента: начальное
Самоучитель Matlab
266
и конечное значение для элементов списка и количество этих элементов. Соз-
дается список равномерно распределенных элементов. Например, командой
linspace(0,1,10) создается список из десяти элементов с первым элемен-
том 0 и последним элементом 1, шаг дискретности равен 0.1. Вся команда
по созданию структуры с начальным распределением для искомых функций
имеет вид IC=bvpinit(linspace(0,1,10),[-2 0]). Результат записыва-
ется в переменную IC, а вторым аргументом функции bvpinit() передается
список [-2 0]. В этом случае для первой функции во всех узловых точках ис-
пользуется значение -2, а для второй функции во всех узловых точках исполь-
зуется значение 0. После этого командой sol=bvp4c('MyBVP','MyBC',IC)
решаем краевую задачу. Вся последовательность команд выглядит так:
>> IC=bvpinit(linspace(0,1,10),[-2 0]);
>> sol=bvp4c('MyBVP','MyBC',IC);
>> plot(sol.x,sol.y(1,:),'r-','LineWidth',2)
>> grid on
>> hold on
>> plot(sol.x,-3.*sinh(sol.x)./sinh(1)+2.*sol.x,'b:','LineWidth',3)
Результат вызова функции bvp4c() записывается в переменную sol. Это
структура, и у нее несколько полей. Поле x (полная ссылка на это поле имеет
вид sol.x) содержит набор узловых точек. Поле y (полная ссылка на это поле
имеет вид sol.y) содержит значения искомых функций в узловых точках.
Значения первой функции содержатся в строке sol.y(1,:) (функция ()
yx ),
для второй функции значения содержатся в строке sol.y(2,:) (функция
()
zx ). Поэтому чтобы построить график для вычисленной функции, можно ис-
пользовать команду plot(sol.x,sol.y(1,:),'r-','LineWidth',2)
(красная линия толщины 2). Для сравнения строится кривая аналитическо-
го решения командой plot(sol.x,-3.*sinh(sol.x)./sinh(1)+2.*
sol.x,'b:','LineWidth',3) (синяя пунктирная кривая). На рис. 6.26
показан результат создания кривых для аналитического решения и решения,
вычисленного числовыми методами.
Как и во всех предыдущих случаях, совпадение числового и аналитического
результатов более чем приемлемое.
Для разнообразия решим еще одну краевую задачу, но уже с использова-
нием функции bvp5c() и с несколько иным способом передачи аргумен-
тов. Задача формулируется так: решить дифференциальное уравнение
()()0
yx yx
′′
′
−=
с граничными условиями (0)
1
y=−и(1)(1)2
yy
′
−=
.
Задача имеет решение () exp() 2
yx
x
=−
. Общая схема решения стандарт-
ная: сводим задачу к системе уравнений первого порядка, создаем функции
для системы уравнений и граничных условий, начальное распределение
и затем с помощью встроенной функции находим решение.
Глава 6. Интегрирование и дифференциальные уравнения
267
Введем новое обозначение 1() ()
yx yx
=
и
2()
()
yx yx
′
=
. В этих новых обо-
значениях исходное дифференциальное уравнение трансформируется
в систему уравнений 12
() ()
yx yx
′
=
и22
() ()
yx yx
′
=
с граничными условия-
ми1(0)10
y+=и21
(1)(1)20
yy
−−
=
. Ниже приведен код функции, ко-
торая определяет функцию для правой части системы уравнений.
function res=MyBVP2(x,y)
res=[y(2);y(2)];
end
Код достаточно простой и, думается, особых комментариев не требует.
На рис. 6.27 этот же код представлен в окне редактора m-файлов.
Рис. 6.27. Функция для определения системы уравнений
Рис. 6.26. Графическое представление для решения краевой задачи
Самоучитель Matlab
268
Функция для определения граничных условий такая:
function res=MyBC2(ya,yb)
res=[ya(1)+1;yb(2)-yb(1)-2];
end
Код функции в окне редактора m-файлов представлен на рис. 6.28.
Рис. 6 .28. Функция для определения граничных условий
В обоих случаях функции возвращают в качестве результата вектор-
столбец. Кроме этого, для формирования начального распределения для
искомых функций создаем специальную функцию START(), которая в ка-
честве результата возвращает вектор-строку с двумя элементами:
function res=START(x)
res=[x.^2/2+x-1,x+1];
end
Первый элемент соответствует функции
2
1()
1
2
x
yx
x
=+
−
(начальное
приближение для функции ()
yx ). Второй элемент соответствует функции
2()
1
yxx
=+(начальное приближение для производной ()
1
yxx
′
=+).
Окно редактора m-файлов с кодом этой функции можно наблюдать на
рис. 6.29.
Рис. 6.29. Функция для определения начального распределения
Глава 6. Интегрирование и дифференциальные уравнения
269
Далее используем следующую последовательность команд для решения
краевой задачи:
>> IC2=bvpinit(0:0.01:1,@START);
>> sol=bvp5c(@MyBVP2,@MyBC2,IC2);
>> plot(sol.x,sol.y(1,:),'r-','LineWidth',2)
>> grid on
>> hold on
>> plot(sol.x,exp(sol.x)-2,'b:','LineWidth',3)
Инструкцией IC2=bvpinit(0:0.01:1,@START) создается начальное при-
ближение для искомых функций. Первым аргументом функции bvpinit()
Рис. 6.30 . Команды для решения краевой задачи
Рис. 6.31. Графическое представление для полученного решения
Самоучитель Matlab
270
передается список, формируемый командой 0:0.01:1. Вторым аргументом
передается указатель @START на функцию, которой вычисляется начальное рас-
пределение для искомых функций. Далее это начальное условие, вместе с ука-
зателями @MyBVP2 и @MyBC2 на функцию уравнения и граничных условий,
используется в команде sol=bvp5c(@MyBVP2,@MyBC2,IC2) для решения
краевой задачи. Окно с использованными командами показано на рис. 6.30.
Как обычно, полученный результат отображается графически вместе с кри-
вой для аналитического решения (рис. 6.31).
Традиционно кривая, построенная на основе числового решения, совпадает
с кривой, построенной на основе известной зависимости для точного (ана-
литического) решения.
Завершающий пример
Да не было ничего! Все это происки!
В. Черномырдин
Еще один простой, но полезный пример использования встроенных функ-
ций для решения дифференциальных уравнений рассмотрим в этом разде-
ле. Речь идет о том, что при определении некоторой функции используется
функция для решения дифференциального уравнения. Другими словами,
функция определяется так, что при вычислении результата решается диф-
ференциальное уравнение. Обратимся к нижеприведенному коду:
>> f=@(x,y)(2*y./x+2*x.^3);
>> F=@(x,a,ya)(ode45(f,a:(x-a)/100:x,ya));
>> [x,y]=F(3,1,0);
>> plot(x,y,'r-','LineWidth',2)
>> grid on
>> hold on
>> plot(x,x.^2.*(x.^2-1),'b:','LineWidth',3)
Командой f=@(x,y)(2*y./x+2*x.^3) определяется функция, задающая
правую часть дифференциального уравнения
3
()
()2 2
yx
yx
x
x
′
=+
. Общее
решение уравнения имеет вид
22
()()
yxxxC
=+
. Константа C вычисляет-
ся исходя из начальных условий.
Командой F=@(x,a,ya)(ode45(f,a:(x-a)/100:x,ya)) определяется
функция, в которой вычисляется решение для упомянутого выше уравне-
ния с начальным значением ya (третий аргумент функции F), которое вы-
числяется в точке a (второй аргумент функции F). Значения для решения
дифференциального уравнения вычисляются от начального значения неза-
висимой переменной до того, что передано первым аргументом функции F.
Глава 6. Интегрирование и дифференциальные уравнения
271
Результатом возвращается, как и в случае функции ode45(), список узло-
вых точек независимой переменной и значений функции в этих точках.
Примером использования созданной функции служит команда
[x,y]=F(3,1,0).Вданном случае вычисляется решение
22
()(1)
yx xx
=−
.
Полученный результат проверяется графически. На рис. 6.32 показано
командное окно с соответствующими инструкциями.
Рис. 6.32. Использование функции решения дифференциального уравнения
при определении анонимной функции
На рис. 6.33 представлен график для рассчитанной функции.
Рис. 6.33. График построен на основе результатов решения дифференциального уравнения
Самоучитель Matlab
272
Как и во всех предыдущих случаях, мы на фоне числового решения отобра-
зили кривую для аналитического решения.
Существуют и другие способы использования функции для решения диф-
ференциальных уравнений. Заинтересованный в этом вопросе читатель мо-
жет проявить здесь свою изобретательность.
273
Глава 7
Уравнения математической физики
-
Вы уже думаете об этом деле?
-
У меня оно не выходит из головы.
-
Какие Ваши соображения?
-
Запутанная история!
-
Как это верно, Ватсон!
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Собака Баскервилей"
С математической точки зрения уравнения математической физики – это
дифференциальные уравнения в частных производных второго порядка.
Такого типа уравнения описывают ряд важных физических процессов – от-
сюда, собственно, и название. Сразу следует отметить, что возможности по
аналитическому решению уравнений математической физики существенно
ограничены, поэтому решение этих уравнений в числовом виде нередко яв-
ляется единственно возможным выходом из ситуации.
В отличие от обыкновенных дифференциальных уравнений, при решении
уравнения в частных производных (второго порядка) самого этого уравне-
ния мало для получения решения.
На заметку
В уравнениях математической физики независимые переменные, равно как
и сама искомая функция, обычно имеют четкую физическую интерпретацию.
Как правило, выделяют пространственные переменные и переменную, обозна-
чающую время (для описания процессов, зависящих от времени). В зависимо-
сти от наличия переменной времени, порядка производной по этой переменной
(по пространственным переменным производные второго порядка) и способа
вхождения в уравнение, выделяют несколько типов уравнений. Уравнения гипер-
болического типа содержат вторую производную по времени и описывают коле-
бания струн и мембран. Уравнения параболического типа содержат первую про-
изводную по времени и описывают процессы теплообмена и диффузии вещества
в пространстве. Уравнения эллиптического типа не содержат производных по
времени и описывают распределение электростатического поля или стационар-
ное (установившееся) распределение температуры. Разумеется, этими задачами
применимость уравнений математической физики не исчерпывается.
Принципиально важно знать область, для которой ищется решение, а так-
же граничные и начальные условия. Более того, не имея информации об
области и граничных условиях, вообще нет смысла говорить о решении
уравнений в частных производных второго порядка. Даже незначительное,
на первый взгляд, изменение граничных условий может привести к кар-
динальному изменению в решении. Неудивительно, что в такой ситуации
Самоучитель Matlab
274
желательно иметь эффективное и надежное средство, позволяющее относи-
тельно быстро и просто получать решение. Дальше мы попытаемся убедить
читателя, что Matlab как раз является таким средством.
На заметку
В Matlab для решения уравнений в частных производных есть пара встроенных
функций и пакет инструментов Partial Differential Equation Toolbox. Встроенные
функции позволяют решать уравнения для случая, когда уравнение содержит
одну пространственную переменную (одномерная задача). С практической
точки зрения это не самый важный тип задач. Намного более эффективным
представляется использование пакета инструментов. Кроме того, в главе будет
показано, насколько полезно приложение Matlab в случае, если удается найти
точное (аналитическое) решение задачи.
Одномерный случай
А это не химера, с физическими фор-
мулами. То, что произошло сегодня,
было непредвиденным и не укладыва-
лось ни в одно, ни в другое решение.
К/ф "Семнадцать мгновений весны"
Функция pdepe() позволяет решать одномерные уравнения параболиче-
ского и эллиптического типа достаточно общего вида. У функции несколь-
ко аргументов. Первый аргумент может принимать три целочисленных зна-
чения (0, 1 или 2). Этот аргумент определяет систему координат, в которой
вычисляется пространственная производная. Значение 0 соответствует де-
картовым координатам, значение 1 соответствует полярным координатам,
а значение 2 соответствует сферическим координатам. В последних двух
случаях подразумевается, что искомая функция зависит только от одной
пространственной координаты (радиуса - соответственно в полярной или
сферической системе координат).
На заметку
"Классическое" уравнение параболического типа в одномерном случае в декар-
товых координатах имеет вид
2
2
2
(,)
(,)
utx
utx
a
t
x
∂∂
=
∂
∂
, где a - параметр задачи,
переменная t означает время, переменная x есть пространственная коорди-
ната,а (,)
ut x - неизвестная (искомая) функция от времени и координаты. В по-
лярных координатах (радиус r и угол φ ) для функции, которая не зависит от угла
φ , соответствующее уравнение запишется как
2
(,)
1
(,)
utr
r utr
a
tr
r
r
⎛⎞
∂∂
∂
⎟
⎜
=
⎟
⎜
⎟⎟
⎜
∂∂
∂
⎝⎠
.
Глава 7. Уравнения математической физики
275
В сферических координатах (радиус r и углы φ и θ ) для функции, не зависящей
от φ и θ , уравнение будет иметь вид
2
2
2
(,)
1
(,)
utr
r utr
a
tr
r
r
⎛⎞
∂∂
∂
⎟
⎜
⎟
=
⎜
⎟
⎜
⎟
⎜
∂∂
∂
⎝⎠
.
Если
ввести обобщенную пространственную координату z , то все три уравнения
можно записать в общем виде
2
(,)
1
(,)
n
n
utz
z utz
a
tz
z
z
⎛⎞
∂∂
∂
⎟
⎜
⎟
=
⎜
⎟
⎜
⎟
⎜
∂∂
∂
⎝⎠
. Здесь пере-
менная n может принимать значение
0
n = для декартовых координат,
1
n=
для полярных координат и
2
n = для сферических координат. Фактически, па-
раметр n передается первым аргументом функции pdepe().
Следует также отметить, что все три уравнения являются частным случаем бо-
лее общего уравнения для трехмерного случая
2
(,)
(,)
utr
au
tr
t
∂
=∆
∂
, где че-
рез ∆ обозначен оператор Лапласа, записанный в соответствующей системе
координат. Через вектор r обозначен полный набор пространственных коор-
динат.
Уравнения эллиптического типа обычно рассматривают в виде
(,) ()
utr fr
∆=
,
где функция ()
fr известна. Однако для одномерного случая уравнение содер-
жит производные от неизвестной функции только по одной (пространственной)
переменной и является, таким образом, обыкновенным дифференциальным
уравнением. Поэтому особого интереса в данном случае уравнение эллиптиче-
ского типа не представляет.
Помимо первого аргумента, определяющего пространственную симметрию
задачи, аргументами функции pdepe() также передаются: указатель на
функцию, определяющую решаемое уравнение (систему уравнений), указа-
тель на функцию начального распределения, указатель на функцию гранич-
ных условий, список узловых значений по переменной времени и список
узловых значений по пространственной переменной. В качестве результата
(первое значение из списка возвращаемых значений) функцией pdepe()
возвращается трехмерный массив, который содержит значения каждой
функции системы (в общем случае) уравнений в каждой из узловых точек
по времени и координате. Все перечисленные функции, которые упомина-
лись выше, должны иметь определенную структуру.
Для лучшего понимания, что и как определяется при решении уравнения
параболического типа в одномерном (по пространственной переменной)
случае, следует учесть, что функция pdepe() позволяет решать уравнения
вида
,,,
,,,
,,,
mm
uu
u
u
C xtu
x
xFxtu
S xtu
xt
x
x
x
−
⎛⎞⎛
⎛⎞
⎞
⎛⎞
∂∂
∂
∂
∂
⎟⎟
⎟
⎟
⎜⎜
⎜
⎜
=+
⎟⎟
⎟
⎟
⎜⎜
⎜
⎜
⎟⎟
⎟
⎟
⎟⎟
⎟
⎟
⎜⎜
⎜
⎜
∂∂
∂
∂
∂
⎝⎠⎝
⎝⎠
⎠
⎝⎠
.
Самоучитель Matlab
276
Здесь через (,)
uxt обозначена неизвестная функция, которую следует вы-
числить. Частные производные по времени и пространственной координа-
те от искомой функции обозначены соответственно как
u
t
∂
∂и
u
x
∂
∂
.
Функ-
ции
,,,
u
Cxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
,
,,,
u
Fxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
и
,,,
u
Sxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
известны, зависят в общем
случае от пространственной координаты, времени, неизвестной функции
и частной производной от этой функции по пространственной коорди-
нате. Определив эти три функции, мы однозначно задаем вид решаемого
уравнения. Но этого все равно мало. Необходимо еще задать граничные
и начальные условия. С начальным условием проще – это значение неиз-
вестной функции в начальный момент времени 0t , то есть условие вида
0
(,) ()
uxt fx
=
, где функция ()
fx известна. Предполагается, что граничные
условия имеют вид ()
,,
(,)
,,,
0
u
pxtu qxtF xtu
x
⎛⎞
∂⎟
⎜
+=
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
на каждой из двух
границ. Поэтому чтобы задать граничные условия, необходимо определить
функции ()
,,
pxtu и (,)
qxt отдельно на левой и правой границе. Таким об-
разом, чтобы приступить к решению задачи, необходимо определить функ-
циональные зависимости
,,,
u
Cxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
,
,,,
u
Fxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
и
,,,
u
Sxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
(для
уравнения), ()
fx (для начального условия), а также функции ()
,,
pxtu
и (,)
qxt для каждой из границ.
Функции
,,,
u
Cxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
,
,,,
u
Fxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
и
,,,
u
Sxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
описываются в функ-
ции уравнения. Функция уравнения – та функция, которая передается вто-
рым аргументом функции pdepe(). Функция уравнения принимает такие
аргументы и в таком порядке: пространственная независимая переменная,
переменная времени, неизвестная функция (относительно которой решается
уравнение) и производная от искомой функции по пространственной коор-
динате. В качестве результата функцией уравнения возвращается список из
трех элементов – это функции
,,,
u
Cxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
,
,,,
u
Fxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
и
,,,
u
Sxtu
x
⎛⎞
∂⎟
⎜
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
.
Для определения функции уравнения достаточно знать уравнение.
На заметку
Так, если решается уравнение вида
2
2
2
(,)
uu
ax
t
t
x
φ
∂∂
=+
∂
∂
(диффузия с источ-
Глава 7. Уравнения математической физики
277
ником интенсивности (,)
xt
φ
), то
,,,
1
u
Cxtu
x
⎛⎞
∂⎟
⎜
=
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
,
2
,,,
uu
Fxtu
a
xx
⎛⎞
∂∂
⎟
⎜
=
⎟
⎜
⎟⎟
⎜
∂∂
⎝⎠
и
,,,
(,)
u
Sxtu
xt
x
φ
⎛⎞
∂⎟
⎜
=
⎟
⎜
⎟⎟
⎜
∂
⎝⎠
.
Общий синтаксис объявления функции уравнения имеет следующий вид:
function [C,F,S]=имя_функции(x,t,u,du)
% здесь код функции
% x – пространственная переменная
%t-время
% u - искомая функция
% du - производная от искомой функции по пространственной координате
end
Функция начального распределения зависит только от пространственной
координаты и определяет зависимость ()
fx . Указатель на эту функцию пе-
редается третьим аргументом функции pdepe().
Функция для определения граничных условий имеет пять аргументов: зна-
чение пространственной переменной на левой границе, значение искомой
функции на левой границе, значение пространственной переменной на пра-
вой границе, значение искомой функции на правой границе, переменная
времени. В качестве результата возвращается список из четырех элементов:
значение функции ()
,,
pxtu на левой границе, значение функции (,)
qxt на
левой границе, значение функции ()
,,
pxtu на правой границе и значение
функции (,)
qxt на правой границе.
На заметку
При решении физических задач обычно рассматривают три типа граничных
условий:
1. Граничное условие первого рода (условие Дирихле), когда на границе задано
значение искомой функции.
2. Граничное условие второго рода (условие Неймана), когда на границе задано
значение производной от искомой функции.
3. Граничное условие третьего рода, когда на границе задается значение линей-
ной комбинации функции и ее производной по пространственной координате.
Граничные условия в общем случае зависят от времени.
Для начала рассмотрим простой пример. Решим задачу об остывании тон-
кого стержня длины L с коэффициентом теплопроводности
2
a ,есливна-
чальный момент центральная треть стержня нагрета до температуры 0
T,
а остальная часть стержня в начальный момент имеет нулевую температуру.
Самоучитель Matlab
278
На левой границе постоянно поддерживается нулевая температура, а пра-
вый конец стержня теплоизолированный.
Сформулируем задачу математически. Для этого обозначим через (, )
Tzτ
температуру стержня в точке с координатой z (0 zL
≤≤) в момент
времени τ ( 0
τ ≥ ). Функция
(,)
Tzτ должна удовлетворять уравне-
нию
2
2
2
TT
a
z
τ
∂∂
=
∂
∂
.
Начальное условие имеет вид
0
(, 0)
Tz
T
τ==при
32
3
LzL
≤≤и(,0)0
Tzτ ==в противном случае. Граничные усло-
вия такие: (0
,
)0
Tz
τ
==
и
(,
)0
TzL
z
τ
∂=
=
∂
. Последнее условие (равен-
ство нулю производной на правой границе) является следствием теплоизо-
лированности стержня справа. Теплоизолированность означает отсутствие
теплового потока, который пропорционален производной от температуры
по координате.
Задача содержит достаточно много феноменологических параметров. Для
решения задачи нужно либо задать числовые значения для этих параме-
тров, либо обезразмерить задачу. В последнем случае количество параме-
тров, которые необходимо задать, существенно сокращается.
Вводим новые обозначения: новая безразмерная пространственная коорди-
ната xz
L
=
(01
x
≤≤), новое безразмерное время
22
taL
τ
=
и новая
функция
0
uT
T
=
. В новых обозначениях получаем уравнение
2
2
uu
t
x
∂∂
=
∂∂
с начальным условием (, 0) 1
uxt ==при 13
23
x
≤≤и(,0)0
uxt ==
в противном случае. Граничные условия имеют вид (0
,
)0
ux
t
==
и
(1
,
)0
ux
t
x
∂=
=
∂
.
Таким образом, можем приступить к решению задачи.
Для этого создаем функцию уравнения:
function [C,F,S]=PDEfunc(x,t,u,du)
C=1;
F=du;
S=0;
end
У функции PDEfunc(), как и положено, четыре аргумента, а результатом
является список из трех элементов. Командой C=1 определяется выражение-
множитель для производной по времени в левой части уравнения (это еди-
ница). Командой F=du задается дифференцируемое по пространственной
переменной выражение в правой части уравнения (это частная произво-
Глава 7. Уравнения математической физики
279
дная первого порядка по пространственной координате). Поскольку тепло-
вые источники отсутствуют, командой S=0 определяем соответствующее
слагаемое в правой части как нулевое. Код функции PDEfunc() в окне ре-
дактора m-файлов показан на рис. 7.1.
Рис. 7 .1. Код функции уравнения
Функция, которая определяет начальное распределение температуры, на-
зывается PDEinit(), у нее один аргумент и она возвращает скалярное зна-
чение в качестве результата:
function f=PDEinit(x)
f=(x>=1/3)&(x<=2/3);
end
Здесь мы воспользовались тем обстоятельством, что логическое значение
истина обрабатывается как единица, а логическое значение ложь обраба-
тывается как ноль. Поэтому функция PDEinit() в качестве результата
возвращает значение 1, если для ее аргумента выполнено условие x>=1/3
и одновременно x<=2/3. Здесь мы использовали оператор логического и &.
В противном случае возвращается 0. На рис. 7.2 показано окно редактора
m-файлов с кодом функции.
Рис. 7 .2 . Код функции начального условия
Самоучитель Matlab
280
Еще одна функция создается для того, чтобы задать граничные условия.
Эта функция называется PDEbound() и имеет такой код:
function [p0,q0,p1,q1]=PDEbound(x0,u0,x1,u1,t)
p0=u0;
q0=0;
p1=0;
q1=1;
end
Результатом является список из четырех элементов. Переменной p0 коман-
дой p0=u0 присваивается значение функции на левой границе u0, перемен-
ной q0 присваивается нулевое значение. Переменные p0 и q0 определяют
граничное условие на левой границе. Переменные p1 и q1 определяют гра-
ничное условие на правой границе. Им присваивается соответственно ну-
левое и единичное значение. Код функции PDEbound() в окне редактора
m-файлов представлен на рис. 7.3.
Рис. 7 .3. Код функции граничных условий
Командный код, с помощью которого решается задача и в котором исполь-
зуются описанные функции, приведен ниже. Для удобства восприятия он
снабжен комментариями:
>> % пространственная координата
>> x=0:0.01:1;
>> % интервал времени
>> t=0:0.01:0.4;
>> % решение дифференциального уравнения
>> sol=pdepe(0,@PDEfunc,@PDEinit,@PDEbound,x,t);
>> % определение функции
>> u=sol(:,:,1);
>> % трехмерный график
>> surf(x,t,u)
>> title('Остывание стержня','FontWeight','BOLD','FontSize',13)
Глава 7. Уравнения математической физики
281
>> xlabel('координата x=z/L','FontWeight','BOLD')
>> ylabel('время t=a^2\tau/L^2','FontWeight','BOLD')
>> zlabel('температура u=T/T0','FontWeight','BOLD')
>> % двумерный график
>> figure
>> plot(x,u(2,:),'r-','LineWidth',2)
>> grid on
>> hold on
>> plot(x,u(5,:),'b--','LineWidth',2)
>> plot(x,u(10,:),'k:','LineWidth',2)
>> legend(strcat('t=',num2str(t(2))),strcat('t=',num2str(t(5))),
strcat('t=',num2str(t(10))))
>> title('Остывание стержня','FontWeight','BOLD','FontSize',13)
>> xlabel('координата x=z/L','FontWeight','BOLD')
>> ylabel('температура u=T/T0','FontWeight','BOLD')
Как выглядит при этом командное окно, показано на рис. 7.4.
Рис. 7 .4 . Код для вычисления решения задачи
Командой x=0:0.01:1 создается список значений пространственной
переменной. Список значений переменной времени создается командой
t=0:0.01:0.4. Решение дифференциального уравнения находим с помо-
щью команды sol=pdepe(0,@PDEfunc,@PDEinit,@PDEbound,x,t).
Аргументами функции pdepe() передаются: целочисленное (нулевое)
Самоучитель Matlab
282
значение для параметра m , определяющего пространственную симметрию
задачи, указатель @PDEfunc на функцию уравнения, указатель @PDEinit
на функцию начального распределения, указатель @PDEbound на функцию
граничных условий, список x узловых точек по пространственной перемен-
ной и список t узловых точек по времени. Результат вычислений записыва-
ется в переменную sol. Это трехмерный массив, последний индекс которого
определяет номер искомой функции в системе уравнений. Поскольку в дан-
ном случае уравнение одно, то и функция одна. Командой u=sol(:,:,1)
в переменную u записываем массив значений этой функции во всех узло-
вых точках. Эти данные используем для построения графиков.
Трехмерный график создаем с помощью команды surf(x,t,u). Добав-
ляем заголовок и подписи координатных осей (используются функции
xlabel(), ylabel() и zlabel()).
На заметку
Для отображения в текстовой строке греческой буквы τ использована инструк-
ция \tau. Такой Tex-овский стиль можно использовать и для отображения дру-
гих символов.
Этот трехмерный график дает представление о том, какова температура
стержня в разные моменты времени в разных точках, то есть позволяет оце-
нить ситуацию, что называется, в целом. График представлен на рис. 7.5.
При желании можно построить отдельные профили пространственного
распределения температуры в разные моменты времени. Так, чтобы соз-
дать еще один график, используем инструкцию figure, после чего выпол-
няем команду plot(x,u(2,:),'r-','LineWidth',2). В результате на
двумерном графике отображается контур распределения температуры по
стержню для момента времени, который записан вторым (индекс 2 в ин-
струкции u(2,:)) в списке t узловых точек по времени. Также отобра-
жаются профили для 5-го и 10-го узлов по переменной времени (команды
plot(x,u(5,:),'b--','LineWidth',2) и plot(x,u(10,:),'k:','
LineWidth',2) соответственно). Результат показан на рис. 7.6.
Чтобы можно было определить, для каких моментов времени построены про-
фили, добавляется легенда. Аргументами функции legend() передаются
однотипные инструкции вида strcat('t=',num2str(t(2))). Основу их
составляет функция объединения (конкатенации) строк strcat(). Ее аргу-
менты – объединяемые строки. Первым аргументом указано текстовое зна-
чение 't=', а второй аргумент – результат преобразования в текст числового
значения для соответствующего момента времени. Момент времени опреде-
ляется инструкцией t(2) (или другим индексом), а преобразование из чис-
лового в текстовый формат выполняется с помощью функции num2str().
Глава 7. Уравнения математической физики
283
Рис. 7 .5 . Трехмерный график построен на основе вычисленного решения
Рис. 7 .6. Двумерный график построен на основе вычисленного решения
Самоучитель Matlab
284
На заметку
Что касается физической стороны вопроса - того, как же все-таки остывает
стержень, то полученное решение позволяет сделать следующий (достаточно
очевидный априори) вывод. На левой границе температура нулевая, а на правой
сначала увеличивается. При этом выравнивается профиль распределения тем-
пературы, становясь монотонным. Затем происходит общее остывание, когда
температура падает по всей длине стержня вплоть до нуля. Правда, скорость
снижения температуры при этом становится все меньше и меньше.
Еще одно замечание касается процедуры обезразмеривания, которую мы ис-
пользовали выше при постановке задачи. Это очень удобный и полезный прием,
которым рекомендуется пользоваться систематически. Одна из главных причин
связана с тем, что такой подход позволяет существенно сократить количество
вычислений и создавать более универсальные коды. Например, в рассмотрен-
ном примере, если мы сначала зададим одно значение параметра 0
T , выпол-
ним вычисления (решим задачу), а впоследствии захотим выполнить расчеты
для другого значения 0
T , то потребности решать еще раз уравнение в частных
производных не будет. Достаточно будет ограничиться алгебраическими рас-
четами.
Знакомство со средой PDETool
Мы будем проводить иностранную
политику иностранными руками.
Дж. Буш (младший)
Среда PDETool является составной частью пакета инструментов Partial
Differential Equation. Среда предназначена для решения дифференциаль-
ных уравнений в частных производных различного типа и разной простран-
ственной размерности. Для этого есть специальный графический редактор,
который позволяет создавать геометрическую область, для которой реша-
ется задача, а также содержит утилиты для определения параметров урав-
нения.
Для запуска среды PDETool необходимо в окне приложения Matlab вы-
полнить команду Start ► Toolboxes ► Partial Differential Equation ►
PDETool GUI (pdetool) (рис. 7.7).
На заметку
Для запуска среды PDETool также можно воспользоваться командой pdetool
в командном окне.
В результате открывается окно редактора геометрических областей, пред-
ставленное на рис. 7.8.
Окно редактора состоит из панели меню, панели инструментов с кнопками
для создания графических областей, раскрывающегося списка выбора типа
Глава 7. Уравнения математической физики
285
решаемой задачи, поля-индикатора с автоматическим отображением коор-
динат курсора мыши в окне создания графической области, а также строки
формул для создания комплексных геометрических областей. В нижней
части окна редактора PDE Toolbox имеется строка состояния и кнопка за-
вершения работы с редактором Exit.
Решение задачи с помощью пакета инструментов PDEToolbox подразуме-
вает реализацию таких подзадач:
• Конструирование геометрической области, определяющей простран-
ственную симметрию задачи.
• Определение типа решаемого уравнения.
• Определение граничных условий, а если необходимо, то и начальных
(для уравнений параболического и гиперболического типа).
После этого можно переходить непосредственно к решению задачи. В ка-
честве иллюстрации рассмотрим задачу об остывании круглой пластинки
радиуса R , если известно, что в начальный момент времени пластинка
Рис. 7.7. Запуск среды PDETool
Самоучитель Matlab
286
имеет температуру 0
T . На границах пластинки на половине дуги поддер-
живается нулевая температура, а на другой половине дуги - температура
0
T . Необходимо найти температуру пластинки T как функцию простран-
ственных координат и времени. Математически эта задача может быть
записана так: решаем уравнение
2
(,,)
(,,)
T
aT
ρφτ
ρφτ
τ
∂
=∆
∂
с началь-
ным условием
0
(,, 0)
TT
ρφτ ==. Граничные условия записываются как
0
(,
,
)
TRT
ρφ
τ
==
при0 φπ
≤<и (,
,
)0
TR
ρφ
τ
==
при
2
πφπ
≤<.
Здесь мы учли, что, кроме времени τ , искомая функция температуры зави-
сит от полярных координат: радиуса ρ (расстояние от точки начала коорди-
нат до точки на плоскости) и полярного угла φ (угол между осью абсцисс
и направлением на точку – значение в пределах от 0 до 2π ). Оператор Ла-
пласа в полярных координатах
2
22
11
ρ
ρρρρφ
⎛⎞
∂∂∂
⎟
⎜
∆=
+
⎟
⎜
⎟⎟
⎜
∂∂
⎝⎠∂
.
Рис. 7 .8. Окно редактора PDE Toolbox
Глава 7. Уравнения математической физики
287
Как и ранее, начинаем с процедуры обезразмеривания задачи. Для это-
го вводим новые переменные rR
ρ
=
и
22
taR
τ
=
.
Также переопреде-
ляем функцию температуры, введя новую функцию
0
uT
T
=
.
В новых
обозначениях задача будет сформулирована следующим образом: необ-
ходимо решить уравнение
,
(, ,)
(, ,)
r
urt
urt
t
φ
φ
φ
∂
=∆
∂
с начальным услови-
ем(,,0)1
urt
φ==
, а также граничными условиями (1
,
,
)1
ur
t
φ
==
при0 φπ
≤<и (1
,
,
)0
ur
t
φ
==
при
2
πφπ
≤< . Здесь обозначено
2
,
22
11
r
r
rrrr
φ
φ
⎛⎞
∂∂∂
⎟
⎜
∆=
+
⎟
⎜
⎟⎟
⎜
∂∂
⎝⎠∂
.
Для решения задачи создаем геометрическую область. Для этого в редак-
торе среды PDEToolbox на панели инструментов щелкаем кнопку с изо-
бражением эллипса с крестом в центре. В окне создания графической об-
ласти наводим курсор мыши в центр предполагаемого круга и, удерживая
нажатой левую кнопку мыши, выделяем нужную область (круг единичного
радиуса), как показано на рис. 7.9.
Рис. 7 .9. Создание области в виде круга
Самоучитель Matlab
288
На заметку
На панели инструментов есть пиктограмма с эллипсом и пиктограмма с эллип-
сом и крестом в центре. Разница между ними заключается в том, что в первом
случае эллипс строится от края области, выделяемой с помощью мыши, а во
втором – от центра области. Какую кнопку использовать, как правило, не прин-
ципиально. Кроме того, для создания геометрических областей вместо кнопок
панели инструментов можно воспользоваться командами меню Draw.
После того, как отпускаем левую кнопку мыши, получаем область, как на
рис. 7.10.
Рис. 7 .10. Результат создания "почти круга"
Область автоматически заливается серым цветом. В области и строке фор-
мул отображается название области (в данном случае это E1 - присваивает-
ся автоматически, но его можно изменить). Поскольку создать круг точно
не удастся, получившуюся в результате область придется подправить. Для
этого наводим курсор мыши на область и выполняем двойной щелчок. В ре-
зультате открывается диалоговое окно, в котором выполняются настройки
параметров геометрической области. Для эллипса открывается диалоговое
окно Object Dialog, представленное на рис. 7.11.
Глава 7. Уравнения математической физики
289
Рис. 7 .11. Уточнение параметров геометрической области
Рис. 7 .12. Геометрическая область создана
В полях X-center и Y-center указываются координаты точки центра эллипса
(в данном случае оба значения нулевые). В полях A-semiaxes и B-semiaxes
указываются значения длин главных полуосей эллипса (для круга они оди-
наковые и совпадают с радиусом круга – в данном случае значение еди-
ничное). Угол поворота (в градусах) эллипса в плоскости определяется
значением в поле Rotation (degrees) (поворот нулевой, хотя для круга это
совершенно не важно). Наконец, в поле Name можно указать идентифика-
Самоучитель Matlab
290
тор (имя) для созданной геометрической области. Мы оставляем то имя,
которое было присвоено ей по умолчанию. Результат внесения изменений
показан на рис. 7.12.
На заметку
Строго говоря, можно было просто создать какой-нибудь эллипс, а затем изме-
нить его параметры так, чтобы он стал кругом с единичным радиусом и центром
в начале координат.
Если геометрическая область более сложная, чем та, что рассматривается
здесь, то поступают следующим образом. Сначала создают "базовые блоки",
из которых затем путем всевозможного комбинирования создается нужная об-
ласть. "Комбинирование" выполняется в строке формул Set formula. Напри-
мер, круговое кольцо можно представить как разность (в смысле операции раз-
ности множеств) двух кругов с общим центром, но разного радиуса.
На этом процесс создания геометрической области завершен, и мы при-
ступаем к определению уравнения. Для этого зададим, к какому типу
уравнение относится. Полезной окажется команда Options ► Application ►
Heat Transfer (рис. 7.13).
Рис. 7 .13. Выбор типа уравнения (задачи)
Также можно было воспользоваться раскрывающимся списком справа от
панели инструментов (рис. 7.14).
Глава 7. Уравнения математической физики
291
Рис. 7.14 . Еще один способ определить тип задачи
Рис. 7.15. Переход в режим определения параметров уравнения в частных производных
Рис. 7 .16. Определение параметров уравнения
Самоучитель Matlab
292
После этого задаем тип уравнения. Во-первых, необходимо перейти в со-
ответствующий режим, для чего используем команду PDE ► PDE Mode.
В результате окно Set formula станет неактивным, а в созданной геометри-
ческой области не будет отображаться метка названия этой области. Во-
вторых, следует задать параметры уравнения. Воспользуемся командой
PDE ► PDE Specification (рис. 7.15), в результате чего открывается однои-
менное с командой PDE Specification диалоговое окно (рис. 7.16).
На заметку
Чтобы открыть окно PDE Specification, можно щелкнуть кнопку с символами
PDE на панели инструментов среды PDETool.
Окно PDE Specification содержит в левой части несколько переключателей.
Для данных настроек активными будут два: Elliptic и Parabolic. Эллипти-
ческий тип уравнений в контексте задачи о распространении тепла исполь-
зуется, если, например, нужно найти стационарное (установившееся) рас-
пределение температуры в каком-то образце. Другими словами, уравнение
эллиптического типа мы использовали бы, если нужно было найти поле
температуры, не зависящее от времени. В нашем случае время играет важ-
ную роль, поскольку температура, очевидно, будет меняться со временем.
Поэтому переключатель должен быть установлен в положение Parabolic,
что соответствует уравнению параболического типа (содержит, кроме про-
чего, первую производную по времени). Для такого типа уравнения необ-
ходимо в полях в правой части окна PDE Specification указать значения со-
ответствующих коэффициентов уравнения. Место и роль коэффициентов
в уравнении определяем по выражению-подсказке в верхней части диало-
гового окна PDE Specification. Выражение для уравнения имеет вид (в тех
обозначениях, что использованы в диалоговом окне PDE Specification):
rho*C*T'-div(k*grad(T))=Q+h*(Text-T). Здесь T обозначает неиз-
вестную искомую функцию, а через T' обозначена производная от этой
функции по времени. Через div и grad обозначены функции вычисления
соответственно дивергенции и градиента. Все остальные параметры имеют
определенный физический смысл (на котором не будем останавливаться,
поскольку в данном случае это совершенно не важно), и их следует указать.
Что мы, собственно, и делаем. В частности, для коэффициентов rho, C и k
указываем единичные значения, а прочие коэффициенты – нулевые.
На заметку
Градиентом
от
скалярного
поля
(,,)
uxyz
называется
вектор
((,,))
uuu
graduxyz
i
j
k
xyz
∂∂∂
=++
∂∂∂
где через i , j и k обозначены
орты в декартовой системе координат. Дивергенцией от векторного поля
Глава 7. Уравнения математической физики
293
123
(,,) ( (,,)
, (,,)
, (,,))
axyz
axyzaxyzaxyz
=
называется скалярная величина
123
((,,))
aaa
divaxyz
xyz
∂∂∂
=++
∂∂∂
.
Таким образом,
222
222
( ((,,)))
uuu
divgraduxyz
u
xyz
∂∂∂
=++≡
∆
∂∂∂
.
Это для
трехмерного случая. Для двумерного пространства все точно так же, только без
координаты z .
После того, как решили все вопросы с уравнением, переходим к граничным
условиям. Здесь следует переключиться в соответствующий режим – ре-
жим определения граничных условий. Режим включается щелчком на
кнопке с изображением символов ∂Ω или выбором команды (рис. 7.17).
Рис. 7 .17 . Переход в режим определения граничных условий
Внешним проявлением перехода в режим определения граничных условий
является, пожалуй, изменение вида геометрической области для решаемой
задачи – закраска области исчезает. Следующий важный этап состоит в вы-
боре той части границы области, для которой будут задаваться условия.
Хотя может показаться, что для круга граница одна единственная, на са-
мом деле это не совсем так. По умолчанию дуга окружности разбивается
на четыре одинаковые поддуги (для каждого из четырех квадрантов). Для
каждой поддуги можно задать собственное граничное условие. Идея очень
простая: выбирается фрагмент границы и для нее задаются граничные усло-
вия. Затем выбирается следующий фрагмент и так далее. В нашем случае
для двух нижних и двух верхних поддуг условия одинаковые. Поэтому
граничные условия задаем парами – выделяем сначала две нижних подду-
ги (которые образуют нижнюю полудугу). Для этого, удерживая нажатой
кнопку <Shift>, щелкаем на соответствующем фрагменте левой кнопкой
мыши (рис. 7.18).
При выделении поддуга меняет цвет с красного на черный. После того
как две нижних поддуги (нижняя полудуга) выделены, задаем граничные
Самоучитель Matlab
294
Рис. 7 .18. Выбор дуги на границе области перед определением граничных условий
Рис. 7.19. Переход в режим определения граничных условий
Глава 7. Уравнения математической физики
295
условия для этих поддуг. С этой целью используем команду Boundary ►
Specify Boundary Conditions (рис. 7.19).
В результате появляется диалоговое окно Boundary Condition, в котором за-
дается тип граничных условий и параметров этих условий (рис. 7.20).
Рис. 7.20. Определение граничных условий для первой полудуги
Слева с помощью переключателя выбирается тип граничных условий -
Неймана или Дирихле (переключатель в положении Neumann или Dirichlet
соответственно). Поскольку в решаемой здесь задаче задаются значения
функции на границе, устанавливаем переключатель в положение Dirichlet
(решаем задачу Дирихле). Граничное условие в строке-подсказке записано
как h*T=r. Здесь, напомним, через T обозначена искомая функция. Параме-
тры h и r задаем. Для нижней полудуги граничное условие нулевое. Поэто-
му коэффициенту r указываем нулевое значение, а коэффициенту h – нену-
левое (для конкретики единичное). Аналогичную процедуру проделываем
для верхней полудуги – выделяем две верхние поддуги и выбираем коман-
ду Boundary ► Specify Boundary Conditions. Настройки диалогового окна
Boundary Conditions для верхней полудуги показаны на рис. 7.21.
Рис. 7.21. Граничные условия на второй полудуге
Самоучитель Matlab
296
От предыдущего случая отличие в том, что коэффициент r равен единице.
На этом процесс определения граничных условий закончен. Следующий
шаг – определение начальных условий. Для этого в меню Solve выбираем
команду Parameters (рис. 7.22).
Рис. 7 .22 . Переход в режим определения начальных условий
Открывается окно Solve Parameters, в котором задаются параметры на-
чального распределения для искомой функции (рис. 7.23).
Рис. 7 .23. Определение начальных условий
Окно содержит несколько полей, которые необходимо заполнить. В поле
Time указываем диапазон (список) значений по времени 0:0.01:1, для ко-
торых вычисляется решение. В поле u(t0) указываем значение 1, что озна-
чает равенство единице искомой функции во всех точках геометрической
области в начальный момент времени. Значения в полях Relative tolerance
и Absolute tolerance для относительной и абсолютной ошибок соответ-
ственно можно оставить без изменений (по умолчанию это 0.01 и 0.001).
Перед тем, как приступить к поиску решения, можно (и нужно) опреде-
литься со способом представления результата. Мы хотим создать цветовую
анимацию. В этом случае геометрическая область закрашивается цветом
в зависимости от температуры. Другими словами, поле температур отобра-
Глава 7. Уравнения математической физики
297
жается в виде цветовой гаммы. Поскольку температура меняется со време-
нем, меняется и раскраска образца. Чтобы задать параметры анимации, вы-
бираем команду Plot ► Parameters (рис. 7.24).
Рис. 7 .24. Определение графических параметров для отображения результата
Откроется диалоговое окно Plot Selection, представленное на рис. 7.25.
Рис. 7 .25. Переход в режим определения параметров анимации
В этом окне устанавливаем флажок опции
Animation для создания в результате поиска ре-
шения анимации и щелкаем кнопку Options,
чтобы задать параметры анимации. После этого
в окне Animation Options в поле Animation rate
указываем количество кадров, отображаемых в
секунду, а в поле Number of repeats указываем
количество повторов анимационного цикла. Вы-
полненные настройки показаны на рис. 7.26.
Наконец, все настройки выполнены, и можно
приступить к поиску решения.
Рис. 7.26. Окно для настрой-
ки параметров анимации
Самоучитель Matlab
298
На заметку
Строго говоря, надо было бы выполнить еще триангуляцию – покрыть геометри-
ческую область такой специфической сеткой с треугольными ячейками розного
размера. Узлы этой сетки используются в качестве реперных точек при числовом
решении задачи. Чем мельче сетка, тем точнее вычисления. Правда, на мелкой
сетке вычисления проводятся дольше. Если триангуляцию не выполнить вручную
(используются команды меню Mesh и кнопка с изображением разграфленного
треугольника), то триангуляция будет выполнена автоматически. Правда сет-
ка будет достаточно крупной. Но мы здесь за качеством не гонимся, нам важен
принцип. Поэтому процесс явного выполнения триангуляции проигнорируем.
Для решения задачи выбираем команду Solve ► Solve PDE (рис. 7.27).
Рис. 7.27. Запуск утилиты решения задачи
Рис. 7 .28. Один из начальных кадров, полученных при решении задачи
Глава 7. Уравнения математической физики
299
В результате создаются кадры анимации, и затем анимация отображается
в графическом окне. На рис. 7.28 показан один из начальных кадров анима-
ции, когда распределение температуры в образце близко к начальному.
С течением времени картина меняется. Один из последних кадров пред-
ставлен на рис. 7.29.
Рис. 7 .29. Один из последних кадров, полученных при решении задачи
Хотя в черно-белом цвете эффект не так очевиден, как в цвете, разницу уви-
деть все же можно.
На заметку
В рассмотренном примере мы использовали абсолютно банальные граничные
и начальное условия – это были константы. В общем случае в начальный момент
времени распределение функции неоднородно. Другими словами, начальное
распределение искомой функции зависит от координат. Это же замечание отно-
сится к граничным условиям. При работе со средой PDETool это немаловажное
обстоятельство можно учесть. При вводе граничных и начальных условий в соот-
ветствующих полях указываются выражения, определяющие пространственное
распределение того или иного параметра. При этом по умолчанию в качестве
пространственных координат используются переменные x и y. Подразумевает-
ся, что переменные x и y являются массивами с координатами точек. Поэтому
все формулы должны вводиться так, чтобы соответствующие операции могли
выполняться с массивами.
Самоучитель Matlab
300
Обработка аналитических результатов
Ватсон, я просто скрыл от Вас логическую
цепь рассуждений и предложил Вам только
выводы. От этого Вы мне не верите.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Кровавая надпись"
Выше мы кратко познакомились со средой PDETool, которая позво-
ляет решать уравнения в частных производных в числовом виде. Ча-
сто это единственно возможный подход. Но "часто" еще не означа-
ет "всегда".
Здесь проиллюстрируем полезность приложения Matlab
даже в том случае, когда известно точное аналитическое решение. Для
иллюстрации рассмотрим задачу о колебаниях прямоугольной мем-
браны с закрепленными краями. Задача формулируется так: необхо-
димо решить уравнение
22
2
2
22
2
(, ,)
(,,) (, ,)
Uxyt
Uxyt
Uxyt
a
tx
y
⎛⎞
∂∂
∂
⎟
⎜
⎟
=+
⎜
⎟
⎜
⎟
⎜
∂∂
∂
⎝⎠
с
граничными
условиями
1
(0,,)(
,,) 0
UxytUxLyt
==
==
и
2
(,0
,)
(,,)0
UxytUxyLt
==
==
,
а
также
начальными
усло-
виями
()()
()()
01
12
2
(,, 0)
1
1
Uxyt
UxL
xL yL
yL
==
−
−
и
(,, 0)
0
Uxyt
t
∂=
=
∂
(пространственные переменные
1
0xL
≤≤и
2
0yL
≤≤ ). Здесь функция (, ,)
Uxyt имеет смысл отклонения мембраны
от положения равновесия в соответствующей точке для данного момента
времени. Именно эту функцию нам нужно найти.
Перед решением обезразмериваем задачу. Вводим новые пространствен-
ные координаты
1
xL
ξ=
и
2
yL
η=
, время
1
atL
τ=
и функцию
0
(,,) (, ,)
uU
x
y
t
U
ξητ =
.
Тогда задача будет сформулирована следующим
образом. Решаем уравнение
222
2
222
(,,) (, ,)
(,,)
uuu
k
ξητ
ξητ
ξητ
τξη
∂∂∂
=+
∂∂∂
(параметр
12
kLL
=
). Граничные условия остаются нулевыми
((0
,
,
)(1
,
,
)0
uu
ξη
τξη
τ
==
==
и
(,0
,)
(,1
,)0
uu
ξητ
ξητ
== ==
),
а начальные условия имеют вид (, , 0) (1 )(1 )
u ξητ
ξξηη
==−
−
и
(,, 0)
0
u ξητ
τ
∂=
=
∂
.
Эта задача имеет аналитическое решение, которое может быть представле-
но в виде бесконечного ряда
()
22
2
63
3
00
c
o
s(
21
)(
21
)s
i
n
(
(
21
))
s
i
n
(
(
21
))
64
(,,)
(2 1)(2 1)
mn
mn
kmn
u
mn
πτ
πξ
πη
ξητ
π
∞∞
==
+++
+
+
=
++
∑∑
.
Глава 7. Уравнения математической физики
301
На заметку
Получить аналитическое решение можно методом разделения переменных. Суть
этого метода состоит в следующем. Ищем частное решение исходного уравне-
ния, удовлетворяющее граничным условиям, в виде произведения трех функций,
каждая из которых зависит от одной переменной: (, , ) () () ( )
uX
Y
T
ξητ
ξητ
=
.
Тогда уравнение может быть записано, после несложных преобразований,
в виде
2
() ()
()
() ()
()
TXY
k
TXY
τξη
τξη
′′
′′
′′
=+
.
Учитывая, что все три функции зави-
сят от разных независимых переменных, а также принимая во внимание гра-
ничные условия
(0) (1) 0
XX
==
и
(0) (1) 0
YY
==
, несложно пока-
зать, что должны выполняться соотношения
2
()
()
X
m
X
ξ
ξ
′′
=−
,
2
()
()
Y
n
Y
η
η
′′
=−
и
22
2
() ()
()
T
mn
k
T
τ
τ
′′
=−
+
, где через m и n обозначены произвольные нату-
ральные числа. Мы получили три дифференциальных уравнения. В этих уравне-
ниях важно то, что это обыкновенные дифференциальные уравнения. Их можно
решить (найти общее решение). Каждая из функций ищется с точностью до об-
щего несущественного множителя. Принимая этот множитель равным единице,
получаем () sin( )
Xm
ξπ
ξ
=
и()sin()
Yn
ηπ
η
=
. Что касается функции ()
Tτ,
то здесь также нужно учесть нулевое начальное значение для производной по
времени. В этом случае можно показать, что
()
22
2
() cos
Tm
n
k
τπ
τ
=+
.
Таким образом, общее решение может быть записано в виде линейной комби-
нации функций вида
()
()
22
2
cos
sin
sin( )
mn
kmn
πτ
πξ
πη
+
. Искомым ре-
шением задачи является функция
()
()
22
2
11
(,,)
cos
sin
sin( )
mn
mn
uA
m
n
k
m
n
ξητ
πτ
πξ
πη
∞∞
==
=+
∑∑
,
где ко-
эффициенты nm
A определяются через функцию начального распределения
(,)(1)(1)
fξηξξηη
=−
−
соотношением вида
()()
11
63
3
00
16(1(1))(1(1))
4(
,
)
s
i
ns
i
n
mn
mn
Ad
fmn
d
mn
ξξ
ηπ
ξπ
ηη
π
−−
−−
==
∫∫
.
Следовательно, коэффициенты nm
A отличны от нуля только для нечетных ин-
дексов. Сделав формальную замену
21
mm
→+
и
21
nn
→+
, вычисляем
выражение
633
64
1
(2 1)(2 1)
mn
π
++
для отличных от нуля коэффициентов. Не-
посредственно отсюда получаем конечное выражение для аналитического ре-
шения задачи.
Самоучитель Matlab
302
Аналитическое решение используем при составлении программного кода
в Matlab. Рассмотрим программный код, представленный ниже, в котором
определяется функция – решение задачи:
function res = u(x,y,t,k)
s=0;
Nmax=100;
for m=0:Nmax
for n=0:Nmax
M=2*m+1;
N=2*n+1;
A=1/M^3/N^3;
s=s+A*cos(pi*t*sqrt(M^2+N^2*k^2)).*sin(pi*M*x).*sin(pi*N*y);
end
end
res=64*s/pi^6;
end
У функции u(), описанной в этом коде, четыре аргумента – кроме двух
пространственных переменных (x и y) и времени t, четвертым аргументом
указан геометрический фактор k (введенная выше переменная
12
kLL
=
).
Все вычисления выполняются в соответствии с приведенными выше фор-
мулами. Остановиться можно, пожалуй, лишь на локальных переменных,
которые вводятся для упрощения вычислений. Это переменные N и M, а так-
же переменная A. Еще раз подчеркнем, что переменные эти введены исклю-
чительно ради удобства. Окно редактора m-файлов с кодом функции пред-
ставлено на рис. 7.30.
Рис. 7.30. Код функции – решения уравнения в частных производных
Глава 7. Уравнения математической физики
303
Созданную таким образом функцию можно использовать в вычислениях.
Например, можно отобразить на графике начальный профиль мембраны.
Для этого используем следующие команды:
>> x=0:0.01:1;
>> y=0:0.01:1;
>> [X,Y]=meshgrid(x,y);
>> Z=u(X,Y,0,1);
>> surf(X,Y,Z)
В результате создается поверхность, дающая представление о профиле мем-
браны в начальный момент времени (рис. 7.31).
Рис. 7.31. Начальный профиль мембраны
Но чтобы представить, что же происходит с течением времени, лучше соз-
дать анимацию. В этом случае полезным будет следующий программный
код:
% Количество кадров (+1):
N=100;
% Продолжительность по времени:
T=2;
% Пространственные координаты:
x=0:0.01:1;
Самоучитель Matlab
304
y=0:0.01:1;
% Геометрический фактор:
k=1;
% Матрицы для графических утилит:
[X,Y]=meshgrid(x,y);
for i=0:N
% Момент времени:
t=i*T/N;
% Расчет профиля мембраны:
Z=u(X,Y,t,k);
% Поверхность:
surf(X,Y,Z);
% Диапазон значений по осям:
axis([0 1,0 1,-1/16 1/16]);
% Координатная сетка:
grid on;
% Кадр анимации:
F(i+1)=getframe;
end
% Отображение анимации:
movie(F,1);
На заметку
Вместо команды movie(F,1) можно воспользоваться инструкцией
movie(F).
Сохраняем этот программный код в файле с именем Membrane.m и выпол-
няем с помощью одноименной команды Membrane в командном окне. В ре-
зультате получаем анимационную картинку, некоторые кадры из которой
представлены в табл. 7.1.
На заметку
Для ускорения вычислений можно уменьшить в программном коде для функции-
решения дифференциального уравнения количество слагаемых в ряде.
Предложенный выше код (имеется в виду код для функции-решения u())
предназначен для решения конкретной задачи. Его можно сделать более
универсальным. В частности, создадим функцию, которая позволит вы-
числять колебания прямоугольной мембраны с закрепленными краями
для произвольного начального профиля мембраны (но при условии, что
начальные скорости точек мембраны равны нулю). Другими словами,
модифицируем программный код так, чтобы можно было вычислять про-
филь мембраны в произвольный момент времени, если начальный про-
филь мембраны задается некоторой функцией (, )
f ξη . Рассмотрим при-
веденный ниже код:
Глава 7. Уравнения математической физики
305
Табл. 7.1. Колебания прямоугольной мембраны
Номер
кадра
Кадр
Номер
кадра
Кадр
1
25
5
30
10
35
15
40
Самоучитель Matlab
306
function s = u2(A,x,y,t,k)
s=0;
Nmax=length(A);
for m=1:Nmax
for n=1:Nmax
s=s+A(m,n)*cos(pi*t*sqrt(m^2+n^2*k^2)).*sin(pi*m*x).*sin(pi*n*y);
end
end
end
Функцией u2() вычисляется ряд для решения дифференциального урав-
нения. Особенность функции, по сравнению с предыдущим случаем, со-
стоит в том, что, помимо пространственных переменных x и y, времени
t и параметра k, первым аргументом функции передается список A коэф-
фициентов разложения функции начального профиля по базисным функ-
циям. Количество слагаемых в ряде определяется количеством элементов
(коэффициентов) в списке A. Коэффициенты этого списка вычисляются
с помощью другой функции, которая называется Coefs(). Ее код при-
веден ниже:
function A=Coefs(f)
Nmax=30;
A=zeros(Nmax,Nmax);
for m=1:Nmax
for n=1:Nmax
F=@(x,y)(f(x,y).*sin(pi*m*x).*sin(pi*n*y));
A(m,n)=4*quad2d(F,0,1,0,1);
end
end
end
Аргумент у функции один – указатель f на функцию, определяющую
профиль начального распределения мембраны. Предполагается, что
это функция двух переменных. В теле функции Coefs() определя-
ется переменная Nmax. Ее значение в данном случае равно 100, и это
количество слагаемых ряда (по каждой из индексных переменных).
Командой A=zeros(Nmax,Nmax) определяется нулевая квадратная
матрица, в которую будут заноситься вычисленные коэффициенты
разложения. В теле вложенных операторов цикла на основе указате-
ля f командой F=@(x,y)(f(x,y).*sin(pi*m*x).*sin(pi*n*y))
определяется подынтегральная функция, на основе которой вычис-
ляются коэффициенты ряда. Коэффициенты вычисляются командой
A(m,n)=4*quad2d(F,0,1,0,1). В этой команде использована функ-
ция quad2d(), предназначенная для вычисления интегралов по плоской
области. Первым аргументом функции передается указатель на подын-
Глава 7. Уравнения математической физики
307
тегральную функцию. Другие аргументы – пределы интегрирования по
каждой из переменных интегрирования.
Для решения задачи создаем файл Membrane2.m со следующим кодом:
% Функция начального профиля:
f=@(x,y)exp(-200*((x-0.5).^2+(y-0.5).^2));
% Вычисление коэффициентов:
A=Coefs(f);
% Количество кадров (+1):
N=300;
% Продолжительность по времени:
T=3;
% Пространственные координаты:
x=0:0.02:1;
y=0:0.02:1;
% Геометрический фактор:
k=1;
% Матрицы для графических утилит:
[X,Y]=meshgrid(x,y);
for i=0:N
% Момент времени:
t=i*T/N;
% Расчет профиля мембраны:
Z=u2(A,X,Y,t,k);
% Поверхность:
surf(X,Y,Z);
% Диапазон значений по осям:
axis([0 1,0 1,-0.4 0.4]);
% Координатная сетка:
grid on;
% Кадр анимации:
F(i+1)=getframe;
end
% Отображение анимации:
movie(F);
Функцию начального профиля создаем командой f=@(x,y)exp(-200*
((x-0.5).^2+(y-0.5).^2)). Здесь речь идет о функциональной зави-
симости
22
(,) exp( 200(
))
fxy
xy
=−
+. Это локализованный в центре ква-
дратной мембраны пик Гауссового типа. В начальный момент мембрана (ее
профиль) имеет вид, как на рис. 7.32.
На заметку
Желающие могут подумать, как с минимальными затратами времени и ресур-
сов построить такой график.
Самоучитель Matlab
308
Рис. 7.32. Начальный профиль мембраны с пиком в центре
Некоторые кадры анимации, созданной в результате выполнения приведен-
ного выше кода, показаны в табл. 7.2.
Табл. 7.2. Колебания мембраны в случае начального профиля в виде пика
Номер
кадра
Кадр
Номер
кадра
Кадр
5
75
Глава 7. Уравнения математической физики
309
Номер
кадра
Кадр
Номер
кадра
Кадр
10
100
25
150
40
200
50
250
Самоучитель Matlab
310
Номер
кадра
Кадр
Номер
кадра
Кадр
60
275
Вообще, картинки получаются достаточно эффектные. К сожалению, не
всегда можно с уверенностью сказать, соответствуют ли полученные про-
фили реальному физическому процессу, или это последствие того, что при
вычислении ряда было оставлено слишком мало слагаемых. Что подела-
ешь – ряды по тригонометрическим функциям довольно часто имеют сла-
бую сходимость.
На заметку
Выше был использован подход, при котором коэффициенты разложения ряда
вычислялись вне тела функции-решения уравнения. Это было сделано не слу-
чайно. Дело в том, что если ряд вычисляется по большому количеству слагае-
мых, значительное время уходит на расчет этих слагаемых. Если коэффициенты
вычислять в теле функции, то такие расчеты будут выполняться каждый раз, ког-
да вызывается функция решения. В использованном выше подходе коэффици-
енты были вычислены единожды и записаны в матрицу. А при вызове функции
решения коэффициенты считываются из этой матрицы. С другой стороны, если
матрица очень большая, могут возникнуть проблемы с системными ресурсами,
в то время как расчет коэффициентов непосредственно при вызове функции ре-
шения можно реализовать так, что использование системных ресурсов сведе-
но к минимуму (зато это будет долго по времени). Тот или иной подход обычно
выбирают, исходя из конкретики решаемой задачи и наличия ресурсов для ее
решения. В любом случае хорошо, что есть из чего выбирать.
311
Глава 8
Обработка данных
-
На этом и построен мой метод дедукции.
-
А как это выглядит на практике?
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Знакомство"
В этой главе обсуждается несколько вопросов, связанных с обработкой дан-
ных. Разумеется, что эта тема многогранна и практически неисчерпаема.
Здесь мы остановимся только на наиболее интересных и, вместе с тем, не
очень сложных задачах, при решении которых целесообразно использовать
приложение Matlab.
Одной из наиболее часто встречающихся является задача интерполирова-
ния. Идеологически близка к ней задача аппроксимации. Именно их и рас-
смотрим в начале этой главы.
Интерполяционные полиномы
-
Нашел!
-
Что именно?
-
Формулу!
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Знакомство"
Обычно о задаче интерполирования говорят в том случае, если имеется не-
который набор табличных значений функции, и по этим табличным значе-
ниям необходимо восстановить или просто построить некоторую аналити-
ческую зависимость. Задача важна во многих отношениях и может иметь
разную исходную постановку. Начнем с наиболее простых случаев.
Предположим, что имеется набор узловых точек 1
x,2
x,...,
n
x и значения 1
y,
2
y,...,
n
y некоторой функции в этих узловых точках. Если речь идет о зада-
че интерполирования, то она может быть сформулирована так: необходимо
построить (в соответствии с определенными критериями) некоторую функ-
цию ()
fx , такую, что эта функция в узловых точках 1
x,2
x,...,
n
x принимает
значения 1
y,2
y,...,
n
y,тоесть ()
kk
fxy
=
длявсехиндексовk от1доn.
Этого критерия совершенно недостаточно, чтобы однозначно определить
интерполяционную функцию ()
fx. Необходимо уточнить ее вид. Очень
часто функцию ()
fx ищут в виде полинома. Степень полинома выбирает-
ся в соответствии с количеством узловых точек. Если узловых точек n , то
степень интерполяционного полинома равняется
1
n−
. Такой полином име-
Самоучитель Matlab
312
ет вид
123
123
1
()
.
.
.
nnn
nn
fxaxaxax
axa
−−−
−
=++ +
++
и содержит n
параметров 1
a,2
a,...,
n
a , благодаря которым удается добиться того, чтобы
интерполяционный полином проходил через базовые точки (, )
kk
xy (индекс
1, 2, ...,
kn
=
). Фактически задача сводится к определению коэффициентов
интерполяционного полинома на основании значений базовых точек. Суще-
ствуют различные алгоритмы решения такой задачи, но в нашем случае все
существенно упрощается, поскольку в Matlab есть специальные функции для
построения интерполяционного полинома и выполнения сопутствующих вы-
числений. Тем не менее, кратко рассмотрим математическую суть проблемы.
Из условий ()
kk
fxy
=
(индекс
1, 2, ...,
kn
=
) получаем систему алгебраи-
ческих уравнений
123
123
1
...
nnn
kkk n
k
n
k
ax
ax
ax
ax
a
y
−−−
−
+++
++
=
, ко-
торую следует решать относительно коэффициентов 1
a,2
a,...,
n
a . Система
линейная, поэтому решить ее особого труда не составляет. Формально, если
ввести в рассмотрение векторы
12
(,,
.
.
.
,)
n
aa
aa
=
и
12
( , ,...,
)n
yy
yy
=
, то сис-
тему можно записать в виде
ˆ
T
aW
y
=
, где символ T означает транспони-
рование, а через ˆ
W обозначена матрица Вандермонда. Она имеет такой вид:
12
11
1
12
22
2
12
11
1
11
...
1
...
1
ˆ
...
...
...
...
...
...
1
...
1
nn
nn
nn
nn
n
nn
nn
n
xx
x
xx
x
W
xx
x
xx
x
−−
−−
−−
−−
−
−−
⎛⎞
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎟
=⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟
⎜
⎟⎟
⎜⎝⎠
то есть для элементов ij
W (индексы ,1
,
2
,
.
.
.
,
ij
n
=
) этой матрицы имеет
место соотношение
nj
ij
i
Wx
−
=
.
Для вычисления матрицы Вандермонда
в Matlab предназначена функция vander(). Аргументом функции указыва-
ется список узловых точек 1
x,2
x,...,
n
x (список-строка или список-столбец).
Если матрица ˆ
W и вектор значений функции в узловых точках y извест-
ны, то коэффициенты интерполяционного полинома a вычисляются как
()1
ˆT
ay
W
−
=
. Ну, а если известны коэффициенты полинома, то значение
полинома можно вычислить в любой точке – для этого в Matlab тоже есть
специальные функции. Рассмотрим документ, представленный в документе
на рис. 8.1.
Командами x=[0,0.2,0.4,0.7,0.9,1.2,1.5] и y=cos(2*pi*x)./
(1+x) задаются узловые точки и значения функции в узловых точках соот-
ветственно. В данном случае табулируется функция
cos(2 )
()1
x
yx
x
π
=
+
. Ма-
трицу Вандермонда вычисляем командой W=vander(x). Коэффициенты
Глава 8. Обработка данных
313
интерполяционного полинома вычисляются командой a=y*inv(W.'). На
этом процесс вычисления интерполяционного полинома собственно и за-
канчивается. Дальнейший код предназначен для иллюстрации полученно-
го результата. В частности, командами z=0:0.01:1.5 и f=polyval(a,z)
создаем набор точек, по которым будем строить полиномиальную кри-
вую. Командой plot(x,y,'ro') на графике отображаем базовые точки,
затем с помощью инструкции hold on переходим в режим удержания
графики и отображаем интерполяционную кривую с помощью команды
plot(z,f,'k-'). Инструкция grid on нужна для отображения коорди-
натной сетки. На рис. 8.2 представлен график с базовыми точками и кривая,
построенная на основе интерполяционного полинома.
Кривая достаточно плавная и проходит через все базовые точки, как и сле-
довало ожидать для интерполяционной кривой. Тем не менее, ситуация да-
леко не всегда такая идиллическая. Об этом речь еще будет идти.
Для выполнения полиномиальной интерполяции в Matlab может использо-
ваться функция polyfit().
Рис. 8.1 . Вычисление интерполяционного полинома
Самоучитель Matlab
314
На заметку
Строго говоря, функция polyfit() предназначена для выполнения аппрокси-
мации. Частным случаем задачи аппроксимации является задача интерполяции.
Аргументами функции polyfit() передаются список узловых точек и спи-
сок значений интерполируемой функции в этих точках. Также указывается
степень интерполяционного полинома. В качестве результата возвращается
список с коэффициентами полинома. Чтобы это был именно интерполяци-
онный полином, необходимо, чтобы степень этого полинома была на еди-
ницу меньше количества узловых точек. В противном случае полученный
полином будет аппроксимировать табличные данные.
На заметку
При вычислении полинома функцией polyfit() используется метод наимень-
ших квадратов. Вычисляется полином заданной степени, который наилучшим
образом аппроксимирует табличные данные. При этом в общем случае полино-
миальная кривая не обязательно проходит через базовые точки. Если степень
полинома на единицу меньше количества базовых точек, то при аппроксимации
метод наименьших квадратов позволяет построить полином, кривая которого
проходит через все базовые точки. То есть фактически такой полином является
интерполяционным.
Рис. 8.2 . Базовые точки и интерполяционная кривая
Глава 8. Обработка данных
315
Пример использования функции polyfit() для создания интерполяцион-
ного полинома приведен в документе на рис. 8.3.
Рис. 8 .3. Создание интерполяционного полинома с помощью функции polyfit()
Здесь мы использовали такую последовательность команд:
>> x=-5:1:5;
>> y=sin(pi*x./2)./(1+x.^2);
>> P=polyfit(x,y,length(x)-1);
>> z=-5.1:0.01:5.1;
>> plot(x,y,'ks')
>> hold on
>> grid on
>> plot(z,polyval(P,z),'r-')
>> title('Интерполяционный полином')
>> P2=polyfit(x,y,5);
>> plot(z,polyval(P2,z),'k-.')
>> legend('базовые точки','интерполяция','аппроксимация')
Первые две команды (x=-5:1:5 и y=sin(pi*x./2)./(1+x.^2)) создают
наборы точек, на основе которых будет строиться интерполяционный по-
лином. Командой P=polyfit(x,y,length(x)-1) создается интерполяци-
онный полином. Собственно, под созданием полинома здесь имеется в виду
вычисление коэффициентов этого полинома. Коэффициенты записывают-
ся в переменную P. Командой z=-5.1:0.01:5.1 создаем список узловых
точек, по которым будет строиться график интерполяционного полинома.
Диапазон значений аргумента, для которого отображается график интерпо-
ляционного полинома, несколько шире диапазона, определяемого базовыми
точками. Базовые точки отображаем командой plot(x,y,'ks'), а командой
plot(z,polyval(P,z),'r-') строим график интерполяционного поли-
нома. Для сравнения, кроме интерполяционного полинома, выполняется еще
Самоучитель Matlab
316
и аппроксимация на основе полиномиального выражения. Коэффициенты
соответствующего полинома вычисляются командой P2=polyfit(x,y,5).
Аппроксимация выполняется на основе полинома пятой степени (третий ар-
гумент функции polyfit()). Кривая на основе этого полинома отображается
с помощью команды plot(z,polyval(P2,z),'k-.').
Заголовок добавляем командой title('Интерполяционный полином'),
а легенду – командой legend('базовые точки','интерполяция',
'аппроксимация'). Результат графических построений представлен на рис. 8.4.
Рис. 8.4. Базовые точки, интерполяционный и аппроксимирующий полиномы
Интерполяционная кривая сплошная, а штрихпунктирная кривая соответствует
полиномиальной аппроксимации. Что касается интерполяционного полинома,
то по определению в узловых точках он дает табличные значения (те, на основе
которых строится полином). Как отмечалось выше, в задаче аппроксимации та-
кое условие не ставится. Достаточно, чтобы кривая проходила достаточно близ-
ко к базовым точкам. Что такое "достаточно близко" – вопрос отдельный.
На заметку
Каким бы способом ни строился интерполяционный полином, он один и тот же
для фиксированного набора базовых точек. Другими словами, для данного на-
бора базовых точек интерполяционный полином один. Как бы мы ни вычисляли
этот полином, если вычисления правильные, получим один и тот же результат.
Глава 8. Обработка данных
317
При большом количестве базовых точек интерполяция полиномом может
оказаться малопродуктивной. Одна из проблем связана с существенно не-
монотонным поведением полиномов высокой степени. Чтобы решить эту
проблему, нередко используют интерполяцию сплайнами. Главная идея
метода состоит в том, что диапазон интерполирования разбивается на под-
диапазоны (например, в пределах между двумя соседними узловыми точ-
ками). В пределах каждого поддиапазона используются разные функции
одного вида (полиномы невысокой степени). Эти функции "сшиваются"
на границах поддиапазонов вместе с производными. В результате получаем
кусочно-гладкую (вместе с производными нескольких первых порядков)
интерполяционную зависимость.
Сплайн-интерполяцию в Matlab можно реализовать с помощью функции
interp1(). Обычно аргументами функции interp1() передают набор
узловых точек аргумента табулированной функции и значений функции
в этих узловых точках. Это два списка, определяющие те базовые точки,
на основе которых выполняется интерполяция. Третьим аргументом ука-
зывается список значений, для которых вычисляется значение интерпо-
ляционной зависимости. Этот аргумент может быть скаляром – тогда зна-
чение интерполяционной зависимости вычисляется в одной точке. Также
четвертым аргументом можно указать (в одинарных кавычках) ключе-
вое слово, определяющее тип базового сплайна (степень полинома). Для
определения типа базового полинома используют следующие ключевые
слова (табл. 8.1).
Табл. 8.1. Ключевые слова, определяющие тип базового полинома
Ключевое слово
Описание
nearest
Интерполяция полиномами нулевой степени – график имеет
ступенчатый вид
linear
Интерполяция полиномами первой степени (линейные функ-
ции) – базовые точки соединяются отрезками. Этот метод ис-
пользуется по умолчанию (то есть если тип базового сплайна не
указан явно)
spline
Интерполяция полиномами третьей степени
pchip
Интерполяция кубическими полиномами Эрмита. Можно вместо
ключевого слова pchip указать ключевое слово cubic
Как правило, к интерполяции на основе базовых полиномов нулевой и пер-
вой степени на практике прибегают достаточно редко, поэтому рассмотрим
методы интерполяции кубическими полиномами. Обратимся к рис. 8.5, на
котором представлен документ с соответствующим примером.
Самоучитель Matlab
318
Рис. 8.5 . Интерполяция кусочно-непрерывными функциями
Использована такая последовательность команд:
>> x=-1:0.2:1;
>> y=cos(3*pi*x);
>> z=-1:0.01:1;
>> f1=interp1(x,y,z,'spline');
>> f2=interp1(x,y,z,'pchip');
>> plot(x,y,'ks')
>> hold on
>> plot(z,f1,'r-','LineWidth',2)
>> plot(z,f2,'g--','LineWidth',2)
>> grid on
>> title('Интерполяция сплайнами')
>> legend('базовые точки','кубические сплайны','полиномы Эрмита')
В переменную x записываются узловые точки аргумента табулируемой
функции. Значения табулируемой функции в узловых точках вычисляют-
ся командой y=cos(3*pi*x). В переменную z записываются значения
аргумента, для которых необходимо вычислить интерполяционные зави-
симости. Интерполяционная зависимость на основе кубических сплайнов
строится командой f1=interp1(x,y,z,'spline'). Здесь первые два
аргумента (переменные x и y) задают базовые точки, на основе которых
строится интерполяционная зависимость. Третий аргумент (переменная
z) задает точки аргумента, для которых необходимо вычислить значения
интерполяционной зависимости. Эти значения, как результат вызова функ-
ции interp1(), записываются в переменную f1. Опционный параметр
'spline' означает, что интерполяционная зависимость строится на осно-
ве базовых полиномов третьей степени. Аналогично, интерполяционная
Глава 8. Обработка данных
319
зависимость на основе полиномов Эрмита создается с помощью команды
f2=interp1(x,y,z,'pchip').
На заметку
Полиномы Эрмита
()
n
Hx(степени n ) определяются как полиномиальные реше-
ния дифференциального уравнения
2
(1)()2()2()0
xyx xyx nyx
′′
′
−−
+=
.
Выражение для полинома Эрмита степени n может быть вычислено как
()
22
() (1)exp( ) exp( )
n
n
n
n
d
Hx
x
x
dx
=−
−
.
Таким образом,
0() 1
Hx=
,
1() 2
Hxx
=
,
2
2()42
Hxx
=−
и
3
3()812
Hxxx
=−
.
На рис. 8.6 показан результат интерполирования разными методами
(обычными сплайнами и полиномами Эрмита) одной и той же табличной
функции.
Рис. 8.6. Интерполяция кубическими сплайнами и полиномами Эрмита
Рассуждать вне контекста конкретной решаемой задачи о том, какой способ
интерполирования лучше, особого смысла нет. Отметим лишь, каждый спо-
соб по-своему хорош.
Самоучитель Matlab
320
Аппроксимация
Это простейшая цепь рассуждений.
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
Задача аппроксимации близка идеологически к задаче интерполяции, но
все же это разные задачи. Например, предположим, что имеется набор
узловых точек k
x (индекс
1, 2, ...,
kn
=
) и значения некоторой функции
k
y в этих точках. Также есть известная функция
12
(,, ,...,
)m
fxaa a , кото-
рая кроме аргумента x зависит еще и от некоторых параметров s
a (индекс
1, 2, ...,
sm
=
). Задача состоит в том, чтобы подобрать такие значения па-
раметров s
a , что функция
12
(,, ,...,
)m
fxa a a наилучшим образом описыва-
ла бы зависимость, заданную параметрами k
xиk
y (индекс
1, 2, ...,
kn
=
).
При этом количество m параметров s
a меньше (или даже намного мень-
ше) количества узловых точек n . Поэтому добиться того, чтобы функ-
ция
12
(,, ,...,
)m
fxa a a давала "точные" значения k
y в узловых точках k
x,
не удастся. Нужен критерий, который бы позволил определить, какая за-
висимость "лучше", а какая "хуже" аппроксимирует табличные значения.
Обычно в качестве такого критерия используется принцип наибольшего
правдоподобия, следствием которого является метод наименьших квадра-
тов. В соответствии с этим методом параметры s
a (индекс
1, 2, ...,
sm
=
)
выбираются так, чтобы сумма
2
12
1
( (,,,...,
))
n
kk
m
k
yf
x
a
aa
=
−
∑
принимала наи-
меньшее значение. Такая задача сводится к решению системы из m алге-
браических уравнений – в общем случае нелинейных. Система решается
относительно параметров s
a (индекс
1, 2, ...,
sm
=
). Эти уравнения име-
ют следующий вид:
12
12
1
(,,,...,
)
( (,,,...,
))
0
n
km
kk
m
k
s
fxaa a
yf
x
a
aa
a
=
∂
−=
∂
∑
(для всех индексов
1, 2, ...,
sm
=
). В случае если функция
12
(,, ,...,
)m
fxaa a
зависит от параметров s
a линейным образом, задача значительно упро-
щается и сводится к решению системы линейных уравнений. Действи-
тельно, в этом случае для функции
12
(,, ,...,
)m
fxa a a может быть использо-
вано представление
12
1122
(,, ,...,
)()
() ... ()
mm
m
fxaa a
xa
xa
xa
φφ
φ
=++
+,
где функции
()
px
φ
(индекс
1, 2, ...,
pm
=
) известные и зависят
только от аргумента x . Тогда система уравнений принимает вид
11
1
((
).
.
.
(
)
)
(
)
0
n
kk
m
k
m
s
k
k
yx
a
x
ax
φφ
φ
=
−−
−
=
∑
. В матричном виде эта систе-
ма может быть записана как ˆ
BaC
=
, где искомый вектор коэффициентов
12
( , ,...,
)m
aa
aa
=
умножается слева на матрицу ˆB , состоящую из элементов
Глава 8. Обработка данных
321
1
()()
n
ij
ikjk
k
bx
x
φφ
=
=
∑
(индексы ,1
,
2
,
.
.
.
,
ij
m
=
). Вектор C в правой части
состоит из элементов
1
()
n
ik
i
k
k
cy
x
φ
=
=
∑ . Таким образом, для поиска аппрок-
симирующей зависимости в случае линейной функции
12
(,, ,...,
)m
fxaa a
для определения оптимальных параметров 1
a,2
a,...,
m
a достаточно методов
линейной алгебры. В общем случае поиск параметров 1
a,2
a,...,
m
a аппрок-
симирующей зависимости формулируется как задача поиска абсолютного
минимума для выражения
2
12
1
( (,,,...,
))
n
kk
m
k
yf
x
a
aa
=
−
∑
.
На заметку
В линейном случае задача решается проще и быстрее. В этом отношении лучше
и приятнее иметь дело с линейной задачей. К счастью, нередко нелинейную за-
дачу можно переформулировать так, что она станет линейной. Для линейной за-
дачи на будущее договоримся называть параметр k
a ( 1,2,...,
km
=
) коэффи-
циентами аппроксимирующего выражения, а функции ()
kx
φ
( 1,2,...,
km
=
)
базисными функциями аппроксимирующего выражения.
Далее рассмотрим, как эти задачи решаются в Matlab. Один из самых про-
стых случаев – аппроксимация на основе полинома. Для решения такой за-
дачи используем встроенную функцию polyfit(). Аргументами функции
передаются массивы узловых точек и значений в этих узловых точках табу-
лируемой функции, а также степень аппроксимирующего полинома. При-
мер использования функции polyfit() приведен в документе на рис. 8.7.
На основе набора базовых точек создается два аппроксимирующих поли-
нома – четвертой и второй степени. Кривые для обоих полиномов, вместе
с исходными базовыми точками, отображаются на графике. Весь команд-
ный код такой (жирным шрифтом выделен ввод пользователя):
>> k=0:10;
>> y=cos(pi*k/5)./(1+k);
>> p=polyfit(k,y,4)
p=
0.0002
-0.0097
0.1315
- 0.6747
0.9880
>> x=0:0.01:10;
>> plot(k,y,'rs','LineWidth',2)
>> grid on
>> hold on
>> q=polyfit(k,y,2)
q=
0.0280
-0.3335
0.7936
>> plot(x,polyval(p,x),'b-','LineWidth',2)
Самоучитель Matlab
322
>> plot(x,polyval(q,x),'g--','LineWidth',2)
>> legend('базовые точки','полином 4-й степени','полином 2-й степени')
Узловые точки по аргументу создаем командой k=0:10 (целочисленные
значения от 0 до 10 включительно). Значения табулированной функции
в этих точках вычисляются командой y=cos(pi*k/5)./(1+k). Таким об-
разом, базовые точки строятся на основе зависимости
()
cos
5
1
k
k
y
k
π
=
+
для
значений индекса
0, 1, ..., 10
k=
. Аппроксимирующий полином вычисляет-
ся командой p=polyfit(k,y,4). Первым аргументом функции polyfit()
передается список k со значениями узловых точек по аргументу. Список y
содержит значения табулированной функции в узловых точках. Третий ар-
гумент функции polyfit() определяет степень аппроксимирующего поли-
нома (в данном случае создается полином четвертой степени). В результате
возвращается список коэффициентов аппроксимирующего полинома. Этот
список записывается в переменную p.
Базовые точки отображаются на графике с помощью команды
plot(k,y,'rs','LineWidth',2). Командой q=polyfit(k,y,2) созда-
ется еще один аппроксимирующий полином, но на этот раз второй степе-
ни. Затем командами plot(x,polyval(p,x),'b-','LineWidth',2)
и
plot(x,polyval(q,x),'g--','LineWidth',2) отображаются
Рис. 8.7. Использование функции polyfit() для выполнения полиномиальной
аппроксимации
Глава 8. Обработка данных
323
аппроксимирующие полиномы. При этом переменная x предварительно
определяется командой x=0:0.01:10. Для вычисления значения полино-
ма использовалась функция polyval(). Легенда добавляется командой
legend('базовые точки','полином 4-й степени','полином 2-й
степени'). Результаты аппроксимации лучше всего исследовать в графи-
ческом виде. На рис. 8.8 представлены результаты построений, выполнен-
ные при создании аппроксимирующих полиномов.
Рис. 8.8. Результат аппроксимации полиномами разной степени
Относительно "качества" аппроксимации, то совершенно очевидно, что
полином четвертой степени в этом отношении более чем хорош. Но такая
идиллия имеет место далеко не всегда. Другими словами, полином не всег-
да является приемлемым типом аппроксимирующей функции. Составим
простенький программный код, с помощью которого будем вычислять ап-
проксимирующие зависимости линейного вида для произвольных базис-
ных функций. Мы будем использовать три функции. Вот их код:
function res=LSFit(x,y,phi,m)
b=zeros(m);
c=zeros(m,1);
for i=1:m
for j=1:m
b(i,j)=sum(phi(x,i).*phi(x,j));
end
Самоучитель Matlab
324
c(i)=sum(y.*phi(x,i));
end
res=b\c;
end
Это функция для вычисления коэффициентов возле базисных функций в ап-
проксимирующем выражении. У функции LSFit() четыре аргумента. Пер-
вые два – это список узловых точек x и список y значений табулированной
функции. По этим точкам строится аппроксимирующая зависимость (точ-
нее, определяются параметры этой зависимости). Указатель phi на базис-
ные функции, через линейную комбинацию которых определяется аппрок-
симирующее выражение, является третьим аргументом функции LSFit().
Четвертый аргумент m функции LSFit() определяет количество слагаемых
в аппроксимирующем выражении. В качестве результата функция возвраща-
ет список коэффициентов, с которыми базисные функции входят в аппрок-
симирующее выражение (переменная-результат обозначена как res).
В теле функции командами b=zeros(m) и c=zeros(m,1) создается ква-
дратная матрица b размера m, заполненная нулями, а также нулевой вектор-
столбец c. Матрица и вектор заполняются в процессе выполнения вложен-
ных операторов цикла. В каждом цикле индексная переменная пробегает
значения от 1 до m. Командой b(i,j)=sum(phi(x,i).*phi(x,j)) вы-
числяются элементы матрицы b. Элементы вектора c вычисляются коман-
дой c(i)=sum(y.*phi(x,i)).
На заметку
В переменную b записывается матрица с элементами
1
()()
n
ij
ikjk
k
bx
x
φφ
=
=
∑
,
где базисные функции
()
px
φ
( 1,2,...,
pm
=
) формируют аппроксимирую-
щее выражение
11 22
()()()...()
mm
fx
xa
xa
xa
φφ
φ
=++
+ . При фикси-
рованных индексах i и j для вычисления суммы по индексу k в команде
b(i,j)=sum(phi(x,i).*phi(x,j)) использована встроенная функ-
ция sum(). Поскольку в инструкции phi(x,i).*phi(x,j) использован
оператор .* поэлементного произведения, то результатом этой инструкции
является список, который получается поэлементным произведением списков
phi(x,i) и phi(x,j). При этом мы предполагаем, что функция, на кото-
рую указывает указатель phi, такая, что ее первым аргументом может быть
список. Как раз для вычисления суммы по всем элементам списка и применя-
лась функция sum(). Аналогичным образом вычисляется результат выражения
c(i)=sum(y.*phi(x,i)). В этом случае вычисляются элементы вектора
1
()
n
ik
i
k
k
cy
x
φ
=
=
∑.
Глава 8. Обработка данных
325
Результат (вектор-столбец коэффициентов аппроксимирующего выраже-
ния) вычисляется командой res=b\c. Окно редактора m-файлов с кодом
этой функции представлено в документе на рис. 8.9.
Рис. 8.9 . Код функции для вычисления коэффициентов аппроксимирующего выражения
Если функция LSFit() позволяет вычислить коэффициенты в аппрокси-
мирующем выражении, то функция GetFit() предназначена для вычис-
ления по этим коэффициентам значения аппроксимирующего выражения.
Она имеет следующий код:
function res = GetFit(a,x,phi)
m=length(a);
res=0;
for i=1:m
res=res+phi(x,i)*a(i);
end
end
У функции три аргумента: список коэффициентов в линейной комбина-
ции (переменная a), список со значениями аргумента, для которых вычис-
ляется значение аппроксимирующего выражения (переменная x), а также
указатель на базовую функцию (переменная phi). Функция GetFit()
возвращает результат – список значений аппроксимирующего выражения
в узловых точках, определяемых списком x (второй аргумент функции).
Переменная-результат обозначена как res. В теле функции командой
m=length(a) определяется количество элементов в списке коэффициен-
тов. Параметр m автоматически определяет количество слагаемых в линей-
ной комбинации базисных функций для аппроксимирующего выражения.
Самоучитель Matlab
326
Сначала переменной res присваивается нулевое значение, а затем в опе-
раторе цикла (в котором индексная переменная i пробегает значения от 1
до m) ее значение изменяется в команде res=res+phi(x,i)*a(i). Здесь
использован оператор матричного умножения *, но это не принципиально,
поскольку в данном случае список phi(x,i) умножается на скаляр a(i)
при фиксированном индексе i. Список phi(x,i) представляет собой на-
бор значений базисной функции с индексом i для значений аргументов из
списка x. Каждый элемент этого списка умножается на скалярное значение
a(i), и полученные на каждом итерационном шаге списки складываются
(в результате выполнения оператора цикла). Общий результат дает значе-
ние аппроксимирующего выражения для набора точек из списка x. Про-
граммный код функции GetFit() можно видеть в документе на рис. 8.10,
где представлено окно редактора m-файлов.
Рис. 8.10. Код функции для вычисления значения аппроксимирующего выражения
Наконец, следующая функция MyFit() объединяет в себе две предыдущие
функции LSFit() и GetFit(). С ее помощью вычисляются значения ап-
проксимирующего выражения и строятся соответствующие графики. Ре-
зультат функцией не возвращается. Код у функции следующий:
function MyFit(x,y,z,phi,m)
a=LSFit(x,y,phi,m);
res=GetFit(a,z,phi);
plot(x,y,'rs','LineWidth',2);
hold on;
grid on;
plot(z,res,'b-','LineWidth',2);
title('Базовые точки и аппроксимация');
legend('базовые точки','аппроксимация');
hold off;
end
Глава 8. Обработка данных
327
Этот же код в редакторе m-файлов представлен на рис. 8.11.
Рис. 8.11. Функция для выполнения линейной аппроксимации
У функции MyFit() пять аргументов. Первые два аргумента (переменные
x и y) определяют базовые точки, на основе которых строится аппрокси-
мирующее выражение. Третий аргумент (переменная z) содержит список
значений, которые служат аргументом для вычисления аппроксимирую-
щего выражения. Указатель phi является ссылкой на базисную функцию
(от двух аргументов). Последний, четвертый аргумент (переменная m),
определяет количество слагаемых в аппроксимирующем выражении. Код
у функции достаточно простой. Командой a=LSFit(x,y,phi,m) вы-
числяются коэффициенты аппроксимирующего полинома. Командой
res=GetFit(a,z,phi) вычисляется значение аппроксимирующего по-
линома в точках, которые определяются списком z. После этого получен-
ные зависимости отображаются на графике. Базовые точки отображаются
командой plot(x,y,'rs','LineWidth',2). Точки отображаются крас-
ными квадратами (толщина линий 2). Командой hold on переходим в ре-
жим удержания графики. Сетку отображаем командой grid on. После этого
командой plot(z,res,'b-','LineWidth',2) отображается аппрокси-
мирующая кривая (синий цвет, сплошная линия толщины 2). Заголовок
добавляется командой title('Базовые точки и аппроксимация').
Команда legend('базовые точки','аппроксимация') нужна для до-
бавления легенды. Наконец, для выхода из режима удержания графики ис-
пользуем команду hold off.
Теперь перейдем к проверке работоспособности созданных функций. Для это-
го обратимся к командному коду, представленному в документе на рис. 8.12.
Самоучитель Matlab
328
Рис. 8.12. Создание аппроксимирующего полинома
Рис. 8.13. Аппроксимация полиномом
Рис. 8.14 . Добавлены команды для аппроксимации косинусами
Глава 8. Обработка данных
329
Здесь мы использовали такие команды:
>> x=0:10;
>> y=cos(x)./(1+x);
>> phi=@(x,k)x.^(k-1);
>> z=0:0.01:10;
>> MyFit(x,y,z,phi,5);
Переменная x содержит значения узловых точек, а переменная y содержит
значения табулированной функции в этих точках. Переменная z содержит зна-
чения по аргументу, для которых вычисляется аппроксимирующее выражение.
Командой phi=@(x,k)x.^(k-1) задается функция двух переменных, кото-
рая соответствует базисным функциям вида
1
()k
kxx
φ
−
=
, то есть функциям
1,x,
2
x и так далее. Другими словами, речь идет об аппроксимации выраже-
нием полиномиального вида. Результат получаем после выполнения команды
MyFit(x,y,z,phi,5). Здесь речь идет об аппроксимирующем полиноме 4-й
степени (пять слагаемых в полиноме). Результат представлен на рис. 8.13.
Достаточно просто выполняется аппроксимация на основе другой функ-
ции. Например, добавим в командное окно еще две команды (рис. 8.14).
Командой f=@(x,k)cos((k-1)*x) создается указатель f на новую базис-
ную функцию вида () cos(( 1))
kxk
x
φ=−
,тоесть1,cos()
x ,cos(2)x итак
далее. Аппроксимация (включая создание графиков) выполняется коман-
дой MyFit(x,y,z,f,5). Результат (график) показан на рис. 8.15.
Рис. 8.15. Аппроксимация косинусами
Самоучитель Matlab
330
Очевидно, что каждая аппроксимация (аппроксимация на основе разных
базисных функций) имеет свои особенности. Кроме того, нередко основ-
ной интерес представляет не графическая кривая, а непосредственно ко-
эффициенты линейной комбинации для аппроксимирующего выражения.
Например, чтобы узнать коэффициенты разложения по степенным функ-
циям, используем команду LSFit(x,y,phi,5). Коэффициенты для ап-
проксимации по косинусам узнаем с помощью команды LSFit(x,y,f,5)
(рис. 8.16).
Рис. 8.16. Вычисление коэффициентов для аппроксимации
по степенным функциям и косинусам
Как отмечалось выше, аппроксимация выражением линейного вида далеко
не всегда позволяет получить приемлемый результат. Есть две ситуации:
нелинейную зависимость удается свести к линейной, и нелинейную зави-
симость не удается свести к линейной. Начнем с первого случая. Поскольку
он предполагает наличие конкретной функциональной зависимости, рас-
смотрим следующую задачу. Пускай по неотрицательным значениям табу-
лированной функции k
y в узловых точках k
x (индекс
1, 2, ...,
kn
=
) необ-
ходимо для аппроксимации построить зависимость вида ()
exp( )
fxabx
=
.
Глава 8. Обработка данных
331
Другими словами, по набору значений k
xиk
y (индекс
1, 2, ...,
kn
=
) нуж-
но вычислить параметры a и b такие, чтобы зависимость ()
exp( )
fxabx
=
наилучшим образом описывала эту зависимость. Пикантность ситуации
в том, что функция ()
exp( )
fxabx
=
нелинейным образом зависит от па-
раметров a и b . Поэтому применяем военную хитрость и рассматриваем
табулированную функцию со значениями
ln( )
kk
zy
=
в узловых точках k
x
(индекс
1, 2, ...,
kn
=
). Если исходная табулированная функция аппрокси-
мируется зависимостью ()
exp( )
fxabx
=
, то новая функция записывается
зависимостью ( ) ln( ( )) ln( )
Fx
fx
abx
==
+
, то есть зависимость линейная.
Поэтому схема вычислений в данном случае такая:
• На основе табулированных значений k
xиk
y (индекс
1, 2, ...,
kn
=
)
создаем новую табличную зависимость k
xи
ln( )
kk
zy
=
(индекс
1, 2, ...,
kn
=
).
• Для табличной зависимости k
xиk
z (индекс
1, 2, ...,
kn
=
) строим ап-
проксимирующую зависимость вида ()
Fxcbx
=+ . Находим коэффи-
циентыbиc.
• Параметр a исходной модели связан с рассчитанным параметром c со-
отношением
exp( )
ac
=
.
Пример вычислений, выполненных в соответствии с описанной схемой,
приведен ниже (рис. 8.17).
Рис. 8 .17 . Нелинейная аппроксимация: простой случай
Командой x=0:10 создается набор узловых точек. Значения та-
булированной функции в узловых точках определяем командой
Самоучитель Matlab
332
y=3*exp(-0.2*x)+0.4*sin(pi*x/5). В данном случае использована
функциональная зависимость ( ) 3 exp( 0.2 ) 0.4 sin( 5)
yx
x
x
π
=−
+
.
Эта
зависимость близка к экспоненциальной, но с некоторой поправкой (до-
бавлен синус). Затем командой z=log(y) определяется новый набор то-
чек. На основе этого набора командой p=polyfit(x,z,1) вычисляются
коэффициенты аппроксимирующего полинома первой степени (линейная
функция). Вычисленные коэффициенты записываются в список p. Элемен-
ты этого списка в команде a=[exp(p(2)) p(1)] используются для опре-
деления нового списка. В результате выполнения этой команды получаем
следующий результат (ввод пользователя выделен жирным шрифтом):
>> a=[exp(p(2)) p(1)]
a=
3.7148 -0.2795
Командой f=@(x)(a(1)*exp(a(2)*x)) определяем функциональную
зависимость, на основе которой строится аппроксимирующее выражение.
В этой зависимости использованы вычисленные на предыдущем шаге ко-
эффициенты (список a). Прочий код предназначен для отображения базо-
вых точек и аппроксимирующей кривой:
>> t=0:0.01:10;
>> plot(x,y,'rs','LineWidth',2)
>> hold on
>> grid on
>> plot(t,f(t),'b--','LineWidth',2)
Такого типа код использовался достаточно часто и особых комментариев,
думается, не требует. Результат показан на рис. 8.18.
Можно полагать, что результат достаточно приемлемый. И получен он мини-
мальными усилиями. Тем не менее, такой простой путь не всегда возможен.
В случае, если задачу к линейной свести не удастся, можно воспользовать-
ся, например, встроенной функцией fminsearch(), предназначенной для
поиска минимума функции нескольких переменных. Первым аргументом
функции fminsearch() передается указатель на минимизируемую функ-
цию, а также список начальных приближений для параметров этой функ-
ции. Поэтому общий подход может быть таким: если необходимо вычис-
лить параметры p
a (индекс
1, 2, ...,
pm
=
) функции
12
(, , ,...,
)m
fxaa a на
основе табличных значений (, )
kk
xy (индекс
1, 2, ...,
kn
=
), то минимизиро-
вать будем функцию
()
2
12
12
1
( , ,...,
)
(,,,...,
)
n
mk
km
k
aaa
yfxaaa
=
Φ=
−
∑
по па-
раметрам 12
,
, ...,
m
aa a . Реализация этого подхода проиллюстрирована в сле-
дующем примере. Обратимся к документу, представленному на рис. 8.19.
Глава 8. Обработка данных
333
Рис. 8.18. Результат аппроксимирования исходной зависимости
Рис. 8.19. Аппроксимация на основе нелинейной функции
Самоучитель Matlab
334
Весь командный код приведен ниже (жирным шрифтом выделен ввод поль-
зователя):
>> x=0:10;
>> y=5*exp(-0.1*x).*sin(0.3*x)+0.3*cos(pi*x/2);
>> f=@(x,a)(a(1)*exp(a(2)*x)).*sin(a(3)*x);
>> F=@(a)sum((y-f(x,a)).^2);
>> a0=[1 -1 1];
>> a=fminsearch(F,a0)
a=
4.4322
- 0.0735
0.3094
>> t=0:0.01:10;
>> plot(x,y,'rs','LineWidth',2)
>> hold on
>> grid on
>> plot(t,f(t,a),'b-','LineWidth',2)
На рис. 8.20 показан график с базовыми точками и аппроксимирующей
кривой, построенной на их основе.
Рис. 8.20. Результат нелинейной аппроксимации
Теперь проанализируем командный код и полученный результат. Коман-
дами x=0:10 и y=5*exp(-0.1*x).*sin(0.3*x)+0.3*cos(pi*x/2)
создаются списки из базовых точек для создания на их основе ап-
Глава 8. Обработка данных
335
проксимирующей зависимости. При этом функциональная зависи-
мость, которая использовалась для создания базовых точек, имеет вид
()
( ) 5exp( 0.1 )sin(0.3 ) 0.3 cos
2
yx
x
x
x
π
=−
+
.
Командой f=@(x,a)
(a(1)*exp(a(2)*x)).*sin(a(3)*x) создается функция, которая ис-
пользуется для создания аппроксимирующей зависимости. Мы используем
функцию
123
1
2
3
(,,,)
exp( )sin( )
fxaaa a ax ax
=
. Параметры 1
a,2
aи3
a необ-
ходимо найти. Для этого командой F=@(a)sum((y-f(x,a)).^2) создаем
функцию, которая зависит от искомых параметров и представляет собой
сумму квадратов отклонений аппроксимирующей функции от табулиро-
ванных значений в узловых точках. Эта функция должна принимать мини-
мальное значение. Именно эту функцию будем минимизировать. Предва-
рительно командой a0=[1 -1 1] создаем список начальных значений для
искомых параметров модели. После этого вычисляем вектор параметров
оптимизации командой a=fminsearch(F,a0). Прочие команды предна-
значены для отображения на графике базовых точек и аппроксимирующей
кривой.
На заметку
Следует отметить, что полученный выше результат достаточно неплох как для
нелинейной модели. Вообще же такие модели крайне сложны для анализа, по-
этому всегда следует искать возможность для того, чтобы упростить ситуацию.
Генерирование случайных чисел
Я говорю об иных случайностях. Надеюсь,
нам повезет, и мы встретим то, что един-
ственное украшает жизнь, – настоящую
неожиданность.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Достаточно важной с прикладной точки зрения является задача по гене-
рированию случайных чисел. Обычно генерировать случайные числа при-
ходится в процессе моделирования различных процессов. В любом случае,
необходимость в генерировании случайных чисел возникает намного чаще,
чем это может показаться на первый взгляд. Здесь мы рассмотрим самые
простые приемы, которые не подразумевают использования специальных
пакетов инструментов (благо, в Matlab недостатка в таких пакетах нет –
например, пакет Statistics). Мы обойдемся несколькими функциями.
В первую очередь это функция rand(), которая позволяет генерировать
(псевдо)случайные равномерно распределенные действительные числа.
У функции есть несколько вариантов вызова. Если вызвать функцию без
аргументов (инструкция rand()), в качестве результата возвращается дей-
Самоучитель Matlab
336
ствительное число в диапазоне от 0 до 1. Если в качестве аргументов функ-
ции rand() указать целые числа, то в качестве результата возвращается
массив соответствующих размеров, заполненный случайными действитель-
ными числами в диапазоне значений от 0 до 1. Например, в результате вы-
зова команды rand(5,10) будет создана матрица размерами 5 на 10 из
случайных чисел. Если указать один аргумент, например rand(5), то будет
создана квадратная матрица соответствующего размера (в данном случае 5
на 5) из случайных чисел.
На заметку
Функция rand() далеко не единственная функция Matlab для генерирования
случайных чисел. Например, функция randn() позволяет генерировать слу-
чайные числа с функцией стандартного нормального распределения, а функция
randi() позволяет генерировать равномерно распределенные целые числа.
Простой пример использования функции генерирования случайных чисел
приведен в документе на рис. 8.21.
Рис. 8.21. Вычисление площади области методом Монте-Карло
В качестве иллюстрации мы попытаемся методами Монте-Карло вычис-
лить площадь области, ограниченной кривыми 1()
yxx
=
и
2
2()
yxx
=
.
Кривые пересекаются при значениях аргумента
0
x=и
1
x=
.
Площадь
Глава 8. Обработка данных
337
может быть вычислена через двойной интеграл
2
xyx
dxdy
<<
∫∫ , повторный
интеграл
2
1
0
x
x
dx dy
∫∫ или обычный интеграл
1
2
0
()
xxd
x
−
∫
. Все три инте-
грала дают одно и то же значение 13.
На заметку
Если быть более точным, то двойной интеграл сводится к повторному, а повтор-
ный – к однократному. Тем не менее, с точки зрения идеологии метода Монте-
Карло, правильнее было бы интерпретировать наши вычисления как расчет
двойного интеграла (который равен площади соответствующе области). Что
касается непосредственно метода Монте-Карло, то в данном случае он реали-
зован по следующей схеме. В пределах единичного квадрата, внутри которого
находится область, площадь которой мы вычисляем, случайным образом выби-
раются точки. Их много. Мы подсчитываем отношение количества точек, кото-
рые попали внутрь области, к общему количеству точек. В граничном пределе
(когда количество точек неограниченно возрастает) это отношение стремится
к отношению площадей области и площади квадрата (которая равна единице).
Таким образом, чтобы вычислить площадь фигуры, нужно сгенерировать доста-
точно большое количество точек. Отношение количества точек внутри области
к общему количеству точек принимаем как оценку для площади области.
Для выполнения вычислений создаем следующий программный код:
z=0:0.01:1;
y1=sqrt(z);
y2=z.^2;
plot(z,y1,'r-','LineWidth',2);
hold on;
plot(z,y2,'r-','LineWidth',2);
grid on;
title('Вычисление интеграла методом Монте-Карло');
n=1000;
s=0;
for i=1:n
x=rand();
y=rand();
if and(y<sqrt(x),y>x^2)
s=s+1/n;
end
plot(x,y,'bo','LineWidth',1,'MarkerSize',2,'MarkerFaceColor','b');
end
hold off;
disp(['Количество точек: ',num2str(n)]);
disp(['Результат вычислений: ',num2str(s)]);
Самоучитель Matlab
338
Вместе с вычислением площади области мы также выполняем некоторые
графические построения. Вначале создается график с кривыми для зави-
симостей, которые ограничивают область. После этого командой n=1000
задаем количество точек, которые будут сгенерированы. В переменную s,
которая инициализируется с начальным нулевым значением, будем записы-
вать результаты вычислений площади. Вычисления выполняются в опера-
торе цикла. Индексная переменная пробегает значения от 1 до n. Команда-
ми x=rand() и y=rand() генерируются случайные числа, которые служат
координатами случайной точки. Затем в условном операторе проверяется
условие and(y<sqrt(x),y>x^2), которое означает, что точка попадает
внутрь области. Если это так, командой s=s+1/n увеличиваем значение
переменной s. Но это еще не все. Сгенерированную точку мы отобража-
ем на графике с помощью команды plot(x,y,'bo','LineWidth',1,
'MarkerSize',2,'MarkerFaceColor','b'). Точки отображаются си-
ними кружками с синей заливкой маркера (опция MarkerFaceColor).
В завершение кода выводится информация о количестве сгенерирован-
ных точек и оценке для площади области. В этом случае мы использовали
команду disp(). Аргументом передается текстовая строка. Строка полу-
чается созданием массива с текстовыми элементами. Для перевода числа
в текстовый формат использовалась функция num2str().
На заметку
Для объединения строк можно было бы использовать и функцию strcat().
Однако эта функция автоматически удаляет конечные пробелы в объединяемых
строках, что в данном случае не очень приемлемо.
Приведенный выше код сохраняем в файле MCInt.m. После этого для вы-
полнения комплекса вычислений в командном окне выполняем команду
MCInt (рис. 8.22).
Рис. 8.22 . Вычисление интеграла в командном окне
Здесь мы реализуем вычисления на основе 1000 точек. Это не очень мно-
го, поэтому результат от запуска к запуску может существенно меняться
(на уровне сотых). График с точками, который создается в результате вы-
полнения кода, представлен на рис. 8.23.
Глава 8. Обработка данных
339
Рис. 8.23. Графическое представление результата
На заметку
Даже из этого простого примера видно, что точность метода Монте-Карло
оставляет желать лучшего. Чтобы добиться приемлемого результата, необхо-
димо существенно увеличить количество тестов. А это требует значительных
затрат времени (и ресурсов). Поэтому к методам вроде Монте-Карло обычно
прибегают, когда другие методы неприменимы.
Выше мы рассматривали задачу, в которой нужно было генерировать слу-
чайные числа, равномерно распределенные в диапазоне от 0 до 1. На прак-
тике приходится иметь дело со случайными величинами, которые имеют
самые разные законы распределения. В таких случаях можно либо восполь-
зоваться встроенной функцией (если такая есть) для генерирования чисел
с нужными характеристиками, либо создать собственную. Нас интересует
последний случай. Пикантность ситуации состоит в том, что создать функ-
цию, генерирующую случайные числа с практически любой приличной (не
очень экзотической) функцией распределения, можно на основе функции,
генерирующей равномерно распределенные числа. Другими словами, на
основе функции rand() можно достаточно просто создать функцию, кото-
рая генерирует числа с заданным законом распределения.
Самоучитель Matlab
340
Полезным окажется то обстоятельство, что если случайная величина ξ
распределена на интервале [0,1] , то случайная величина
1
()
F
ηξ
−
=
имеет
функцию распределения ()
Fx . Здесь функция ()
Fx непрерывная и стро-
го возрастающая, а через
1
()
Fx
−
обозначена обратная функция к функции
()
Fx . Таким образом, если нам нужно создать функцию для генерирования
случайных чисел с функцией распределения ()
Fx , то мы должны найти
обратную функцию
1
()
Fx
−
, а затем вычислять случайные числа η в соот-
ветствии с соотношением
1
()
F
ηξ
−
=
, где случайное число ξ генерируется,
например, с помощью функции rand().
На заметку
Напомним, что по определению функцией распределения
()
Fx
ξ случайной
величины ξ называется вероятность ()
Px
ξ < того, что случайная величина
принимает значение меньшее x (параметр
x
−∞ < < +∞ ). Плотностью
распределения случайной величины называется функция
()
()
dFx
px
dx
ξ
ξ=
.
Для равномерно распределенной на интервале от 0 до 1 случайной величи-
ны функция распределения имеет вид () 0
Fx
ξ=
при
0
x<,()
Fxx
ξ=
при
01
x
≤≤и()1
Fx
ξ=
при
1
x > . Плотность распределения для этого
распределения () 1
px
ξ=при
[0,1]
x∈
и ()0
px
ξ=при
[0,1]
x∉
.
В качестве примера применения на практике описанного выше принципа
создадим функцию, которая позволит генерировать случайные числа с по-
казательным распределением.
На заметку
Случайная величина ξ распределена с показательным законом с параметром
α , если функция ее распределения равна () 1 exp( )
Fx
x
ξ
α
=−
−
при
0
x≥
и равна нулю в противном случае (то есть при
0
x<).
В данном случае функция распределения () 1 exp( )
Fx
x
α
=−
−
.
Обрат-
ная к ней функция может быть найдена в результате решения уравнения
()
xF
y
=
относительно y , то есть
1
()
yFx
−
=
. Это нам позволит найти об-
ратную функцию. Имеем
1e
x
p
()
yx
α
=−
−
. После несложных преобразо-
ваний находим
ln(1 )y
x
α
−
=−
. Таким образом,
1
ln(1 )
()
x
Fx
α
−
−
=−
. По-
этому если мы будем генерировать случайные числа ξ функцией rand(),
а затем на их основе вычислять числа
ln(1 )ξ
η
α
−
=−
, то случайные числа
η будут иметь показательное распределение с параметром α . Обратимся
к документу на рис. 8.24.
Глава 8. Обработка данных
341
Рис. 8.24. Генерирование случайных чисел с показательным распределением
Использованный в вычислениях командный код приведен ниже (для удоб-
ства восприятия код снабжен комментариями):
% Количество тестов:
n=10000;
% Параметр распределения:
alpha=3;
% Равномерно распределенные случайные числа:
xi=rand(1,n);
% Числа с показательным (экспоненциальным) распределением:
eta=-log(1-xi)/alpha;
% Наибольшее из чисел:
Xmax=max(eta);
Самоучитель Matlab
342
% Количество рангов в гистограмме:
k=100;
% Шаг дискретности:
h=Xmax/k;
% Аргумент для функции плотности распределения:
x=0:h:Xmax;
% Создание гистограммы:
hist(eta,x);
% Переход в режим удержания графики:
hold on;
% Коэффициент масштабирования для плотности распределения:
R=n*h;
% Значения масштабированной плотности распределения:
p=Xmax*n/k*alpha*exp(-alpha*x);
% График функции (масштабированная плотность распределения):
plot(x,p,'r-','LineWidth',2);
% Отображение сетки:
grid on;
% Отображение заголовка:
title('Показательное (экспоненциальное) распределение');
% Отображение легенды:
legend('статистика','теория');
% Выход из режима удержания графики:
hold off;
Переменная n определяет количество генерируемых случайных чисел.
В принципе, чем это число больше, тем статистическое распределение
ближе к теоретической кривой. Параметр распределения α записывается
в переменную alpha командой alpha=3 (то есть в нашем случае рассма-
тривается распределение с параметром
3
α = ). Командой xi=rand(1,n)
создаем список из равномерно распределенных на интервале от 0 до 1 чи-
сел. Числа с показательным (экспоненциальным) распределением создаем
с помощью команды eta=-log(1-xi)/alpha.
Собственно, на этом процесс генерирования случайных чисел с нужным
нам распределением завершен. Дальше мы пытаемся проверить, насколько
сгенерированные числа (имеются в виду числа в переменной eta – именно
эти числа мы будем использовать в дальнейшем) подчиняются экспоненци-
альному распределению. Делать это будем с помощью графиков. В частно-
сти, по набору случайных чисел построим гистограмму распределения слу-
чайных чисел по значениям и теоретическую кривую на основе функции
плотности экспоненциального распределения.
Для построения графика функции плотности распределения нам по-
надобится наибольшее из вычисленных чисел (для верхней границы по
Глава 8. Обработка данных
343
аргументу при отображении функции). Наибольшее из случайных чисел
вычисляем командой Xmax=max(eta). Переменная k определяет ко-
личество рангов в гистограмме (столбцов в диаграмме на один больше).
Шаг дискретности по аргументу определяется в соответствии с количе-
ством рангов гистограммы командой h=Xmax/k. Список аргументов для
функции плотности распределения вычисляется как x=0:h:Xmax. Эти
же значения будем использовать для определения рангов гистограммы.
Командой hist(eta,x) создаем гистограмму. Здесь мы использовали
встроенную функцию hist() для создания гистограмм. Первым аргу-
ментом передается список значений, для которых строится гистограм-
ма, а второй аргумент определяет ранговые значения, для формирования
столбцов гистограммы.
На заметку
Если строится гистограмма на основе значений {}
iη (первый аргумент функ-
ции hist()),
1, 2, ...,
in
=
с ранговой разбивкой в соответствии со списком
{}jx (второй аргумент функции hist()),
1, 2, ...,
jm
=
, то в результате
строится диаграмма, высота столбиков которой равняется количеству значений
из списка {}
iη , которые попадают в диапазон между соседними точками j
xи
1
jx + (для всех возможных индексов). Функция hist() в качестве результата
возвращает список со значениями высоты столбцов гистограммы.
Гистограмма дает нам представление о законе распределения случайных
чисел. Нам этот закон необходимо сравнить с теоретической кривой для
экспоненциального распределения. Соответствующая теоретическая зави-
симость строится на основе функции плотности распределения. Так, если
случайные числа имеют плотность распределения ()
px,авсегочиселn,то
оценкой (точнее, математическим ожиданием) для количества чисел, по-
падающих в интервал значений от x до xd
x
+ (при малых значениях dx ),
будет значение
()
np x dx . В нашем случае роль dx играет переменная h.
Поэтому функцию для плотности распределения случайных чисел
() exp( )
px
x
αα
=−
следует умножить на коэффициент масштабирова-
ния R=n*h. Значения "масштабированной" плотности распределения
вычисляем командой p=Xmax*n/k*alpha*exp(-alpha*x). Для срав-
нения командой plot(x,p,'r-','LineWidth',2) строим график тео-
ретической зависимости. Приведенный код сохраняем в файле с именем
MyDist.m и в командном окне выполняем команду MyDist. Результаты
графических построений представлены на рис. 8.25.
Видим, что совпадение достаточно неплохое. Если увеличить количество
генерируемых точек, совпадение будет еще лучше.
Самоучитель Matlab
344
Статистические вычисления
-
Хотите доказательств?
-
Нет, не хочу. Сейчас начнете нудеть, паль-
цы загибать: "Это раз, это два, это три..." .
А у меня времени нет. Мне нужно быстрень-
ко жирную точку на этом деле поставить.
К/ф "Статский советник"
Существует ряд задач, при решении которых (с разной степенью успешно-
сти) могут применяться статистические методы. В качестве примера рас-
смотрим следующую задачу. Есть набор статистических данных (случайные
числа). Известно, что они распределены по нормальному закону с некото-
рым средним значением a и дисперсией
2
σ . Эти параметры неизвестны,
и их нужно определить (на основе статистических данных).
Для решения задачи используем метод моментов. Суть его состоит в том, что
для определения параметров распределения на основе статистических данных
вычисляются эмпирические моменты и приравниваются к соответствующим
теоретическим моментам. Теоретические моменты содержат неизвестные па-
раметры распределения. Таким образом, получаем систему алгебраических
уравнений, решая которую находим неизвестные параметры распределения.
Рис. 8.25. Распределение случайных чисел
Глава 8. Обработка данных
345
На заметку
Моментом порядка k случайной величины ξ называется математическое ожи-
дание от величины
k
ξ (обозначается как
k
M ξ ). Момент первого порядка на-
зывается математическим ожиданием случайной величины. Если случайная ве-
личина имеет плотность распределения ()
px , то момент порядка k для этой
случайной величины вычисляется как
()
kk
Mx
p
x
d
x
ξ
+∞
−∞
=
∫.
Для нормального распределения плотность дается выражением
2
2
1(
)
()
exp
2
2
xa
px
σ
πσ
⎛⎞
−
⎟
⎜
⎟
=−
⎜
⎟
⎜
⎟
⎜⎝⎠
.
Поскольку в задаче необходимо вычис-
лить два параметра, то нас будут интересовать первые два момента, то есть
()
Mx
p
x
d
x
a
ξ
+∞
−∞
==
∫
и
222
2
()
Mx
p
x
d
x
a
ξσ
+∞
−∞
==
+
∫
.
Эти теоретиче-
ские оценки необходимо сравнить с эмпирическими (вычисляемыми по
статистическим данным).
На заметку
Эмпирическим моментом порядка k , вычисляемым на основе выборки {}
ix
объема n (то есть
1, 2, ...,
in
=
), называется число
1
1
n
k
ki
i
mx
n=
=
∑.
Учитывая все приведенные выше обстоятельства, приходим к выводу, что
1
am
=
и
2
2
ma
σ=−
, где обозначено 1
1
1
n
i
i
mx
n=
=
∑и
2
2
1
1
n
i
i
mx
n=
=
∑.
Документ с исполнительным кодом приведен на рис. 8.26.
Помимо непосредственно вычислений, этот код содержит также и команды
для генерирования случайных чисел с параметрами (3, 4) (то есть
3
a=
и
2
4
σ = ). Рассмотрим этот код:
n=100000;
x=3+2*randn(1,n);
m1=sum(x)/n;
a=m1;
m2=sum(x.^2)/n;
sigma=sqrt(m2-a^2);
disp('Параметры распределения:');
disp(['a=',num2str(a),' и sigma=',num2str(sigma)]);
Самоучитель Matlab
346
Командой n=100000 задается значение для переменной, которая определя-
ет объем генерируемой выборки (количество генерируемых чисел). Числа
генерируются командой x=3+2*randn(1,n).
На заметку
Функция randn() генерирует случайные числа со стандартным нормальным
распределением, то есть со средним значением
0
a = и дисперсией
2
1
σ=
.
Нам нужны случайные числа с нормальным распределением и такими параме-
трами:
3
a=и
2
4
σ=
. Легко показать, что если случайная величина ξ имеет
стандартное нормальное распределение, то случайная величина
a
ησ
ξ
=+
будет иметь нормальное распределение с параметрами
2
(,)
a σ . Поэтому для
генерирования чисел с нормальным распределением с параметрами (3, 4) ис-
пользуем инструкцию 3+2*randn(). Это для генерирования одного числа.
Для генерирования серии чисел функции randn() передаются аргументы –
размеры создаваемого массива из случайных чисел.
Командой m1=sum(x)/n вычисляем эмпирический момент первого по-
рядка (среднее арифметическое). Командой m2=sum(x.^2)/n вычисля-
ется второй эмпирический момент. Стандартное отклонение (корень ква-
дратный из дисперсии
2
σ ) вычисляется командой sigma=sqrt(m2-a^2).
Перед этим командой a=m1 вычисляется оценка для параметра распределе-
ния a. Результаты вычислений выводятся на экран.
На заметку
Здесь мы намеренно не использовали встроенные функции для вычисления
статистических характеристик, наподобие mean() (вычисление среднего
значения), var() (вычисление дисперсии) или std() (вычисление среднего
значения). При использовании встроенных функций необходимо обращать вни-
мание, смещенная или несмещенная характеристики вычисляются. Это заме-
чание актуально для функций var() и std(). Детальное обсуждение особен-
ностей работы этих функций выходит за рамки книги.
Рис. 8.26. Определение параметров распределения
Глава 8. Обработка данных
347
Сохраняем командный код в файле с именем NormDist.m. В командном
окне выполняем команду NormDist. Результат показан в документе на
рис. 8.27.
Рис. 8.27. Результаты вычислений
Вычисленные значения достаточно близки к теоретическим. В принци-
пе, увеличение объема выборки повышает точность. Тем не менее, следует
помнить, что речь идет об обработке статистических данных, поэтому даже
очень большой объем выборки не гарантирует стопроцентной достоверно-
сти полученных результатов.
348
Глава 9
Символьные вычисления
-
Штирлиц, Вы ведь сами учили меня анали-
тичности и спокойствию.
-
Это Вы меня призываете к спокойствию?
После того, что сказали?!
К/ф "Семнадцать мгновений весны"
Несмотря на то, что приложение Matlab предназначено для выполнения чис-
ловых расчетов, в Matlab также можно выполнять расчеты и в символьном
виде – то есть расчеты, в которых используются символьные переменные,
а в результате получают символьные (аналитические) выражения. Именно
символьным вычислениям посвящена данная глава. Есть несколько спосо-
бов выполнять вычисления в символьном виде. Один, простой, подразуме-
вает использование специальных встроенных функций в командном окне,
второй, тоже простой, подразумевает использование специального пакета
инструментов (который называется Symbolic Math Toolbox).
Использование символьных переменных
Я должен Вас поздравить, Ватсон. Вы сде-
лали, в общем, правильные наблюдения. Вы
ошиблись только в знаке.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Знакомство"
В первую очередь рассмотрим способы ввода в рабочем документе (команд-
ном окне) символьных переменных – переменных, значениями которых яв-
ляются их названия. Другими словами, символьной переменной значение
не присваивается. Проблема в том, что если просто попытаться воспользо-
ваться переменной, которой не присвоено значение, появится сообщение об
ошибке. Поэтому необходимо предпринять некоторые предосторожности.
Предосторожности состоят в том, что символьные переменные предвари-
тельно необходимо объявить, для чего используем ключевое слово syms.
После этого ключевого слова указываются, через пробел, те переменные,
которые необходимо рассматривать как символьные. Если впоследствии
эти переменные используются в выражениях, то результат также получим
символьный. Пример использования символьных переменных приведен
в документе на рис. 9.1.
Документ любопытный, и имеет смысл рассмотреть его подробно. Пер-
вой командой в документе является инструкция syms a b c, которой
Глава 9. Символьные вычисления
349
объявляются три символьные переменные: a, b и c. Затем командой
x=(-b+sqrt(b^2-4*a*c))/2/a переменной x присваивается значение,
представленное в виде выражения, содержащего символьные переменные.
Таким образом, переменная x получает символьное значение. Значение этой
переменной так и отображается, в терминах переменных a, b и c в команд-
ном окне. Чтобы увидеть значение переменной x в более наглядном виде,
используем функцию pretty(), аргументом которой указывается сим-
вольное значение (в данном случае – переменная x). Переменную x в свою
очередь также можно использовать в дальнейших вычислениях. Например,
переменной eq значение присваивается командой eq=a*x^2+b*x+c. Здесь
отметим, что присвоенное переменной x значение определяется выражени-
Рис. 9.1. Использование символьных переменных
Самоучитель Matlab
350
ем
2
4
2
bba
c
x
a
−+
−
=
, которое, в свою очередь, есть не что иное, как один
из корней уравнения
2
0
ax
bxc
++=
. Поэтому значение переменной eq
должно с неизбежностью равняться нулю. Но убедиться в этом не просто.
При вычислении значения этой переменной получаем символьное выраже-
ние, в котором сложно узнать ноль. Не помогает и команда pretty(eq).
Ситуация проясняется, если воспользоваться командой simplify(eq).
Функцией simplify() упрощается выражение, указанное аргументом.
В данном случае после упрощения получаем ноль, как и следовало ожидать.
В символьном виде удобно задавать функции. Для этого аргумент (или ар-
гументы) функции предварительно объявляется как символьная перемен-
ная, после чего функция задается как выражение, зависящее от этой пере-
менной. Такой простой пример приведен в документе на рис. 9.2.
Рис. 9.2 . Функция задана через символьную переменную
Правда, вычисление таких функций имеет некоторые особенности. Напри-
мер, командой syms x y определяем две символьные переменные. Затем
командой f=sin(x)/x на основе символьной переменной x задаем значе-
ние переменной f. После этого переменную f можно использовать для ото-
бражения на графике соответствующей функциональной зависимости. Так,
результат выполнения команд ezplot(f,[-5*pi 5*pi]) и grid on по-
казан на рис. 9.3.
Глава 9. Символьные вычисления
351
Рис. 9.3. График функции, заданной на основе символьного выражения
Рис. 9 .4 . Замены в символьном выражении с несколькими переменными
Самоучитель Matlab
352
С вычислением значения такой своеобразной функции дела обстоят не-
сколько хуже. Чтобы вычислить значение функции в точке, используем
функцию subs(). Первым аргументом функции указывается переменная,
определенная на основе символьного выражения. Второй аргумент – зна-
чение для символьной переменной. Это значение, кстати, тоже может быть
символьным. В частности, командой subs(f,pi/2) вычисляется значение
для числового аргумента, а командой subs(f,y) вычисляется выражение
с заменой символьной переменной x на символьную переменную y.
Если в выражение входит несколько символьных переменных, то функцию
subs() используют в немного ином формате. Первым аргументом, как
и ранее, указывается переменная символьного выражения, а затем, через
запятую, заменяемая в выражении символьная переменная и ее значение.
На рис. 9.4 представлено продолжение предыдущего документа.
Команды здесь такие (жирным шрифтом выделен ввод пользователя):
>> z=cos(x*y)+x/y
z=
cos(x*y) + x/y
>> subs(z,x,1)
ans =
cos(y) + 1/y
>> subs(z,y,x)
ans =
cos(x^2) + 1
>> subs(subs(z,x,pi),y,0.5)
ans =
6.2832
Командой z=cos(x*y)+x/y задается символьное выражение, в которое
входят две символьные переменные x и y.
На заметку
Переменные x и y в качестве символьных объявлены ранее, в предыдущей ча-
сти документа – см. рис. 9.3 .
Результатом выполнения команды subs(z,x,1) является выражение,
получающееся заменой в выражении z переменной x на 1. При этом вы-
ражение z не меняется. В результате выполнения команды subs(z,y,x)
получаем выражение, которое получается из z заменой переменной y на x.
Причем результат автоматически упрощается (насколько это возможно).
Наконец, чтобы выполнить замену сразу нескольких символьных пере-
менных, используем конструкцию из вложенных функций subs(), как
в команде subs(subs(z,x,pi),y,0.5).
Глава 9. Символьные вычисления
353
Удобно то, что непосредственно в командном окне можно выполнять сим-
вольные операции и с числами. Для этого полезной станет функция sym().
Ее аргументом указывается (заключенное в одинарные кавычки) выраже-
ние, которое следует интерпретировать и обрабатывать как символьное. Та-
ким символьным выражением может быть и число. Обратимся к примеру
в документе, показанном на рис. 9.5.
Рис. 9.5. Символьные вычисления
Результатом команды sym('3/7')+sym('6/11') будет сумма дробей,
причем вычисленная "точно", без округления. Результат представляется
в виде правильной дроби. Далее, командой a=1+sqrt(sym('2')) опреде-
ляется переменная a с точным (символьным) значением 12
+ . Операции
с этой переменной выполняются так, что их результат также вычисляет-
ся в символьном виде. Например, результат выражения a^2 символьный.
Правда, он не очень компактный, но вызов команды simplify(a^2) упро-
щает соответствующее выражение.
На заметку
Для преобразования символьного числового выражения в формат числа с пла-
вающей точкой используется функция vpa(). Ее аргументом указывают вы-
числяемое (преобразуемое) выражение. Второй необязательный аргумент
определяет количество значащих цифр после десятичной запятой.
Самоучитель Matlab
354
Основные символьные операции
-
Интересное решение.
-
Вы думаете?
-
А что? Демократично, удобно.
-
Честно говоря, мне виделось нечто более
изящное.
К/ф "Чародеи"
В этом разделе кратко остановимся на некоторых задачах, которые часто
приходится (или желательно) решать в символьном виде. К ним, безуслов-
но, следует отнести дифференцирование, интегрирование, разложение
функции в ряд Тейлора, а также решение дифференциальных и алгебраи-
ческих уравнений. Для выполнения всех этих операций (а также многих
других) в Matlab есть специальные встроенные функции, с которыми нам,
собственно, и предстоит познакомиться. Начнем с дифференцирования.
Для вычисления производных (в том числе и частных) от символьных вы-
ражений используется функция diff(). У нее есть несколько форматов
вызова. Самый простой случай – если необходимо вычислить производную
от символьного выражения, в котором всего одна символьная переменная.
В этом случае выражение указывается аргументом функции diff(). Этот
и другие примеры вызова функции diff() представлены в документе на
рис. 9.6.
Рис. 9.6. Вычисление производных
Глава 9. Символьные вычисления
355
Командой syms x y объявляются две символьные переменные x и y. Затем
на основе этих переменных объявляем символьное выражение f=sin(x)/x.
Для вычисления производной от этого выражения используем команду
diff(f), в которой единственным аргументом функции diff() передано
дифференцируемое выражение. Производная автоматически вычисляется
по символьной переменной. Если переменных в выражении несколько, про-
изводная вычисляется по той, которая в алфавите "ближе" к букве x. На-
пример, определим выражение F=sin(x)*y^2 и продифференцируем его
с помощью команды diff(F). В данном случае производная вычисляется
по переменной x. Чтобы вычислить производную по переменной y, исполь-
зуем команду diff(F,y). Здесь вторым аргументом явно указана перемен-
ная, по которой вычисляется производная.
Если вторым аргументом функции diff() указать целое число, то оно
определит порядок производной от выражения, переданного первым аргу-
ментом функции. Обратимся к документу на рис. 9.7.
Рис. 9.7. Производная второго порядка
Здесь командой f=sym('(x^3-5*x^2+3*x)*sin(x)') определяется
символьное выражение, в которое входит всего лишь одна символьная пе-
ременная x.
На заметку
Обратите внимание, как определяется символьное выражение: в одинарных
кавычках оно указывается аргументом функции sym().
Вторую производную от созданного символьного выражения вычисляем
с помощью команды diff(f,2). Можно также вызвать функцию diff()
со следующим способом передачи аргументов: дифференцируемое выраже-
ние, переменная дифференцирования и порядок дифференцирования. На-
пример, команда diff(f,x,2) означает вычисление второй производной
от выражения f по переменной x.
Самоучитель Matlab
356
Обратной к дифференцированию является процедура интегрирования.
В данном случае имеется в виду вычисление первообразной.
На заметку
Первообразной для функции ()
fx называется такая функция ()
Fx , произво-
дная от которой равняется ()
fx , то есть по определению
() ()
Fx fx
′
=
.
За-
дача вычисления неопределенного интеграла от функции ()
fx (обозначается
()
fxdx
∫ ) сводится к вычислению упомянутой выше функции ()
Fx . Другими
словами, если ()
()
Fx
fxdx
=
∫ , то это означает, что
() ()
Fx fx
′
=
.
Перво-
образная вычисляется с точностью до аддитивной постоянной, которую обычно
для простоты не упоминают.
Для вычисления интеграла от символьного выражения используют функ-
цию int(). Если единственным аргументом указано символьное выраже-
ние с одной символьной переменной, то в результате возвращается перво-
образная для выражения (если эту первообразную удается найти). Если
в выражении несколько символьных переменных, интеграл вычисляется
по переменной, наиболее близкой в алфавитном списке к букве x. Чтобы
явно указать переменную интегрирования, ее передают вторым аргументом
функции int(). Примеры приведены в документе на рис. 9.8.
Последовательность команд такая (жирным шрифтом выделен ввод поль-
зователя):
>> f=sym('ln(x)')
f=
log(x)
>> int(f)
ans =
x*(log(x) - 1)
>> int('exp(a*x)*cos(b*x)')
ans =
(exp(a*x)*(a*cos(b*x) + b*sin(b*x)))/(a^2 + b^2)
>> int('exp(a*x)',sym('a'))
ans =
exp(a*x)/x
Сначала в переменную f записываем символьное выражение
sym('ln(x)'). Затем командой int(f) вычисляем интеграл
ln( )
(ln( ) 1)
xdxxx
=−
∫
.
Другой пример – вычисление интеграла
22
exp( )( cos( )
sin( ))
exp( ) cos( )
axa
bxbbx
ax
bx dx
ab
+
=
+
∫
с помощью команды
Глава 9. Символьные вычисления
357
int('exp(a*x)*cos(b*x)'). В обоих случаях интегрирование по умол-
чанию выполняется по переменной x. Примером явного указания перемен-
ной интегрирования может быть команда int('exp(a*x)',sym('a')),
которой вычисляется интеграл
exp( )
exp( )
ax
ax da
x
=
∫
по переменной a.
Для вычисления определенных интегралов в символьном виде также ис-
пользуется функция int(). Только теперь она вызывается в несколько
ином формате. Так, если переменная интегрирования определяется авто-
матически, то помимо подынтегрального выражения аргументами функ-
ции int() передаются пределы интегрирования – это второй и третий
аргументы. Если вторым аргументом указать переменную интегрирова-
ния, то пределы интегрирования указываются третьим и четвертым аргу-
ментами.
На заметку
Напомним, что между определенным и неопределенным интегралами су-
ществует связь. Так, если имеет место соотношение
() ()
fxdx Fx
=
∫
,
Рис. 9 .8. Вычисление неопределенных интегралов
Самоучитель Matlab
358
то определенный интеграл
()()()
b
a
fxdx Fb Fa
=−
∫
. О бычно значение опре-
деленного интеграла отождествляют с площадью под графиком функции ()
fx
на интервале значений аргумента axb
≤≤.
В документе на рис. 9.9 приведены примеры вычисления определенных ин-
тегралов:
Рис. 9.9. Определенный интеграл
Рассмотрим команды подробнее (жирный шрифт означает ввод пользова-
теля):
>> int('tan(z)',0,pi/4)
ans =
log(2)/2
>> syms b positive
>> int('sin(b*x)/x',0,inf)
ans =
pi/2
Интеграл
4
0
ln(2)
()2
tgzdz
π
=
∫
вычисляется командой int('tan(z)',0,
pi/4). В данном случае первым аргументом функции int() передается
интегрируемое символьное выражение (подынтегральная функция), а вто-
рой и третий аргументы – пределы интегрирования по символьной пере-
менной z. Выбор на эту переменную пал в силу ее единственности в под-
ынтегральном выражении.
Перед вычислением следующего интеграла мы используем команду
syms b positive для того, чтобы объявить символьную переменную b
Глава 9. Символьные вычисления
359
и указать, что она положительная (ключевое слово positive в объявлении
переменной) – эта информация важна при вычислении интеграла Дирихле
0
sin( )
2
bx
dx
x
π
∞
=
∫
.
Интеграл вычисляем командой int('sin(b*x)/x',
0,inf). Для обозначения бесконечности используем ключевое слово inf.
Еще одна достаточно часто встречающаяся на практике задача – разложе-
ние функции в степенной ряд (обычно ряд Тейлора).
На заметку
Рядом Тейлора для функции ()
fx в окрестности точки a называется бесконеч-
ная сумма
0
()
()n
n
n
fx
cxa
∞
=
=−
∑
.
Коэффициенты разложения n
c определя-
ются на основе производных n -го порядка
()()
n
faфункции ()
fxвточкеa,
а именно:
()()
!
n
n
fa
c
n
=
.
Для вычисления ряда Тейлора функций (точнее, конечного количества
слагаемых этого ряда) используют функцию taylor(). Первым аргумен-
том функции указывается раскладываемое в ряд выражение. Далее может
быть указана символьная переменная, по которой выполняется разложе-
ние. Если переменная не указана, она определяется автоматически по тем
же критериям, что описывались выше для задачи интегрирования или
дифференцирования. Следующий числовой аргумент определяет степень
первого отбрасываемого слагаемого ряда (например, значение 10 этого ар-
гумента означает, что в ряд будут вычислены слагаемые до 9 степени вклю-
чительно). Также можно указать аргументом точку, в окрестности которой
выполняется разложение в ряд. Если этот аргумент не указан, разложение
выполняется в окрестности нуля. На рис. 9.10 приведены простые примеры
разложений в ряд Тейлора.
Командой f=sym('sin(x)/x') задаем исходное выражение (это
2
0
sin( )
(1)
(2 1)!
nn
n
xx
xn
∞
=
−
=
+
∑
). Командой taylor(f,10) вычисляем первые
пять слагаемых ряда Тейлора, а командой pretty(ans) вычисленный ре-
зультат представляем в более-менее пристойном виде. Здесь мы для ссыл-
ки на результат выполнения предыдущей команды использовали ключевое
слово ans.
Самоучитель Matlab
360
На заметку
Команда taylor(f,10) означает, что при разложении выражения
f в ряд учитываются слагаемые до 9 степени включительно. В сумме
24681
0
sin( )
1
...
3!5!7!9!11!
x
xxxxx
x
=
−+−+− +слагаемое с показателем сте-
пени 9 по переменной x отсутствует. Поэтому остаются слагаемые до 8-й сте-
пени включительно.
Следующей командой pretty(taylor(sym('ln(t)'),5,1)) выполня-
ется разложение натурального логарифма ln( )t по переменной t в окрест-
ности точки
1
t = до 4-й степени включительно. Результат сразу приво-
дится к читабельному виду. Как несложно убедиться, в результате получаем
первые слагаемые ряда
1
1
(1)( 1)
ln( )
nn
n
t
t
n
∞
+
=
−−
=
∑
.
Кроме рассмотренных задач, хочется остановиться еще на двух – решении ал-
гебраических и дифференциальных уравнений и систем. Начнем с алгебры.
Алгебраические уравнения и системы в символьном виде решаются с по-
мощью функции solve(). Некоторые способы вызова этой функции для
Рис. 9.10. Разложение в ряд Тейлора
Глава 9. Символьные вычисления
361
решения уравнений и систем рассмотрим на конкретных примерах. Для на-
чала стоит обратить внимание на рис. 9.11.
Рис. 9.11 . Решение квадратного уравнения
Здесь для решения квадратного уравнения
2
0
ax
bxc
++=в символьном
виде мы воспользовались командой solve('a*x^2+b*x+c=0') (и затем
командой pretty(ans) для изменения формы представления результата).
Таким образом, единственным аргументом функции solve() указано ре-
шаемое уравнение. Поскольку в соответствующем выражении имеется
переменная x, относительно этой переменной и решается уравнение. Если
нужно явно указать переменную, относительно которой решается уравне-
ние, она указывается вторым аргументом функции solve().
Примерно так же просто решаются системы уравнений: решаемые уравне-
ния системы передаются аргументами функции solve(). Можно также
явно указать переменные, относительно которых решается система. При-
мер представлен в документе на рис. 9.12.
Здесь мы решаем систему уравнений
22
25
xy
+=и
1
yx
−=
. У системы
два решения:
3
x=
,
4
y=и
4
x=−,
3
y=−
. Нам понадобятся две коман-
ды. Команда объявления символьных переменных syms x y и команда
[x y]=solve('x^2+y^2=25','y-x=1',x,y), которой непосредственно
решается система уравнений. Несложно убедиться, что решения найдены
правильно.
Самоучитель Matlab
362
Решение дифференциального уравнения или системы дифференциальных
уравнений могут быть найдены посредством функции dsolve().
На заметку
Здесь речь идет об обыкновенных дифференциальных уравнениях. Такие урав-
нения содержат неизвестную функцию от одной переменной, а также произво-
дные (разного порядка) от этой функции.
Чтобы решить дифференциальное уравнение, его нужно передать аргумен-
том функции dsolve(). Возникает вопрос, как записать дифференциаль-
ное уравнение? Существует несколько правил.
1. Для обозначения операции дифференцирования используется символ D.
2. Операция вычисления n-й производной указывается в формате Dn (то
есть символ D и порядок производной).
3. По умолчанию независимой переменной полагается переменная t. Если
используется другое имя для независимой переменной, она указывается
последним аргументом функции dsolve().
На заметку
Дифференциальное уравнение может решаться само по себе, а может решать-
ся вместе с начальными условиями. В последнем случае речь идет о задаче
Коши. Если кроме дифференциального уравнения необходимо учесть началь-
ные условия, то они передаются аргументами функции dsolve(). Если ре-
шается одно только уравнение, то результат будет содержать константы инте-
грирование – независимые произвольные константы. Количество постоянных
интегрирования совпадает с порядком дифференциального уравнения или
старшей производной в уравнении. Постоянные интегрирования по умолчанию
обозначаются в выводимом результате как C1, C2 и так далее.
Рис. 9.12. Решение системы уравнений
Глава 9. Символьные вычисления
363
Примеры решения дифференциальных уравнений приведены в документе
на рис. 9.13.
Рис. 9.13. Решение дифференциальных уравнений
Командой dsolve('Dz+3*z=2*cos(x)','x') решается дифференци-
альное уравнение
() 3() 2cos()
dzx
zx
x
dx
+=
.
В результате получаем общее
решение для функции
31
() cos()
sin()
55e
x
p
(
3
)
C
zx
x
x
x
=++, где через C
обозначена постоянная интегрирования (в документе на рис. 9.13 эта кон-
станта обозначена как C18 – индекс является следствием особенностей ал-
горитма, использованного для вычисления результата).
Командой dsolve('D2y+25*y=0','y(0)=2','Dy(0)=-1') решается
задача Коши: дифференциальное уравнение
2
2
()25() 0
dyt
yt
dt
+=
с началь-
ными условиями (0) 2
y=и
(0
)1
dyt
dt
=
=−.
Решение этой задачи имеет
вид
1
() 2cos(5) sin(5)
5
yt
t
t
=−
. Именно такое решение и найдено.
Наконец, в документе на рис. 9.14 показан возможный способ решения сис-
темы дифференциальных уравнений.
В результате выполнения команды [x y]=dsolve('Dx=x+2*y',
'Dy=3*x-4*y','x(0)=1','y(0)=2') получаем решение системы диф-
ференциальных уравнений
() () 2()
dxt
xt yt
dt
=+и
() 3() 4()
dyt
xt yt
dt
=−
Самоучитель Matlab
364
с начальными условиями (0) 1
x
=
и(0)2
y=
. Получено корректное реше-
ние
10
3
() exp(2) exp( 5)
77
xt
t
t
=−
−
и
59
() exp(2) exp( 5)
77
yt
t
t
=+
−
.
Собственно говоря, это далеко не полный перечень тех символьных опе-
раций, которые могут выполняться в командном окне. Однако следует по-
нимать, что командное окно, в общем-то, и не рассчитано на выполнение
символьных расчетов. Несложно догадаться, что в Matlab есть другое "ме-
сто", которое подходит для этих целей куда больше. Это "место" – редактор
встроенной среды - системы компьютерной алгебры MuPAD, реализован-
ный в пакете инструментов Symbolic Math Toolbox. Разумно познакомиться
с этой утилитой поближе.
Среда MuPAD
Ну кто так строит? Кто так строит?
К/ф "Чародеи"
Чтобы увидеть во всей красе встроенный редактор среды MuPAD, достаточ-
но в главном окне приложения Matlab выполнить команду Start ► Toolboxes
► Symbolic Math ► MuPAD, как показано на рис. 9.15.
Можно также в командном окне выполнить команду mupad. В результате
откроется окно приветствия, в котором необходимо сделать выбор относи-
тельно дальнейших планов работы со средой MuPAD (рис. 9.16).
В данном случае мы планируем создать новый документ, поэтому в окне
приветствия щелкаем кнопку New Notebook. После этого откроется непо-
средственно редактор среды MuPAD с новым пустым документом. Наблю-
дать эту красоту можно на рис. 9.17.
Рис. 9.14 . Решение системы дифференциальных уравнений
Глава 9. Символьные вычисления
365
Рис. 9.15. Запуск реактора среды MuPAD
Рис. 9.16. Создание нового документа MuPAD
Самоучитель Matlab
366
Рис. 9.17. Редактор среды MuPAD с новым пустым документом
Рис. 9.18. Примеры простых вычислений в MuPAD
Глава 9. Символьные вычисления
367
Структура окна редактора MuPAD достаточно консервативна. Среди функ-
циональных элементов интерфейса можно выделить панель меню и панель
инструментов в верхней части окна и палитры в правой колонке. Основная
белая область в окне редактора – это то рабочее пространство, в котором
выполняются вычисления. Здесь вводятся команды, и отображается ре-
зультат их выполнения. Подсказкой места ввода служит мигающий курсор
и специальная метка в виде открытой квадратной скобки.
Но мало найти место, куда вводить команды, необходимо знать, как их вво-
дить. Другими словами, необходимо иметь хотя бы общее представление
о тех правилах, которые определяют командный язык, используемый в Mu-
PAD. В силу объективных и очевидных причин, здесь мы рассмотрим толь-
ко основные команды и приемы. Особенности графического интерфейса
будут описываться по мере надобности в контексте решаемых задач.
На заметку
Прежде, чем приступить к обзору возможностей MuPAD, немного истории. Сре-
да (более точный термин – система компьютерной алгебры) MuPAD с 1997 года
разрабатывалась и развивалась как отдельный проект группой разработчиков
из университета Падерборна (Германия) и компанией SciFace Software. Суще-
ствовала бесплатная и коммерческая версии продукта. После покупки в 2008
году компании SciFace компанией Mathworks среда MuPAD стала составной ча-
стью пакета инструментов Symbolic Math Toolbox приложения Matlab.
В MuPAD пользователю предлагается широкий спектр возможностей по реше-
нию самых разнообразных задач, в том числе и с использованием специальных
подпакетов. Основу MuPAD составляет оригинальный командный язык, который
очень напоминает командный язык Maple и поддерживает методы объектно-
ориентированного программирования. На самом деле первое знакомство с
командами MuPAD уже состоялось – в предыдущих разделах мы использовали
функции для выполнения символьных операций.
На рис. 9.18 показан документ MuPAD с примерами простых вычислений.
Принцип достаточно простой: в рабочей области в том месте, где мигает кур-
сор (область ввода) вводим команду, а для ее выполнения нажимаем клави-
шу <Enter>. Под командой, в области вывода, отображается результат.
На заметку
По умолчанию команды ввода отображаются красным цветом, а результат их
выполнения – синим. Есть еще текст, который отображается черным цветом.
Чтобы результат выполнения не отображался в области вывода, а конце коман-
ды следует поставить двоеточие.
Синтаксис арифметических операций близок к их соответствующей мате-
матической записи. Среди используемых операторов есть оператор сложе-
ния (+), оператор умножения (*), оператор вычитания (-), оператор деле-
Самоучитель Matlab
368
ния (/), оператор возведения в степень (^) и другие. Оператором присва-
ивания является комбинация двоеточия и знака равенства (:=). Символь-
ная константа PI означает число π, мнимая единица обозначается как I. По
умолчанию все операции выполняются в символьном виде. Например, при
вычислении значения sin(PI/4) возвращается символьный ре
зультат
2
2
, а не приближенное значение в формате числа с плавающей
точкой. Но
если нужно именно такое значение – тоже нет проблем. Можно воспользо-
ваться функцией float(). Аргументом передается выражение, которое не-
обходимо представить в формате числа с плавающей точкой. Нередко аргу-
ментом указывается символ % - указатель на результат выполнения послед-
ней ко манды.
На заметку
По сравнению с командным окном Matlab, рабочая область среды MuPAD имеет
важное отличие: команды в рабочей области можно выполнять в разной после-
довательности, причем по несколько раз. Другими словами, порядок следова-
ния команд в рабочей области не обязательно совпадает с последовательно-
стью их выполнения. Более того, если команда введена и выполнена, ее можно
отредактировать и выполнить снова.
Количество значащих цифр, отображаемых в формате с плавающей точкой,
задается системной переменной DIGITS и по умолчанию равно 10. Чтобы
изменить это значение, переменной DIGITS присваивают новое значение
(например, DIGITS:=30). Чтобы вернуть настойки по умолчанию, вызыва-
ем команду delete DIGITS. Такого же типа инструкцию используют для
"сброса" значений символьных переменных.
Разумеется, возможности среды MuPAD не ограничиваются алгебраически-
ми вычислениями. Те же задачи, которые рассматривались выше, решаются
в MuPAD с ощутимо большим эффектом. Немаловажное достоинство –
создание качественной графики и анимации. На рис. 9.19 представлен до-
кумент с двумерным графиком функции.
Двумерный график создаем командой plot(cos(x)+cos(3*x),x=0..4
*PI). Основу команды составляет функция plot(). Первым аргументом
функции передается выражение, которое определяет отображаемую на гра-
фике зависимость. Второй аргумент – независимая переменная и диапазон
ее значений.
На заметку
Диапазон изменения переменной указывается так: переменная, знак равенства
и границы диапазона изменения переменной, разделенные двумя точками.
Глава 9. Символьные вычисления
369
Рис. 9.19. Создание двумерного графика
Рис. 9.20. Создание трехмерного графика
Самоучитель Matlab
370
С помощью той же функции plot() создается и трехмерная графика.
В этом случае первым аргументом функции передается выражение, завися-
щее от двух символьных переменных, а также диапазон изменения каждой
из переменных. Индикатором того, что график трехмерный, является опция
#3D, которая обычно в списке аргументов указывается последней. Пример
создания трехмерного графика приведен на рис. 9.20.
Здесь мы использоваликомандуplot(sin(sqrt(x^2+y^2))/sqrt(x^2+
y^2),x=-4*PI..4*PI,y=-4*PI..4*PI,#3D). Кроме перечисленных
параметров, при работе с графикой используются многие другие опции, ко-
торые мы рассмотрим несколько позже. Сейчас перейдем к рассмотрению
основных классов задач – опишем, как они решаются в среде MuPAD.
Определение функции
Сначала меня это забавляло - с одной
стороны. Но, с другой, я понимал, что
пора объясниться.
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
До этого мы работали с выражениями. Но на практике бывает намного
удобнее определить ту или иную функциональную зависимость и рабо-
тать с ней. В среде MuPAD функция может задаваться несколькими спо-
собами. Здесь мы рассмотрим наиболее простой – с помощью оператора
"стрелка" (оператор ->). Функция в этом случае определяется так: указы-
вается имя функции, оператор присваивания, список аргументов (разде-
ленных запятыми), оператор -> и выражение, в которое входят аргументы
и которое определяет функциональную зависимость. Например, командой
y:=x->x^2 задается функция
2
()
yxx
=
. Фактически здесь переменная y
определяется как оператор. Действие этого оператора на аргумент x сво-
дится к тому, что вычисляется значение x^2. При этом переменная x играет
роль локальной переменной.
Рассмотрим документ, представленный на рис. 9.21.
В этом документе мы определили функцию
sin( )
()x
fx
x
=
с помощью
команды f:=x->sin(x)/x. Затем эта функция используется в разных вы-
ражениях. Так, ее можно вызывать с символьным аргументом: f(z) или
f(PI/4). Удобно использовать функции при отображении графиков, по-
скольку команда вызова функции выглядит намного компактнее по срав-
нению с выражением, задающим соответствующую функциональную зави-
симость.
Глава 9. Символьные вычисления
371
На рис. 9.22 приведен пример объявления и использования функции двух
переменных.
Функция объявляется командой F:=(x,y)->sin(x)*sin(y)/sqrt(x^2+
y^2). Там же приведен пример вызова этой функции при создании двумер-
ного графика. При этом функция передается с одним фиксированным аргу-
ментом. На рис. 9.23 приведены другие примеры использования функции
двух переменных.
На заметку
Стоит отметить, что необходимости отдельно объявлять символьные перемен-
ные в среде MuPAD нет. Все переменные по умолчанию полагаются символьны-
ми, а операции выполняются в символьном виде.
Рис. 9 .21. Определение функции
Самоучитель Matlab
372
Рис. 9.22. Функция двух переменных
Рис. 9 .23. Использование функции двух переменных
Глава 9. Символьные вычисления
373
Вычисление производных
Нас всех губит отсутствие дерзости
в перспективном видении проблем. Мы не
можем себе позволить фантазировать.
К/ф "Семнадцать мгновений весны"
Не будет большой новостью узнать, что производные в MuPAD вычисля-
ются с помощью функции diff(). Дифференцируемое выражение ука-
зывается первым аргументом функции, а переменная дифференцирова-
ния – вторым. Примеры использования функции diff() для вычисления
производной приведены в документе на рис. 9.24.
Рис. 9.24. Производная от функции одной переменной вычислена
с помощью функции diff()
Дифференцируемое выражение может быть непосредственно указано аргу-
ментом функции diff(), как в команде diff(x^2*sin(x),x). Этой же
функцией diff() вычисляются производные высоких порядков. В общем
случае переменные, по которым вычисляются производные от выражения –
первого аргумента функции diff(), указываются через запятую в соответ-
ствии с порядком вычисления производной. Поскольку переменная диффе-
ренцирования в данном случае одна, то именно она через запятую указывается
в списке аргументов функции diff(). Например, команда diff(f(x),x)
Самоучитель Matlab
374
означает первую производную, а команда diff(f(x),x,x) означает вто-
рую производную. В обоих случаях дифференцируется выражение f(x), вы-
численное на основе функции f(), определенной ранее.
На заметку
Результат вычисления производной очень часто представлен в неупрощенном
виде. Для упрощения результата используют функцию simplify(), аргумен-
том которой передается упрощаемое выражение. Бывает удобно в качестве
ссылки на результат предыдущей команды использовать инструкцию %, как, на-
пример, в команде simplify(%).
Интерес представляет команда simplify(diff(f(x),x$100)). Во-
первых, здесь команда дифференцирования "спрятана" аргументом функ-
ции simplify() – то есть производная вычисляется, и результат сразу
упрощается. Но что же это за производная? Это 100-я производная по пере-
менной x от выражения f(x). Чтобы понять это, необходимо учесть, что
результатом инструкции x$100 является последовательность из 100 эле-
ментов, каждый из которых равен x.
На заметку
Последовательность – набор элементов, разделенных запятыми. Оператор по-
следовательности $ имеет несколько форм вызова. В формате x$n формиру-
ется последовательность из n элементов x.
Что касается функции diff(), то она хороша всем, кроме одного – с ее по-
мощью не получится вычислить производную для конкретного числового зна-
чения аргумента. В этом случае сначала придется получить общее символьное
выражение, а уже затем подставить вместо аргумента нужное числовое значе-
ние. Благо, кроме функции diff(), есть и другие способы вычислить произ-
водную.
При работе с функциями одной переменной производные можно вычис-
лять с помощью специального оператора производной – штриха. Штрих
возле имени функции означает производную от этой функции. Также про-
изводная вычисляется с помощью функции D(). Аргументом этой функ-
ции указывается имя функции, для которой вычисляется производная.
Обратимся к примерам в продолжении рассмотренного выше документа,
представленном на рис. 9.25.
Если воспользоваться командой вида f', в результате получим формальное
правило вычисления производной от функции одной переменной f().
На заметку
Чтобы понять результаты вычислений, в которых используются функции, удоб-
но представлять функции как операторы. Команду определения функции вида
имя_функции:=аргументы->выражение можно интерпретировать следующим
Глава 9. Символьные вычисления
375
образом. Инструкция аргументы->выражение задает правило, определяющее,
какие действия должны быть выполнены, в соответствии с этим правилом, над
аргументами, чтобы получить выражение. Это правило в качестве значения при-
сваивается переменной имя_функции. Эта переменная становится оператором,
действие которого на аргументы сводится к применению соответствующего пра-
вила. Другими словами, если имеет место команда имя_функции(аргументы),
то результат получается применением правила аргументы->выражение к аргу-
ментам.
Если используем команду f'(z), то получаем значение производной от
функции f(z) по переменной z. Удобно и то, что при вычислении произ-
водной с помощью оператора "штрих" аргументом функции может быть
указано число – например, как в команде f'(2). В этом случае сначала
вычисляется производная, а затем в полученное выражение вместо сим-
вольной переменной, по которой вычислялась производная, подставляется
значение 2.
Рис. 9.25. Вычисление производной с помощью функции D() и символа производной
Самоучитель Matlab
376
Оператор "штрих" можно использовать несколько раз подряд, чтобы вы-
числить производную более высокого порядка, чем первый. Так, произво-
дная второго порядка вычисляется командой f''(t). Правда, такой под-
ход не очень удобен при вычислении производных очень высокого порядка.
Намного легче это сделать с помощью функции D(). Аргументом функции
указывается имя дифференцируемой функции. Результатом является опе-
ратор, определяющий функциональную зависимость для производной от
исходной функции. Таким образом, этот оператор может быть применен к
аргументу (или аргументам). Например, инструкцией D(f) вычисляется
оператор для производной. Командой D(f)(z) вычисляется выражение
для производной при значении символьной переменной z, а командой D(f)
(2) вычисляется значение производной при значении аргумента 2. Вычис-
лить производную высокого порядка (например, 100-ю) можно с помощью
оператора функциональной композиции @@, который полезен при много-
кратном действии функционального оператора. Команда вычисления 100-й
производной имеет вид (D@@100)(f)(t).
На заметку
По определению оператора @@ инструкция вида (f@@5)(x) означает вы-
числение выражения f(f(f(f(f(x))))). Соответственно, инструкция
(D@@100)(f)(x) означает вычисление выражения D(D(...(D(D(f)))))
(x) – символов D должно быть ровно 100.
Частные производные также вычисляются достаточно просто. В этом случае
применяется функция diff() или функция D(). В документе на рис. 9.26
процесс вычисления частных производных иллюстрируется на примере
функции ( , )
exp()
n
Fxy
x
ay
=−
двух переменных – задается командой
F:=(x,y)->x^n*exp(-a*y).
Частая производная
2
(,)
Fxy
xy
∂
∂∂
вычисляется командой diff(F(x,y),x,y).
Здесь первый аргумент diff() является дифференцируемым выражени-
ем, а два других аргумента обозначают переменные, по которым вычисля-
ются производные.
При вычислении частных производных с помощью функции D() первым ее
аргументом указывается список с числами, определяющими номера аргу-
ментов функции, по которым вычисляются частные производные. Второй
аргумент функции D() является именем функции, от которой вычисляют-
ся частные производные. Инструкция D([1],F) означает, что производная
вычисляется по первому аргументу функции F(). Результатом является
оператор, определяющий функциональную зависимость для соответствую-
щей частной производной.
Глава 9. Символьные вычисления
377
Команда D([1,2],F)(x,y) означает частную производную
2
(,)
Fxy
xy
∂
∂∂
(то
есть производная по первому x и второму y аргументам). Для вычисления
производной
6
5
2
1
(,)
x
y
Fxy
xy=
=
∂
∂∂
(пятая производная по первому аргументу и пер-
вая производная по второму аргументу, при значении первого аргумента 2 и
значении второго аргумента 1) используем команду D([1$5,2],F)(2,1).
На заметку
Результат инструкции 1$5 есть последовательность из пяти единиц, то есть
1,1,1,1,1.
Рис. 9.26. Вычисление частных производных разными методами
Самоучитель Matlab
378
Вычисление интегралов
Если возражений нет, то форма принима-
ется. Приступим к проверке содержания.
К/ф "Чародеи"
Интегралы вычисляются функцией int(). Первым аргументом указывает-
ся подынтегральное выражение. Второй аргумент – переменная интегриро-
вания. Если интеграл определенный, то переменная интегрирования указы-
вается вместе с диапазоном изменения.
На заметку
Бесконечность обозначается ключевым словом infinity.
Примеры вычисления интегралов приведены в документе на рис. 9.27.
Рис. 9.27. Вычисление интегралов
Неопределенный интеграл
22
sin( )
cos( )
exp( ) cos( )
exp( )
bb
xab
x
ax
bx dx
ax
ab
−
−=
−
+
∫
вычисляется командой int(exp(-a*x)*cos(b*x),x). Для вычисления
определенного интеграла
0
1
exp( ) cos(5 )
26
xx
d
x
∞
−=
∫
используем коман-
Глава 9. Символьные вычисления
379
ду int(exp(-x)*cos(5*x),x=0..infinity). Так же легко вычисля-
ется интеграл
2
37
0
1
cos( ) sin( )
40
xx
d
x
π
=
∫
.
В этом случае мы используем
команду int(cos(x)^3*sin(x)^7,x=0..PI/2). Здесь все достаточно
просто. Тем не менее, нередко при вычислении интегралов, особенно не-
собственных, приходится задавать дополнительные условия относитель-
но параметров, которые входят в интеграл. Например, интеграл Пуассона
2
0
1
exp(
)2
ax dx
a
π
∞
−=
∫
сходится при значениях параметра
0
a> .Привы-
числении соответствующего интеграла в среде MuPAD необходимо пред-
варительно указать, что переменная a, входящая в подынтегральное выра-
жение, положительна. Для этого перед вычислением интеграла командой
assume(a>0) задаем нужное ограничение на переменную a. После этого
интеграл вычисляется командой int(exp(-a*x^2),x=0..infinity).
К сожалению, далеко не любой интеграл можно вычислить в аналитиче-
ском виде. В этом случае в области вывода отображается символьное пред-
ставление для интеграла, как это показано на рис. 9.28 при попытке вы-
числить интеграл
1
0
sin(2 )
1
x
dx
x
π
+
∫
с помощью команды int(sin(2*PI*x)/
sqrt(1+x),x=0..1).
Рис. 9.28. Вычисление определенного интеграла в числовом виде
Самоучитель Matlab
380
В таком случае можно прибегнуть к вычислению интеграла в числовом виде.
Для этого используем команду float(int(sin(2*PI*x)/sqrt(1+x),
x=0..1)) или
numeric::int(sin(2*PI*x)/sqrt(1+x),x=0..1).
В первом случае выполняется попытка вычислить интеграл в символьном
виде, и если не удается, то вычисления производятся с использованием число-
вых алгоритмов. Во втором случае числовые алгоритмы используются сразу.
Решение алгебраических уравнений
и неравенств
Работа у меня такая – думать дальше
своего носа.
Дж. Буш (младший)
Для решения алгебраических уравнений и неравенств используется функ-
ция solve(). Аргументами функции solve() передаются уравнения или
неравенства, которые необходимо решить. Если уравнений (неравенств)
несколько, они оформляются в виде списка – заключаются в квадратные
скобки. Кроме уравнений и неравенств, обычно указывают переменные, от-
носительно которых решается уравнение, неравенство или система. Если
таких переменных несколько, то они тоже заключаются в квадратные скоб-
ки. Пример решения алгебраического уравнения и системы из двух алге-
браических уравнений приведен в документе на рис. 9.29.
Рис. 9.29. Решение алгебраических уравнений и систем
Глава 9. Символьные вычисления
381
Показательной в данном случае является команда solve(eq,x), которой
решается квадратное уравнение общего вида (то есть
2
0
ax
bxc
++=).
Предварительно это уравнение командой eq:=a*x^2+b*x+c=0 присваи-
вается в качестве значения переменной eq. Обращаем внимание, что резуль-
тат представлен для всех случаев: общий (если параметр
0
a ≠ ), решение
линейного уравнения
0
bxc
+= (при значении параметра
0
a = ), множе-
ство комплексных чисел » (при всех нулевых значениях
0
abc
===
решением уравнения является любое число) и пустое множество ∅ (при
значениях параметров
0
ab
== и ненулевом параметре
0
c ≠ уравнение
решений не имеет).
Для решения системы уравнений 2225
xy
+=и
1
yx
− = используем
команду solve([x^2+y^2=25,y-x=1],[x,y]). Здесь первым аргумен-
том функции solve() передан список [x^2+y^2=25,y-x=1] с уравнени-
ями решаемой системы, а второй аргумент – список [x,y] с переменными,
относительно которых решается система.
Точно так же обстоят дела с неравенствами. Некоторые простые примеры
решения неравенств приведены в документе на рис. 9.30.
Рис. 9.30 . Решение неравенств
Командой solve(x^2-5*x+6<0,x) предпринимаем попытку решить
неравенство
2
560
x −+ <. На множестве действительных чисел реше-
ние этого неравенства – диапазон значений аргумента от 2 до 3, то есть
(2, 3)
x∈
. Этот диапазон отображается в области вывода результата. Тем не
менее, кроме этого диапазона, там можно видеть что-то еще. Причина в том,
что решение ищется на множестве комплексных чисел.
Самоучитель Matlab
382
На заметку
В качестве "дополнительного" решения указано множество вида
5
2
iy
+ ,где
через i обозначена мнимая единица 2
1
i=−
. Через y обозначена действи-
тельная переменная. Если в выражение
2
56
zz
− +подставить значение
5
2
zi
y
=+ , получим действительное выражение
21
0
4
y
−−<
.
С одной стороны, это удобно. С другой стороны – ситуация существенно
усложняется, а простые задачи нередко становятся сложными. Поэтому не-
редко приходится явно указывать, что решение ищется на каком-то множе-
стве – обычно это множество действительных чисел. Например, чтобы най-
ти решение неравенства на множестве действительных чисел, используем
команду solve(x^2-5*x+6<0,x) assuming x in R_. От предыдущей
команды она отличается инструкцией assuming x in R_. Состоит она из
ключевого слова assuming и инструкции x in R_
-
это инструкция в фор-
мате переменная in множество. Переменной в данном случае является x,
а множеством, как отмечалось, является множество действительных чисел,
что стандартно обозначается как R_.
Попытка решить неравенство на множестве действительных чисел приво-
дит к ожидаемому результату. При решении более сложного полиномиаль-
ного неравенства также разумно четко определить область поиска решений
(команда solve(x^3-11*x^2+31*x-21<0,x) assuming x in R_).
Получаем правильное решение для неравенства
32
11
31210
xxx
−+
−
<
,
которое состоит в объединении интервалов
(,
1
)(
3
,
7
)
x∈−∞∪
.
Решение дифференциальных уравнений
Все это так прямолинейно и перпенди-
кулярно, что мне неприятно.
В. Черномырдин
Дифференциальные уравнения также можно решать функцией solve().
Правда, в этом случае необходимо приложить некоторые усилия – а имен-
но, как-то намекнуть, что решается именно дифференциальное уравнение,
а не какое-то другое. Существует несколько способов добиться этого. Но
самый простой вариант, пожалуй, состоит в том, чтобы в явном виде ука-
зать метод поиска решения – для дифференциальных уравнений это ode
(сокращение от ordinary differential equation, то есть обыкновенное диффе-
ренциальное уравнение). Синтаксис вызова функции solve() имеет такой
вид: ode::solve(). Первым аргументом указывается решаемое уравнение
или заключенное в фигурные скобки множество уравнений (если решается
Глава 9. Символьные вычисления
383
система). Также аргументами передается неизвестная функция (или функ-
ции – заключенные в фигурные скобки). Некоторые примеры решения
дифференциальных уравнений приведены в документе на рис. 9.31.
Рис. 9.31. Решение дифференциальных уравнений
Документ содержит несколько примеров. Первый среди них – решение
дифференциального уравнения
2
() ()0
yx wyx
′′
+=
. Общее решение этого
уравнения, как известно, представляет собой линейную комбинацию сину-
са и косинуса:
12
() cos( )
sin( )
yxC
wxC
wx
=+. Здесь через 1
Cи2
C пред-
ставлены произвольные константы интегрирования, которые определяют-
ся из начальных или граничных условий. Если воспользоваться командой
ode::solve(y''(x)+w^2*y(x)=0,y(x)), то фактически это решение
и получим, правда, записанное в несколько ином виде – через комплексные
экспоненты, то есть как
12
() exp( )
exp( )
yxC
iwx C
iwx
=+
−
.
На заметку
Здесь имеет смысл напомнить формулу Эйлера exp( ) cos( )
sin( )
it
tit
=+.
Далее командой ode::solve({y''(x)+25*y(x)=0,y(0)=3,y'(0)=2},
y(x)) решаем задачу Коши: уравнение
() 25() 0
yx yx
′′
+=
и начальные
условия (0) 3
y=
и(0)2
y′
=
.
Результат получаем точный и достаточно
компактный.
Самоучитель Matlab
384
На заметку
Уравнение и начальные условия при передаче аргументом функции solve()
заключаются в фигурные скобки.
По тому же принципу действуем, решая задачу Коши для системы диф-
ференциальных
уравнений
() 3() ()
xt
xt yt
′
=−
,
() 2() ()
ytxtyt
′
=+
с начальными условиями (0) 1
x
=
и(0)2
y=
.
Задача имеет решение
( ) exp(2 )(cos( ) sin( ))
xt
t
t
t
=−
и () 2exp(2)cos()
yt
tt
=
.
Соответствующая
команда выглядит как ode::solve({x'(t)=3*x(t)-y(t),y'(t)=2*x
(t)+y(t),x(0)=1,y(0)=2},{x(t),y(t)}).
На заметку
В случае необходимости результат решения дифференциального уравнения
или системы уравнений можно упрощать с помощью функции simplify()
или Simplify().
Задача с граничными условиями решается так же, как задача с начальными
значениями, только вместо значения функции и ее производных в начальных
точках задаются значения функции (и ее производных) в граничных точ-
ках. В качестве примера можно привести команду ode::solve({y''(x)+
9*y(x)=0,y(0)=1,y'(1)=0},y(x)). С помощью этой команды ре-
шается уравнение
()9()0
yx yx
′′
+=
с граничными условиями (0) 1
y=
и(1)0
y′
=
. В результате найдено решение дифференциального уравнения,
удовлетворяющее обоим граничным условиям.
Элементы программирования
Вопросы надо ставить уместно и своевре-
менно.
К/ф "Чародеи"
В среде MuPAD можно составлять программные коды, в которых вычисле-
ния выполняются в символьном виде. Здесь мы кратко рассмотрим основ-
ные управляющие инструкции, которые при этом допускается использо-
вать.
В MuPAD используется несколько базовых операторов. Для создания точек
ветвления в программных кодах используется условный оператор if. Син-
таксис его вызова следующий:
if условие then
команды
else
команды
end_if
Глава 9. Символьные вычисления
385
После ключевого слова if указывается условие, которое проверяется и в за-
висимости от истинности или ложности которого выполняется тот или иной
блок команд. В частности, если условие истинно, выполняются команды,
указанные после ключевого слова then. Если условие ложно, выполняются
команды, указанные после ключевого слова else. Заканчивается условный
оператор инструкцией end_if.
На заметку
Блок с инструкцией else не является обязательным. Если этот блок отсутству-
ет, то условный оператор обрабатывается так: при истинном условии выполня-
ются команды после ключевого слова then. Если условие ложно, управление
передается следующему оператору, после условного.
В документе на рис. 9.32 представлен код функции, в которой использован
условный оператор.
Рис. 9.32. Использование условного оператора при определении функции
Самоучитель Matlab
386
Для объявления функции использован следующий программный код:
f:=x->if x<0 then x^2*exp(x)
else sin(2*PI*x)^4*exp(-x^2)
end_if
Всоответствии сэтимкодомопределяетсякусочно-непрерывнаяфункция,ко-
торая при отрицательных аргументах принимает значение
2
() exp()
fxxx
=
и при неотрицательных аргументах равна
42
() sin(2 ) exp()
fx
x
x
π
=−
. Для
большей наглядности там же приведен график описанной функции. График
построен с помощью команды plot(f,x=-7..2). Здесь стоит обратить
внимание, что первым аргументом указано только имя функции (без аргу-
мента). Это необходимо, поскольку в противном случае, если указать ар-
гумент, график построен не будет в силу невозможности обработать в сим-
вольном виде условие, проверяемое в условном операторе. В том формате
вызова, который использован, оператор (имя функции), указанный первым
аргументом функции plot(), действует на диапазон изменения перемен-
ной, указанной вторым аргументом функции plot().
Если проверяется несколько условий, используют вложенные условные
операторы. Полезными могут стать и логические операторы, с помощью ко-
торых проверяются сложные условия.
На заметку
В MuPAD используются следующие логические операторы. Логическое и – опе-
ратор and, логическое или – оператор or, логическое исключающее или – опе-
ратор xor, логическое отрицание – оператор not, логическая импликация –
оператор ==> и логическое тождество – оператор <=>. Результатом выражения
A and B является значение TRUE, если оба операнда A и B равны TRUE. Если
хотя бы один из операндов равен FALSE, результатом выражения является
FALSE. Результатом выражения A or B является значение TRUE, если хотя
бы один из операндов равен TRUE. Если оба операнда равны FALSE, значени-
ем выражения будет FALSE. Значение выражения A xor B равно TRUE, если
один и только один из операндов равен TRUE (другой, соответственно, равен
FALSE). Если оба операнда равны TRUE или оба равны FALSE, значением вы-
ражения A xor B будет FALSE. Выражение not A равняется TRUE, если
операнд A равен FALSE. Если значение операнда A равно TRUE, результатом
выражения является значение FALSE. Значение выражения A ==> B опреде-
ляется как результат вычисления выражения (not A) or B, то есть резуль-
татом будет FALSE, если первый операнд равен TRUE, а второй операнд равен
FALSE. Во всех прочих случаях результатом будет TRUE. Выражение A <=> B
является эквивалентом выражения (A ==> B) and (B ==> A). Если про-
ще, то результат выражения A <=> B равен TRUE при одинаковых значениях
операндов и равен FALSE при разных значениях операндов.
Кроме того, для создания логических выражений часто используют операторы
сравнения: равно (=), не равно (<>), меньше (<), больше (>), меньше или равно
(<=), больше или равно (>=).
Глава 9. Символьные вычисления
387
Еще один пример объявления кусочно-непрерывной функции приведен в
документе на рис. 9.33.
Рис. 9.33. Еще одна кусочно-непрерывная функция
Для определения функции использован следующий программный код:
f:=x->if x<0 or x>4 then
cos(2*PI*x)^2
else if x<1 then
1-x^2
else if x<3 then
sin(2*PI*x)
else x-3
end_if
end_if
end_if
В данном случае функция состоит из нескольких фрагментов. Для значе-
ний аргумента функции
0
x<и
4
x > соответствующая функциональная
зависимость имеет вид
2
() cos(2 )
fx
x
π
=
.
Для значений аргумента в диа-
Самоучитель Matlab
388
пазоне 01
x
≤<зависимость имеет вид
2
()1
fx
x
=−
. Для значений ар-
гумента 13
x
≤< использована зависимость () sin(2 )
fx
x
π
=
.
Наконец,
в случае, если аргумент попадает в диапазон значений 34
x
≤≤, значение
функции вычисляется по формуле ()
4
fxx
=−
.
Весь этот нехитрый ал-
горитм реализован через систему вложенных условных операторов. Соста-
вить представление о том, как выглядит вся функциональная зависимость,
можно по документу на рис. 9.34.
Рис. 9.34. График кусочно-непрерывной функции
Тот же программный код можно реализовать несколько проще (с точки
зрения синтаксиса). В MuPAD во вложенных условных операторах вместо
конструкции else if можно использовать одно ключевое слово elif.
При этом соответствующий блок инструкцией end_if заканчивать не нуж-
но. Другими словами, вместо синтаксической конструкции
if условие then
команды
else if условие then
команды
else if условие then
команды
else команды
end_if
end_if
end_if
Глава 9. Символьные вычисления
389
используется конструкция вида
if условие then команды
elif условие then команды
elif условие then команды
else команды
end_if
Какая из них лучше в плане читабельности, решать читателю. Что касается
нашей функции, то ее код мог бы выглядеть так (для удобства имя функции
заменено на f2):
f2:=x->if x<0 or x>4 then cos(2*PI*x)^2
elif x<1 then 1-x^2
elif x<3 then sin(2*PI*x)
else x-3
end_if
При этом результат выполнения команды определения функции факти-
чески такой же, как и при использовании "неупрощенного" синтаксиса
(рис. 9.35).
Рис. 9.35. Еще один способ определения кусочно-непрерывной функции
Желающие могут проверить, что это та же самая функция, что рассматри-
валась выше.
Самоучитель Matlab
390
Еще один способ проверки нескольких условий подразумевает использова-
ние оператора выбора case. В этом случае некоторое выражение проверя-
ется на предмет совпадения с одним из возможных значений и в зависимо-
сти от того, есть совпадение или нет, выполняются определенные команды.
Синтаксис вызова оператора такой:
case выражение
of значение_1 do
команды_1
of значение_2 do
команды_2
...
otherwise
команды
end_case
После ключевого слова case указывается проверяемое выражение. Далее
идут блоки вида of значение do. Значение выражения, указанного по-
сле ключевого слова case, последовательно сравнивается со значениями
в блоках of значение do до первого совпадения. Если совпадение найдено,
выполняются все команды, начиная с соответствующего блока и до конца
оператора case (инструкция end_case).
На заметку
Чтобы досрочно выйти из оператора выбора case, используют инструкцию
break.
Необязательный блок с ключевым словом otherwise предназначен для
случая, если при проверке выражения не найдено совпадений. Ниже приве-
ден пример использования оператора выбора case для объявления функ-
ции, которая выводит текстовое сообщение в зависимости от переданного
ей числового аргумента.
GetColor:=x->
case x
of1do
print(Unquoted,"1 - означает КРАСНЫЙ");
break
of2do
print(Unquoted,"2 - означает ЖЕЛТЫЙ");
break
of3do
print(Unquoted,"3 - означает ЗЕЛЕНЫЙ");
break
otherwise
print(NoNL,x);
Глава 9. Символьные вычисления
391
print(Unquoted," - не знаю такого цвета")
end_case
У функции GetColor() один аргумент – предполагается, что он число-
вой. Основу кода функции составляет оператор выбора case, в котором про-
веряется значение аргумента функции. Если аргумент равен 1, командой
print(Unquoted,"1
-
означает КРАСНЫЙ") выводится сообщение
1 – означает КРАСНЫЙ. Первым аргументом функции print() пере-
дается инструкция Unquoted, которая означает, что при отображении со-
общения в области вывода его не нужно заключать в двойные кавычки. Что-
бы после вывода сообщения работа оператора выбора завершалась, после
команды с функцией print() указана инструкция break.
На заметку
Последовательность команд в MuPAD разделяется точкой с запятой (то есть ;).
Для значений аргумента функции 2 и 3 также предусмотрены свои сооб-
щения. Каждый из соответствующих блоков заканчивается инструкцией
break – в силу той же причины, что и для первого блока. Блок otherwise
выполняется, если не найдено ни одно совпадение. В этом случае коман-
дой print(NoNL,x) выводится значение аргумента, переданного функ-
ции GetColor() при вызове. Инструкция NoNL в аргументах функции
print() означает, что после вывода соответствующего сообщения переход
к новой строке не выполняется.
На заметку
Ключевое слово NoNL является аббревиатурой от No New Line (означает нет но-
вой строки).
Следующей командой print(Unquoted," – не знаю такого цве-
та") к выведенному числовому значению (мы предполагаем, что числово-
му) добавляется текстовое сообщение.
На заметку
Поскольку блоком otherwise оператор выбора завершается, нет необходи-
мости указывать в конце этого блока инструкцию break.
На рис. 9.36 показано рабочее окно среды MuPAD с кодом функции
GetColor().
Примеры вызова функции GetColor() с разными числовыми аргумен-
тами (в диапазоне натуральных значений от 1 до 4) представлены на
рис. 9.37.
Самоучитель Matlab
392
Рис. 9.36. Программный код функции с оператором выбора case
Рис. 9.37. Результат вызова функции GetColor()
Глава 9. Символьные вычисления
393
Еще одна функция, в которой использован оператор выбора case, пред-
ставлена в документе на рис. 9.38.
Рис. 9.38. В функции TestNumber() использован оператор выбора case
Программный код этой функции приведен ниже:
TestNumber:=x->
case x
of1do
of2do
of3do
of5do
of8do
print(Unquoted,"Это число Фибоначчи!");
break
of6do
Самоучитель Matlab
394
print(Unquoted,"Совершенное число: 6=1+2+3 и 6=1*2*3");
break
otherwise
print(Unquoted,"Ничего интересного!")
end_case
Особенность этого кода состоит в том, что он содержит пустые блоки of-
do – то есть блоки, которые не содержат команд для выполнения. Такой
подход используется, если одни и те же действия нужно выполнять для
нескольких значений проверяемого выражения. Что касается функции
TestNumber(), то у нее один аргумент, который проверяется на предмет
принадлежности к последовательности Фибоначчи.
На заметку
Последовательность Фибоначчи формируется так. Первые два числа последо-
вательности равны 1, а каждое следующее равно сумме двух предыдущих. Та-
ким образом, получаем числа 1, 1, 2, 3, 5, 8, 13, 21 и так далее.
Для нас интерес представляют числа в пределах первого десятка. В этом
диапазоне к последовательности Фибоначчи имеют отношение числа 1, 2,
3, 5 и 8. Именно эти значения проверяются в начальных of-do блоках опе-
ратора выбора. Все эти блоки, кроме блока, соответствующего значению 8,
пустые – то есть не содержат команд для выполнения. Поэтому если име-
ет место совпадение в одном из таких пустых блоков, сразу выполняются
команды первого непустого блока – в данном случае блока для значения
аргумента 8. Благодаря этому для значений 1, 2, 3, 5 и 8 аргумента функции
TestNumber() выполняются одни и те же команды. А именно командой
print(Unquoted,"Это число Фибоначчи!") выводится сообщение
Это число Фибоначчи!, а затем благодаря инструкции break работа
оператора выбора (а с ним и все функции) завершается.
Отдельно обрабатывается значение аргумента 6. Число 6 – так на-
зываемое совершенное. Совершенные числа имеют особенность –
он равны сумме своих делителей (чисел, на которые делится чис-
ло). Делителями числа 6 являются числа 1, 2 и 3. Сумма этих чисел
также равна 6. Если аргумент функции TestNumber() равен 6, командой
print(Unquoted,"Совершенное число: 6=1+2+3 и 6=1*2*3") вы-
водится сообщение о том, что число 6 - совершенное. Во всех прочих случа-
ях появляется сообщение Ничего интересного!. На рис. 9.39 приведен
фрагмент документа с примерами вызова функции TestNumber().
Стоит обратить внимание на то, как обрабатывается символьный аргумент
функции (то есть аргумент, которому не присвоено числовое значение).
В этом случае в силу очевидных причин реализуется otherwise-блок опе-
ратора выбора.
Глава 9. Символьные вычисления
395
Помимо условных операторов, важное место в программировании занима-
ют операторы цикла, которые позволяют многократное повторение опреде-
ленных действий. В MuPAD используются операторы цикла for, while
и repeat. Рассмотрим каждый из этих операторов.
Синтаксис вызова оператора цикла for следующий:
for переменная from значение_1 to значение_2 step значение_3 do
команды
end_for
Выполняется оператор цикла for следующим образом. Индексная пере-
менная, указанная после ключевого слова for, последовательно пробегает
значения от значение_1 (указано после ключевого слова from) до значения
(не превышая значения) значение_2 (указано после ключевого слова to)
с приращением на каждом шаге, равном значение_3 (указано после ключе-
вого слова step). При каждом фиксированном значении индексной пере-
менной выполняются команды, размещенные после ключевого слова do
и до окончания тела оператора цикла (инструкция end_for).
На заметку
Шаг приращения (инструкция step) указывать не обязательно. В этом случае
индексная переменная изменяется на единицу. Если изменение индексной
переменной в процессе выполнения оператора цикла уменьшается, вместо ин-
струкции to используют инструкцию downto.
Рис. 9.39. Результат вызова функции TestNumber()
Самоучитель Matlab
396
Рассмотрим следующий программный код, в котором использован опера-
тор цикла for при определении функции, которой вычисляются числа Фи-
боначчи:
Fib:=n->(
a:=1;
b:=1;
forkfrom3tondo
b:=a+b;
a:=b-a;
end_for;
b)
У функции Fib() один аргумент, который определяет номер числа в по-
следовательности Фибоначчи. Поскольку основу тела функции составляют
несколько команд, все они объединены в один блок, для чего эти команды
заключаются в круглые скобки. Первыми двумя командами переменным
a и b присваиваются единичные значения. Эти переменные "помнят" те-
кущие значения предпоследнего и последнего чисел в последовательности.
После этого запускается оператор цикла. Его индексная переменная пробе-
гает значения от 3 (первое и второе числа уже "вычислены" – это начальные
значения переменных a и b) до n (аргумент функции Fib()). В теле опе-
ратора цикла выполняются две команды. Командой b:=a+b вычисляется
новое значение для числа в последовательности. После этого в переменную
a необходимо записать то значение, что было записано (до выполнения
команды b:=a+b) в переменной b. Сделать это можно с помощью коман-
ды a:=b-a. Таким образом, после выполнения одной итерации в операторе
цикла вычисляется новое число в последовательности и, как и на началь-
ном этапе, в переменной a записано предпоследнее (на данный момент)
значение в последовательности, а в переменной b – последнее. После вы-
полнения оператора цикла в переменную b будет записано число в последо-
вательности с порядковым номером n. Чтобы переменная b возвращалась
как результат, она указывается последней командой в последовательности
команд, определяющих код функции Fib(). Документ с кодом этой функ-
ции представлен на рис. 9.40.
Пример использования этой функции приведен в документе на рис. 9.41.
Здесь тоже использован оператор цикла for. В рамках этого оператора ин-
дексная переменная пробегает значения от 1 до 20. При фиксированном
значении индексной переменной с помощью функции Fib() вычисляет-
ся число с соответствующим индексом в последовательности Фибоначчи,
и вычисленные числа отображаются в одной строке.
Глава 9. Символьные вычисления
397
На заметку
Для того чтобы между числами добавлялся пробел, помимо команды
print(NoNL,Fib(i)) использована еще и команда print(NoNL," ").
В результате в строке отображаются первые двадцать чисел последователь-
ности Фибоначчи.
На заметку
Существует еще одна популярная форма оператора цикла, которая использует-
ся при переборе значений из некоторого множества. Синтаксис вызова опера-
тора цикла в этом случае имеет такой вид:
Рис. 9.40. Документ с кодом функции Fib()
Рис. 9.41. Использование функции Fib()
Самоучитель Matlab
398
for переменная in множество_значений do
команды
end_for
В этом случае последовательно перебирается множество значений. На каждом
итерационном шаге переменная принимает очередное значение из множества
значений.
Синтаксис вызова оператора while имеет следующий вид:
while условие do
команды
end_while
Оператор выполняется следующим образом. Сначала проверяется условие.
Если условие истинное, выполняются команды в теле оператора while. За-
тем снова проверяется условие. Если условие истинно, выполняются коман-
ды, и так далее. В документе на рис. 9.42 приведен пример кода, в котором
вычисляются числа Фибоначчи, но в отличие от предыдущего случая здесь
использован оператор while.
Рис. 9.42. Вычисление чисел Фибоначчи с помощью оператора while
Нами использовался следующий код:
a:=1:
b:=1:
i:=2:
print(NoNL,a);
Глава 9. Символьные вычисления
399
print(NoNL," ");
print(NoNL,b);
while i<20 do
b:=a+b:
a:=b-a:
print(NoNL," ");
print(NoNL,b);
i:=i+1:
end_while:
Переменные a и b, в которые будут записываться числа Фибоначчи, а также
индексная переменная i, получают свои начальные единичные значения.
Текущие единичные значения переменных a и b отображаются в области
вывода. После этого запускается оператор цикла while, в котором и про-
исходят все основные события. В операторе проверяется условие i<20.
В теле оператора цикла while командами b:=a+b и a:=b-a вычисляется
очередное число в последовательности Фибоначчи. Далее в области вывода
отображается вновь вычисленное число, после чего командой i:=i+1 вы-
числяется новое итерационное значение.
На заметку
Начальное значение индексной переменной i равно 2. На момент присваива-
ния значения переменной i известно два числа (единичные значения перемен-
ных a и b) из последовательности. В операторе цикла после вычисления нового
числа последовательности значение переменной i увеличивается на единицу.
Таким образом, перед проверкой условия i<20 в операторе while значение
переменной i указывает количество уже вычисленных чисел в последователь-
ности. Поэтому вычисления продолжаются до тех пор, пока количество вычис-
ленных чисел меньше двадцати. Другими словами, будет вычислено двадцать
чисел из последовательности Фибоначчи.
На рис. 9.43 показан документ, в котором та же задача решается с помощью
оператора repeat.
По сравнению с предыдущим случаем изменения кода минимальные:
a:=1:
b:=1:
i:=2:
print(NoNL,a);
print(NoNL," ");
print(NoNL,b);
repeat
b:=a+b:
a:=b-a:
print(NoNL," ");
print(NoNL,b);
Самоучитель Matlab
400
i:=i+1:
until i>=20 end_repeat:
Общий синтаксис вызова оператора repeat напоминает синтаксис вызова
оператора while, но условие проверяется после выполнения команд тела
цикла, а истинность условия означает завершение оператора:
repeat
команды
until условие end_repeat
Выполняется оператор так: сначала выполняются команды, затем проверя-
ется условие. Чтобы оператор repeat продолжил работу, необходимо, что-
бы условие было ложным. Если условие истинно, работа оператора repeat
заканчивается.
Помимо блоков команд, содержащих условные операторы и операторы
цикла, в документах MuPAD можно создавать процедуры – именованные
блоки программного кода, которые можно вызывать по имени. Синтаксис
объявления процедуры такой:
имя_процедуры:=proc(аргументы)
local локальные_переменные;
begin
команды
end_proc
Рис. 9 .43. Вычисление чисел Фибоначчи с помощью оператора repeat
Глава 9. Символьные вычисления
401
После имени процедуры через оператор присваивания указывается ключе-
вое слово proc, после которого в круглых скобках перечисляются аргумен-
ты процедуры. Если в процедуре используются локальные переменные, они
перечисляются после ключевого слова local. Эта часть кода не является
обязательной. Тело кода процедуры размещается между ключевыми слова-
ми begin и end_proc.
На заметку
Переменные могут быть локальными и глобальными. Локальные переменные
доступны только в пределах кода процедуры в том смысле, что любые измене-
ния, вносимые в такие переменные в теле процедуры, отменяются после выпол-
нения процедуры. По умолчанию все переменные (не объявленные в разделе
local) полагаются глобальными. При совпадении имен глобальной и локаль-
ной переменных приоритет остается за локальной переменной.
Если процедура возвращает результат, то для этого обычно используют ин-
струкцию return(). Аргументом указывается возвращаемое значение. Но
в принципе можно обойтись и без этой инструкции. В этом случае возвра-
щается последнее вычисленное значение в процедуре. Пример процедуры
для вычисления чисел Фибоначчи приведен ниже:
FibNums:=proc(n)
local i,a,b;
begin
a:=1:
b:=1:
forifrom3tondo
b:=a+b:
a:=b-a:
end_for:
return(b);
end_proc:
Использование этой процедуры в рабочем документе MuPAD показано на
рис. 9.44.
Еще один пример процедуры (тоже для вычисления чисел Фибоначчи) по-
казан в документе на рис. 9.45.
В этом случае использована рекурсия – вызов процедуры в теле этой же
процедуры. Код процедуры следующий:
FNums:=proc(n)
begin
if n=1 or n=2 then return(1):
else return(FNums(n-1)+FNums(n-2)):
end_if:
end_proc
Самоучитель Matlab
402
Рис. 9 .44 . Документ с описанием процедуры
Рис. 9.45. Процедура с рекурсией
Глава 9. Символьные вычисления
403
Здесь реализован такой алгоритм. Проверяется значение аргумента про-
цедуры. Если значение аргумента равно 1 или 2, то в качестве значения
процедуры возвращается 1. В противном случае в качестве результата воз-
вращается выражение, в котором значение вычисляется путем вызова опре-
деляемой процедуры, но уже с другими аргументами.
На заметку
В качестве завершающей инструкции вместо ключевых слов end_for, end_
while, end_repeat, end_if, end_case и end_proc в соответствующих
местах можно использовать ключевое слово end.
Редактор кодов
Странный способ украшать дом моно-
граммой королевы.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Кровавая надпись"
При работе со средой MuPAD существует возможность создавать и сохра-
нять отдельными файлами программные коды, а затем вызывать их в ра-
бочем документе в случае необходимости. Коды создаются в специальном
редакторе, который может быть запущен из окна заставки среды MuPAD –
для этого следует выбрать команду New Editor (см. рис. 9.46). Можно от-
крыть окно редактора кодов, воспользовавшись командой File ► New Editor
(рис. 9.46).
Рис. 9.46. Запуск редактора кодов
В результате открывается окно редактора кодов, представленное на рис. 9.47.
Самоучитель Matlab
404
Рис. 9.47. Окно редактора кодов
В окне вводится код и сохраняется файл (команда File ► Save). Напри-
мер, вводим код и сохраняем в файл с именем MyCode.mu, как показано на
рис. 9.48.
Рис. 9.48. Окно редактора кодов с командами после сохранения
В данном случае файл содержит такой код:
Глава 9. Символьные вычисления
405
SEED:=123;
rnd:=random(-10..10);
L:=[];
forkfrom1to10do
L:=L.[rnd()];
end;
ones:=random(2);
n:=5;
A:=matrix(n,n,[ones()$i=1..n*n])
Этим кодом создается список L из десяти целых случайных чисел, а также
квадратная матрица A, заполненная случайным образом нулями и единица-
ми. Важное место в этом коде занимает процесс генерирования случайных
чисел. Первой командой SEED:=123 выполняется инициализация генера-
тора случайных чисел. Это позволяет каждый раз при выполнении кода ге-
нерировать одну и ту же "случайную" последовательность. Команда не обя-
зательная (ее можно было не использовать), а нужна скорее для удобства.
На заметку
Пикантность ситуации состоит в том, что при генерировании случайных чисел
на самом деле генерируются неслучайные числа. Это так называемые псевдос-
лучайные числа. Для генерирования последовательности таких чисел необхо-
димо задать некое "затравочное" число, которое генератор случайных чисел
использует в расчетах при вычислении первого псевдослучайного числа. Обыч-
но при запуске генератора случайных чисел в качестве такого "затравочного"
числа используется, например, системное время. Это создает иллюзию случай-
ности. Но можно "затравочное" значение задать и в явном виде. Если каждый
раз использовать одно и то же значение, будет генерироваться одна и та же по-
следовательность чисел.
Командой rnd:=random(-10..10) определяется функция rnd() для ге-
нерирования случайных чисел. При определении функции rnd() в свою
очередь использована встроенная функция random(), которой генериру-
ются целые случайные числа. Если аргументом функции random() указать
диапазон, то генерироваться будут случайные целые числа, равномерно
распределенные в этом диапазоне (включая граничные точки диапазона).
Таким образом, функцией rnd() будут генерироваться числа в диапазоне
от -10 до 10.
Командой L:=[] создается пустой список L. После этого с помощью опе-
ратора цикла (индексная переменная k пробегает значения от 1 до 10)
этот список заполняется случайными числами. В теле цикла использована
команда L:=L.[rnd()]. Она буквально означает добавление в конец спи-
ска L элемента, который вычисляется инструкцией rnd(), то есть случай-
ного числа в диапазоне от -10 до 10.
Самоучитель Matlab
406
На заметку
Для добавления в конец списка нового элемента может использоваться функ-
ция append() или так называемый точечный синтаксис. Здесь использован
второй способ. Инструкцией вида список.[элемент] возвращается список,
который получается объединением исходного списка и элемента, указанного
после точки в квадратных скобках. Поэтому команда L:=L.[rnd()], напри-
мер, означает, что переменной L в качестве значения присваивается список,
который получается добавлением в конец списка – текущего значения L эле-
мента, вычисляемого как rnd() (случайное число).
После выполнения оператора цикла список L заполнен десятью случай-
ными числами. На следующем этапе создаем случайную матрицу из нулей
и единиц. Для этого командой ones:=random(2) создаем функцию, кото-
рая генерирует целое случайное число в диапазоне от 0 до 1 включительно,
то есть с равной вероятностью генерирует нули и единицы.
На заметку
Если функции random() передан один аргумент (например, m), то это все
равно, как если бы был указан диапазон 0..m-1. Другими словами, будут ге-
нерироваться неотрицательные целые числа, меньшие аргумента функции
random().
Командой n:=5 инициализируется переменная n, а затем эта переменная
используется в команде A:=matrix(n,n,[ones()$i=1..n*n]). В ре-
зультате создается упомянутая выше матрица из нулей и единиц. Матрица
записывается в переменную A. Формируется матрица с помощью встроен-
ной функции matrix(). Первые два аргумента функции matrix() опре-
деляют размер матрицы (в данном случае матрица состоит из n строк и n
столбцов). Третий аргумент – список элементов матрицы. Матрица эле-
ментов заполняется построчно. Список элементов создается инструкцией
[ones()$i=1..n*n]. Это заключенная в квадратные скобки последова-
тельность. Последовательность, в свою очередь, создается с помощью опе-
ратора создания последовательности $. Слева от оператора $ указывается
общее выражение, которое используется для вычисления элементов после-
довательности. Справа от оператора $ указывается индексная переменная
(в общем случае она может использоваться в выражении слева от операто-
ра $) и диапазон изменения индексной переменной. Поскольку в квадрат-
ной матрице размера n всего элементов n*n, то индексная переменная про-
бегает значения от 1 до n*n.
Для выполнения кода, записанного в файле MyCode.mu, в рабочем до-
кументе среды MuPAD выбираем команду Notebook ► Read Commands
(рис. 9.49).
Глава 9. Символьные вычисления
407
В открывшемся диалоговом окне необходимо выбрать соответствующий
файл для выполнения кода (в данном случае это файл MyCode.mu). Хотя
внешних проявлений этого чудесного процесса практически не будет, эф-
фект все же есть. Он состоит в том, что в рабочем документе можно исполь-
зовать все те переменные, что содержатся в коде файла MyCode.mu и с ко-
торыми выполнялись вычисления.
На заметку
Поскольку среда MuPAD предназначена для символьных расчетов, то в рабочем
документе можно использовать любые переменные, названия которых разре-
шены синтаксическими правилами командного языка. Вопрос только в том, ка-
кие значения будут иметь эти переменные. После выполнения командного кода
из файла MyCode.mu переменные, которые есть в этом коде, будут иметь зна-
чения, определяемые в коде.
На рис. 9.50 показан рабочий документ среды MuPAD, в котором после вы-
полнения кода из файла MyCode.mu проводятся вычисления с переменны-
ми, использованными в этом коде.
В частности, если в пустом рабочем документе выполнить команду L (имя
списка из случайных чисел), получим результат: список из десяти случай-
ных чисел. Аналогичная ситуация и для матрицы A – хотя непосредственно
в рабочем документе MuPAD матрица не определялась, у соответствующей
переменной есть значение. Легко проверить, что имеют числовые значения
индексные переменные k и i, использовавшиеся в операторе цикла и коман-
де с оператором создания последовательности. Доступны также созданные
в коде функции. Например, командой rnd()$i=1..n создается список из
пяти (значение переменной n) случайных чисел в диапазоне от -10 до 10.
Рис. 9.49. Выполнение кода из файла
Самоучитель Matlab
408
На заметку
Мы кратко уже обсуждали методы работы с последовательностями и списками.
Последовательность представляет собой набор объектов (разного типа), раз-
деленных запятыми. Кроме явного перечисления элементов последователь-
ности, существует несколько способов ее создания. Обычно прибегают к по-
мощи специального оператора создания последовательности $ или функции
_ seqgen() (точнее, это функциональная форма оператора $). Для создания
последовательности в "автоматическом" режиме следует указать общее выра-
жение для генерирования элементов последовательности, а также индексную
переменную и множество ее значений. Ели используется функция _seqgen(),
то ее аргументы указываются именно так: выражение (зависящее, как правило,
от индексной переменной), индексная переменная и диапазон ее изменения
(или список значений). Если последовательность создается с помощью опера-
тора $, то выражение для элементов последовательности указывается слева от
оператора, а все остальное – справа.
Список представляет собой упорядоченный набор данных. Технически от по-
следовательности список отличается тем, что его элементы все вместе за-
ключаются в квадратные скобки. Другими словами, список – это заключенная
в квадратные скобки последовательность. Что касается сути вопроса, то главное
Рис. 9.50. Рабочее окно с командами после выполнения кода файла
Глава 9. Символьные вычисления
409
отличие списка от последовательности в том, что вложенные списки создавать
можно, а вложенные последовательности – нет. Другими словами, элементом
списка может быть другой список, а при попытке вставить одну последователь-
ность в качестве элемента в другую последовательность эти последовательно-
сти просто объединяются.
Множество представляет собой набор элементов, для которого не имеет значе-
ния порядок следования элементов во множестве. Для множества важно, вхо-
дит элемент в него или нет. Чтобы получить множество, достаточно заключить
последовательность в фигурные скобки.
Кроме этого, существуют еще таблицы, матрицы и массивы. Эти структуры соз-
даются соответственно с помощью функций table(), matrix() и array().
Отличие между матрицей и объектом состоит в том, что у матрицы индексы
целочисленные, а у таблицы это могут быть произвольные величины. Одно из
отличий матрицы и массива (помимо способа хранения данных) состоит в том,
что матрица может быть одномерной (вектор) или двумерной, а размерность
массива может быть и больше.
Создание анимации
-
Хорошо, допустим, Земля вращается
вокруг Солнца.
-
То есть как, "допустим"?
К/ф "Приключения Шерлока Холмса
и доктора Ватсона. Знакомство"
Ранее мы уже познакомились с функцией plot(), которая позволяет соз-
давать двумерные и трехмерные графики. Важно учесть еще два важных
обстоятельства: во-первых, с помощью функции plot() можно создавать
анимацию и, во-вторых, это далеко не единственная функция для создания
графики и анимации. Начнем с создания анимации с помощью функции
plot(). Обычно так создаются простые анимационные сюжеты.
Общая идея состоит в том, что при создании анимации с помощью функ-
ции plot() добавляется еще один дополнительный аргумент в формате
переменная=диапазон. Эта переменная играет роль времени. Пример созда-
ния двумерной анимации представлен в документе на рис. 9.51.
Здесь мы использовали команду f:=x->exp(-x^2/2)/sqrt(2*PI) для
определения функциональной зависимости вида
()
2
() exp
22
fx
x
π
=−
(Гауссово распределение). Функцию
(,)(()())2
Fxtfxtfxt
=+
+−
определяем командой F:=(x,t)->(f(x+t)+f(x-t))/2. Именно на осно-
ве этой функции создаем анимацию. Первая переменная x в этой функции
соответствует пространственной переменной, а вторая переменная t соот-
ветствует времени. Функция (,)
Fxt описывает две разбегающиеся в разные
Самоучитель Matlab
410
стороны волны Гауссового профиля. Такой результат может быть получен
при решении задачи о колебаниях бесконечной струны с начальным рас-
пределением, которое описывается функцией ()
fx.
Для создания анимации используем команду plot(F(x,t),x=-15..15,
t=0..10). В отличие от команды создания обычной графики здесь в ар-
гументах функции plot() указан еще интервал t=0..10 изменения вре-
менной переменной t. При выполнении этой команды внешне впечатление
такое, что создан график функции. Но если этот график выделить (щелкнув
в области графика мышкой), получим результат, как на рис. 9.52.
Обратить стоит внимание на панели, которые появляются в окне редактора
среды MuPAD сразу под панелью меню. Нас в первую очередь интересует
панель с ползунком и кнопками управления анимацией. По умолчанию эта
панель отображается справа. Для запуска анимации необходимо щелкнуть
кнопку с изображением стрелки (в виде треугольника), как показано на
Рис. 9.51. Создание двумерной анимации с помощью функции plot()
Глава 9. Символьные вычисления
411
рис. 9.52. В результате анимация запускается, а пиктограмма кнопки с треу-
гольника меняется на квадрат. Повторный щелчок на этой кнопке приведет
к остановке анимации. Некоторые анимационные кадры (по умолчанию
всего их 50) представлены в табл. 9.1.
Практически так же просто создается трехмерная анимация. Чтобы картин-
ка была трехмерной, в аргументах функции plot() указываем инструкцию
#3D, а чтобы это была анимация, а не статическое изображение, добавляем
дополнительный аргумент, который определяет диапазон изменения пере-
менной, отождествляющей время. Пример создания трехмерной анимации
приведен на рис. 9.53.
Это фактически расширенный до трехмерного случая предыдущий при-
мер. Анимируются четыре пространственных Гауссовых пика. В начальный
момент все пики находятся в начале системы координат, а затем начинают
"разбегаться" в разные стороны вдоль координатных осей. Некоторые кад-
ры анимации приведены в табл. 9.2.
Как и в предыдущем случае, командой f:=x->exp(-x^2/2)/
sqrt(2*PI) создаем функцию Гауссового типа. После этого коман-
дой F:=(x,y,t)->(f(x-t)+f(x+t))*(f(y-t)+f(y+t))/4 опреде-
ляем базовую функцию, на основе которой будем строить трехмерную
анимацию. Непосредственно анимация создается с помощью команды
plot(F(x,y,t),x=-4..4,y=-4..4,Mesh=[80,80],t=0..2,#3D).
Первым аргументом функции plot() передается функция от трех аргу-
Рис. 9.52. Просмотр анимации
Самоучитель Matlab
412
Табл. 9.1. Кадры двумерной анима
Номер
кадра
Кадр
Номер
кадра
Кадр
1
12
5
16
7
25
8
40
9
50
Глава 9. Символьные вычисления
413
Рис. 9.53. Трехмерная анимация
ментов F(x,y,t). Также указан диапазон изменения пространственных
переменных x и y, а также переменной t, которую отождествляем со време-
нем. Инструкция #3D свидетельствует о том, что создается трехмерный гра-
фик. Все эти аргументы вполне ожидаемы. Несколько неожиданным может
показаться аргумент-опция Mesh=[80,80]. Она определяет количество
узловых точек по каждой из координатных осей, на основе которых строит-
ся график функции (по умолчанию значение опции Mesh равно [50,40]).
Эта опция не является обязательной. Мы ее использовали для того, чтобы
график выглядел достаточно плавным. Если оставить для этой опции на-
стройки по умолчанию, поверхность будет немного "угловатой" – особенно
в районе пика.
Самоучитель Matlab
414
Табл. 9.2. Кадры трехмерной анимации
Номер
кадра
Кадр
Номер
кадра
Кадр
1
19
10
20
13
23
15
28
17
45
Глава 9. Символьные вычисления
415
Несколько замечаний о создании графики
Вместо того чтобы поражать милейшего
доктора Ватсона нашими гениальными фа-
мильными способностями, нужно было про-
сто трезво взглянуть на маркера, который
беседовал со швейцаром.
К/ф "Приключения Шерлока Холмса и
доктора Ватсона. Король шантажа"
В общем, для минимального использования возможностей среды MuPAD
при создании графики и анимации достаточно функции plot(). Тем не ме-
нее, это даже не верхняя часть айсберга от тех возможностей в области гра-
фики и анимации, а намного меньше. Все описать здесь в силу объективных
причин не получится. Выше мы рассмотрели только наиболее общие воз-
можности среды MuPAD в плане создания графики и анимации. Здесь мы
несколько расширим свои познания в этой области. Хотя скорее материал
этого раздела можно рассматривать как напутственные пожелания.
На заметку
Значительная часть возможностей среды MuPAD реализована через библиоте-
ки. Для того чтобы использовать функцию, описанную в той или иной библиоте-
ке, перед именем функции следует еще указать и имя библиотеки. Имя библио-
теки и имя функции разделяются оператором расширения контекста :: (два
двоеточия). Другими словами, если функция описана в библиотеке, то вызывать
функцию следует инструкцией вида библиотека::функция. Исключением явля-
ется стандартная библиотека, функции из которой мы рассматривали до это-
го, и которые вызываются напрямую, без указания имени библиотеки. Обычно
под библиотечными подразумевают те функции, что описаны не в стандартной
библиотеке. Кроме того, библиотечную функцию можно загрузить в глобальное
пространство имен с помощью инструкции вида use(библиотека,функция).
После этого функцию можно вызывать без указания библиотеки. Если из би-
блиотеки загружается несколько функций, они перечисляются через запятую.
Чтобы экспортировать (загрузить в глобальное пространство имен) всю би-
блиотеку, используют инструкцию вида use(библиотека). Значительная часть
графических возможностей среды MuPAD реализована через функции библио-
теки plot. Читателю, который планирует систематически использовать в своей
работе среду MuPAD, имеет смысл обратить внимание на эту библиотеку.
Конечно же, не следует игнорировать опционные параметры, которые по-
зволяют задавать основные свойства создаваемых графических объектов.
Такие дополнительные опционные параметры могут задаваться непосред-
ственно в функции plot(). Есть и другие функции для работы с графи-
кой. Например, среди графических функций стандартной библиотеки
имеется функция plotfunc2d(), предназначенная для создания двумер-
ных графиков функций от одного переменного. Аналогичная ей функция
Самоучитель Matlab
416
plotfunc3d() предназначена для создания трехмерной графики. Приме-
ры вызова этих функций приведены в документе на рис. 9.54 и рис. 9.55.
Рис. 9.54. Создание графики с помощью функции plotfunc2d()
Рис. 9.55 . Создание графики с помощью функции plotfunc3d()
Многие опции для функций plotfunc2d() и plotfunc3d() одинаковы.
Например, опцией GridVisible отображается координатная сетка (значе-
ние опции TRUE), а вспомогательная сетка отображается с помощью опции
SubgridVisible. Опция Header позволяет задать заголовок графика.
Глава 9. Символьные вычисления
417
Тип шрифта для заголовка задается опцией HeaderFont. Существуют так-
же опции для определения цвета кривых (опция Colors), толщины линий
(опция LineWidth), подписей координатных осей (опция AxesTitles),
шрифта для отображения легенды (опция LegendFont), цвета фона и ко-
ординатных осей (опция BackgroundColor и AxesLineColor соответ-
ственно) и многих других.
На заметку
Значения "цветовых" опций могут задаваться в формате RGB::цвет. В качестве
цвета используется одно из ключевых слов (Red, Green, Blue и так далее).
Более полное описание графических возможностей среды MuPAD могло
бы стать темой отдельной книги. Наша книга не об этом. Единственное, что
настоятельно хочется порекомендовать читателю в завершение, – не игно-
рировать уникальные возможности, которые предоставляются пользовате-
лю средой MuPAD, в том числе и в области создания графики и анимации.
418
Приложение А
Файловый ввод/вывод
Во всяком случае, другого у нас нет.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Большие массивы данных нередко приходится считывать с внешних фай-
лов и туда же записывать результат после выполнения нужных расчетов.
Здесь кратко описываются методы и некоторые простые приемы считыва-
ния информации из файла и записи информации в файл, а также ряда дру-
гих операций с файлами.
Существует несколько базовых операций, которые обычно приходится вы-
полнять в процессе работы с файлами. Им соответствует несколько функ-
ций, которые предназначены для выполнения соответствующих действий.
Одно из самых простых – открытие из командного окна файла внешнего
приложения. Открыть внешний документ можно с помощью функции
open(). Аргументом функции указывается полное имя файла, который
открывается. Какое приложение будет использовано для открытия файла,
определяется по его расширению. Например, чтобы открыть файл MyData.
pdf, который находится в каталоге C:\Documents\Data, используем
команду open('C:\Documents\Data\MyData.pdf'). Открываться
файл будет приложением, ассоциированным с pdf-расширением (скорее
всего, это Adobe Acrobat). Для загрузки файла в рабочее пространство при-
ложения Matlab используют функцию load(). Аргументом функции ука-
зывается имя загружаемого файла. Это может быть как mat-файл, так и,
например, txt-файл. Рассмотрим простой пример. На рис. А.1 представлен
текстовый документ, содержащий числовые значения.
Рис. А.1. Текстовый документ с числовыми значениями
Файл MyMatrix.txt содержит числовые значения, формирующие ма-
трицу размерами 3×3. Мы хотим считать числовые значения из этого фай-
ла и записать результат в некоторую переменную в рабочем документе
Matlab. Для этого в командном окне используем команду a=load('C:\
Documents\Data\MyMatrix.txt') (рис. А.2).
Приложение А. Файловый ввод/вывод
419
Рис. А.2 . Результат загрузки файла – переменной присвоено значение
Аргументом функции load() указано полное имя к файлу 'C:\
Documents\Data\MyMatrix.txt'
(предполагается,
что
файл
MyMatrix.txt находится в каталоге C:\Documents\Data). Результат
вызова функции load() присваивается в качестве значения переменной a.
В результате эта переменная получает в качестве значения матрицу, состав-
ленную из числовых значений из файла MyMatrix.txt.
Эксперимент можно продолжить. Для этого новый рабочий документ со-
храняем в качестве рабочего пространства как mat-файл (рис. А.3).
Рис. А.3. Сохранение рабочего документа Matlab
Самоучитель Matlab
420
В документе командами A=[1 2 3;4 5 6;7 8 9] и B=rand(5,3) создается
две матрицы (одна из целых чисел, а вторая – из случайных). С помощью коман-
ды File ► Save Workspace As сохраняем файл рабочего пространства с именем
NewData.mat в каталоге C:\Documents\Data. После этого в командном
окне с помощью команды clear удаляем из рабочего пространства созданные
переменные и затем командой clc очищаем командное окно. Далее командой
load('C:\Documents\Data\NewData.mat') выполняем загрузку файла.
После загрузки файла проверяем значения переменных A и B (рис. А.4).
Рис. А.4 . Результат загрузки mat-файла
Несложно заметить, что переменные определены и имеют те же значения,
которые они получили при создании.
На заметку
При желании можно загрузить не весь файл, а только отдельные переменные,
определенные в этом файле. Например, командой load('C:\Documents\
Data\NewData.mat','B') из файла NewData.mat будет загружена пе-
ременная B.
Полезной в работе может стать функция save(). Эта функция позволя-
ет сохранять данные вычислений в файл непосредственно из командного
окна. Обратимся к примеру в документе на рис. А.5.
В командном окне инструкциями x=0:0.5:10, y=cos(2*pi*x)./(1+x)
и z=exp(-x).*sin(2*pi*x) создаются массивы данных, и затем эти спи-
Приложение А. Файловый ввод/вывод
421
ски в команде res=[x',y',z'] используются для формирования матри-
цы из трех столбцов. Содержимое этой матрицы мы записываем в текстовый
файл. Для этого используется команда save('C:\Documents\Data\Funcs.
txt','res','-ascii'). Первый аргумент функции save() определяет пол-
ное название файла, в который записывается переменная, определяемая вторым
аргументом функции save(). Опция -ascii является индикатором того, ис-
пользуется ли текстовый формат. В результате в файл Funcs.txt будет записа-
но содержимое переменной res. Содержимое этого файла показано на рис. А.6.
Рис. А.6. Содержимое файла Funcs.txt
На заметку
Если файл Funcs.txt не существовал, он будет создан. Если он существовал,
содержимое файла переписывается.
Кроме обработки файла целиком, не менее часто необходимо работать
с фрагментами данных, записанных в файл или которые необходимо туда
Рис. А.5 . Сохранение данных в файл с помощью функции save()
Самоучитель Matlab
422
записать. Для таких задач используют инструкции низкоуровневого досту-
па к файлам.
Для открытия файла и последующей работы с ним предназначена функция
fopen(). Аргументом функции указывается открываемый файл. Опцион-
ные параметры определяют режим открытия файла (то есть то, для чего от-
крывается файл). Назначение некоторых опций кратко описано в табл. А.1.
Табл. А.1. Некоторые опции определения режима открытия файла
Опция
Назначение
'r'
Файл открывается для чтения. Этот режим применяется по умолчанию
'w'
Файл открывается (или создается новый) для записи. Если у файла есть
содержимое, при записи оно удаляется
'a'
Файл открывается (или создается новый) для записи. Новое содержимое
дописывается в конец файла. Старое содержимое не удаляется
'r+' Существующий файл открывается для чтения и записи
'w+'
Открывается существующий файл или создается новый для чтения и за-
писи. Новое содержимое замещает старое
'a+'
Открывается существующий файл (или создается новый) для чтения и за-
писи. Новое содержимое дописывается в конец файла
По умолчанию используется режим работы с бинарными файлами. Для ра-
боты с текстовыми файлами в опции режима добавляется литера t – напри-
мер, 'rt' (открытие текстового файла для чтения) или 'wt+' (открытие
(создание) текстового файла для чтения и записи).
В качестве результата при вызове функции fopen() возвращается указа-
тель на открытый файл. Открываемые файлы нумеруются подряд, начиная
с номера 3. Если файл открыт не был, возвращается значение -1.
На заметку
По умолчанию индексы 0, 1 и 2 имеют стандартные файлы системного ввода
stdin, системного вывода stdout и системный файл потока ошибок stderr
соответственно. Эти файлы доступны автоматически, и открывать их не нужно.
После завершения работы с файлом его следует закрыть с помощью функ-
ции fclose(). Аргументом функции передается указатель на файл (ин-
дикатор файла, который получаем при его открытии). Есть также ряд по-
лезных функций, которые используются при работе с файлом. Среди них
функции fread() и fwrite(), предназначенные соответственно для чте-
ния данных из файла и записи данных в файл. Функция feof() позволяет
определить, достигнут ли конец файла, функция ftell() возвращает в ка-
честве значения текущую позицию указателя (смещение в байтах от начала
файла), функция frewind() переводит указатель в начало файла, а функ-
ция fseek() позволяет перемещать указатель в нужную позицию в файле.
423
Приложение Б
Структуры и ячейки
Чрезвычайно интересно! Поразительную
ерунду сочиняют эти газетчики с утра. До-
ждемся вечерних новостей.
К/ф "Клуб самоубийц, или Приключения
титулованной особы"
Понятие структуры в Matlab близко к тому, что мы подразумеваем под
структурами, например, в С++. Структура представляет собой способ ор-
ганизации разнородных данных. Данные относятся к структуре через поля.
Фактически в структуре объединяются разные переменные, которые яв-
ляются полями структуры. Другими словами, если о каком-то объекте из-
вестно, что по своей типизации он относится к структуре, то, во-первых, об
этом объекте будем говорить, что он является экземпляром структуры и,
во-вторых, у этого объекта есть поля. Значения полей могут быть самыми
разнообразными.
На заметку
Структура представляет собой шаблон, на основе которого создаются экзем-
пляры структуры. В этом смысле можно говорить о структуре как о типе данных.
Но если в С++ перед созданием экземпляров структуры саму структуру
нужно предварительно описать, то в Matlab экземпляр структуры можно
создавать сразу. Существует несколько способов сделать это. Так или иначе,
используется точечный синтаксис – после имени экземпляра структуры че-
рез точку указывается поле (имя поля). Пример создания экземпляра про-
стой структуры приведен в документе на рис. Б.1.
Экземпляр структуры создается командой
Card.name='Алексей Васильев';
Card.age=36;
Card.city='Киев';
Card.email='vasilev@univ.kiev.ua'
У созданного экземпляра структуры Card четыре поля: name, age, city
и email. Для того, чтобы получить значение поля, используем инструкцию
вида структура.поле – как, например, в команде Card.email.
Экземпляры структур можно создавать также с помощью функции
struct(). Простой пример использования этой функции приведен в до-
кументе на рис. Б.2.
Самоучитель Matlab
424
Рис. Б .1. Создание экземпляра структуры
Рис. Б.2. Еще один способ создания экземпляра структуры
В этом случае экземпляр структуры создается такой командой:
Card=struct('name','Алексей Васильев','age',36,...
'city','Киев','email','vasilev@univ.kiev.ua')
Аргументы функции struct() указываются парами поле-значение. Ре-
зультат – аналогичный предыдущему.
Использование единственного экземпляра структуры представляется ма-
лоперспективным. Вся прелесть структур связана как раз с возможностью
использования многих экземпляров структуры. Обычно такие "многие" эк-
земпляры реализуют в виде массива – массива структур. Пример создания
небольшого массива структур приведен в документе на рис. Б.3.
Приложение Б. Структуры и ячейки
425
Рис. Б.3 . Массив структур
Создание структур – элементов массива основано на определении полей со-
ответствующих структур. Обращение к полям структуры – элемента масси-
ва выполняется в формате структура(индекс).поле. Например, массив из
трех структур создается такими командами:
>> MS.code=[1 2 3];
MS.num=100;
>> MS(2).code=[4 5 6];
MS(2).num=200;
>> MS(3).code=[7 8 9];
MS(3).num=300;
Вызов команды, состоящей из имени массива структур (например, команда
MS), приводит к отображению общей информации о массиве.
Самоучитель Matlab
426
На заметку
В приведенном примере экземпляр структуры, который стал первым элемен-
том массива, создавался без всякого намека на принадлежность к какому бы
то ни было массиву. Только после создания следующих экземпляров структур
становится ясно, что речь идет о массиве.
Ссылка вида структура(индекс) означает обращение к экземпляру струк-
туры - элементу массива. Инструкция вида массив_структур.поле (как,
например, в команде MS.num) возвращает в качестве результата список из
значений соответствующих полей элементов массива структур.
Еще более либеральным, если можно так выразиться, по сравнению с масси-
вом структур, является массив ячеек. Элементами массива ячеек могут быть
данные любых типов. Массив ячеек удобно представлять в виде банковско-
го сейфа с ячейками, в которых можно хранить различное содержимое.
Во многом массив ячеек похож на обычный массив. Однако при этом важно
помнить, что элементы такого массива в общем случае относятся к разным
типам. Кроме того, при работе с массивами ячеек следует понимать разницу
между ячейкой массива и содержимым ячейки массива. Создается массив
ячеек с помощью функции cell() (аргументы – размеры массива) или
путем явного указания элементов массива. Однако если элементы обычно-
го массива заключаются в квадратные скобки, то элементы массива ячеек
заключаются в фигурные скобки. Чтобы получить доступ к содержимому
ячейки, индекс ячейки указывается в фигурных скобках после имени мас-
сива. Простой пример создания массива ячеек с помощью функции cell()
приведен в документе на рис. Б.4.
Сначала командой IM=cell(2,3) объявляем массив ячеек размерами 2×3.
Чтобы заполнить ячейки значениями, выполняем оператор цикла. Индекс-
ная переменная i пробегает в цикле значения от 1 до 3. В теле цикла выпол-
няются две команды: IM{1,i}=ones(i) и IM{2,i}=rand(i,i). Таким
образом, ячейки первого ряда массива ячеек IM заполняются квадратными
единичными (заполненными единицами) матрицами размера 1, 2 и 3 соот-
ветственно. Ячейки второго ряда массива ячеек IM заполняются квадрат-
ными матрицами, заполненными случайными числами. Вызов имени мас-
сива ячеек IM приводит к отображению информации о содержимом ячеек
массива. Чтобы получить содержимое ячейки массива, индексы указываем
в фигурных скобках – как, например, в команде IM{1,2}. Результатом яв-
ляется квадратная матрица из единиц размера 2×2. Результатом вызова ко-
манды IM{2,3} является матрица из случайных чисел размера 3×3. Другой
пример – на этот раз "явного" создания массива ячеек – приведен во второй
части рассмотренного выше документа, представленной на рис. Б.5.
Приложение Б. Структуры и ячейки
427
Массив ячеек создается командой CA={'Текст',100;[1 2 3],IM}.
Массив ячеек CA состоит из четырех ячеек – по две ячейки в строке. Первая
ячейка в первой строке является текстом, вторая – числом. Первая ячейка
второй строки содержит числовой массив, а вторая ячейка во второй строке
сама является массивом ячеек – это тот массив IM из матриц, который был
создан на предыдущем этапе (см. рис. Б.4). Как и в предыдущем случае, вы-
зов команды из имени массива ячеек позволяет получить общие сведения
о том, что записано в ячейки массива. Для доступа к содержимому ячей-
ки индексы указываем в фигурных скобках. Например, в результате вызо-
ва команды CA{1,1} получаем значение первой ячейки в первой строке.
Для инструкции CA{2,1} результатом является массив, записанный в эту
ячейку. Возможно, комментариев потребует команда CA{2,2}{1,3}, в ре-
зультате выполнения которой получаем квадратную матрицу размера 3×3,
заполненную единицами. Объяснение простое. Результатом инструкции
CA{2,2} является содержимое второй ячейки во втором столбце. Это мас-
сив ячеек IM. Поэтому инструкция CA{2,2}{1,3} на самом деле означает
содержимое ячейки IM{1,3}. Это и есть наша загадочная матрица.
Рис. Б .4 . Создание массива ячеек с помощью функции cell()
Самоучитель Matlab
428
Рис. Б .5 . Явное создание массива ячеек
429
Приложение В
Надстройка для работы с Excel
В сфере услуг еще, к сожалению, характер
требуется. Не докажешь – не получишь!
К/ф "Чародеи"
Приложение Excel занимает особое место среди офисных приложений.
Если коротко, то приложение это исключительно простое в использова-
нии как для расчетного пакета и достаточно продуктивное как для массо-
вого приложения, рассчитанного на широкий круг пользователей. Более
того, приложение Excel идеологически близко, если так можно выразиться,
к пакету Matlab, поскольку в Excel также используется принцип реализа-
ции структур данных в виде таблиц/матриц. Это обстоятельство наводит
на естественную мысль о том, чтобы объединить каким-то образом удоб-
ство интерфейса Excel и вычислительную мощь Matlab. Такая возможность
реализуется с помощью надстройки Spreadsheet Link EX, которая входит
в состав пакета Matlab. Здесь мы опишем, во-первых, как эта надстройка
подключается, и, во-вторых, рассмотрим некоторые простые примеры ис-
пользования возможностей надстройки.
На заметку
В Excel часть возможностей реализована через надстройки. Это специальные
утилиты, которые позволяют использовать дополнительные функции и элемен-
ты интерфейса для решения задач определенного класса. Надстройки могут
поставляться вместе с Excel или отдельно. Для использования надстройки ее
необходимо подключить. Эта процедура выполняется только один раз.
Общая идея, положенная в основу использования надстройки Spread-
sheet Link EX, состоит в том, что после подключения надстройки часть функ-
циональных возможностей Matlab становится доступной непосредственно
из рабочего документа Excel. Другими словами, данные из документа Excel
могут быть импортированы в рабочее пространство Matlab, обработаны там
и экспортированы в документ Excel. Еще раз подчеркнем, что все эти дей-
ствия можно выполнить, так сказать, "не покидая" приложение Excel.
Как уже отмечалось выше, для того, чтобы использовать надстройку
Spreadsheet Link EX, ее необходимо подключить. Процедура эта достаточно
простая и стандартная для Excel. В частности, на вкладке Файл ленты при-
ложения Excel выбираем команду Параметры (рис. В.1).
В результате открывается окно настроек Excel, которое называется Пара-
метры Excel. В левой части окна имеется ряд пиктограмм, определяющих
Самоучитель Matlab
430
тот или иной раздел для выполнения настроек. В данном случае нас интере-
сует раздел Надстройки (рис. В.2).
Рис. В .1. На вкладке Файл выбираем команду Параметры
В нижней части этого окна есть раскрывающийся список Управление, ко-
торый по умолчанию открыт в позиции Надстройки Excel. Справа от этого
списка есть кнопка Перейти, которую необходимо щелкнуть. После этого
откроется диалоговое окно Надстройки, в котором непосредственно вы-
бираются надстройки для подключения. В принципе, достаточно в спи-
ске надстроек установить флажок опции с названием надстройки Spread-
sheet Link EX и щелкнуть кнопку OK (рис. В.3).
Проблема, однако, в том, что, скорее всего, в списке доступных надстроек нуж-
ной надстройки не будет. Причина та, что по умолчанию в списке надстроек
отображаются только те из них, что записаны в определенный каталог. Оче-
видно, что файл надстройки Spreadsheet Link EX находится не там, где хо-
телось бы. Соответствующий файл следует найти, что называется, вручную.
Для этого щелкаем кнопку Обзор и в открывшемся окне находим в системе
каталогов файл надстройки Spreadsheet Link EX. В Matlab для разных версий
Excel предлагаются разные файлы надстройки. Для версии Excel 2010 (как
и Excel 2007) файл называется excllink2007.xlam. По умолчанию файл
находится в подкаталоге \toolbox\exlink того каталога, в который уста-
новлен Matlab (например, каталог C:\Program Files\MATLAB\R2010b\
Приложение В. Надстройка для работы с Excel
431
toolbox\exlink). Указанный файл следует выбрать и подтвердить свой
выбор. Как следствие, в списке надстроек в окне Надстройки (см. рис. В.3)
появится опция с именем надстройки Spreadsheet Link EX.
Рис. В .2 . В окне Параметры Excel в разделе Надстройки необходимо щелкнуть кнопку Перейти
Рис. В.3. Для подключения надстройки Spreadsheet Link EX необходимо установить флажок
соответствующей опции
Самоучитель Matlab
432
После того, как надстройка Spreadsheet Link EX подключена, на вкладке
Главная ленты приложения Excel появляется группа из одной пиктограм-
мы с фирменным Matlab-овским изображением (рис. В.4).
Рис. В.4 . Пиктограмма надстройки Spreadsheet Link EX на вкладке Главная
Данная группа представляет собой раскрывающийся список с командами,
посредством которых выполняются некоторые настройки и базовые дей-
ствия по взаимодействию приложений Matlab и Excel. Для выполнения ряда
важных настроек используем команду Preferences из раскрывающегося
списка команд (рис. В.4). Открывается окно настроек Matlab Preferences
(рис. В.5).
Рис. В.5 . Окно настроек надстройки Spreadsheet Link EX
Окно содержит ряд опций и текстовое поле. По умолчанию опция
Start Matlab at Excel startup активна, и это означает, что при запуске Ex-
cel автоматически будет активироваться (запускаться) и Matlab (в режиме
командного окна). Полезность такого режима во многих случаях сомни-
Приложение В. Надстройка для работы с Excel
433
тельна, если только не предполагается использовать Excel исключительно
для совместной работы с Matlab. Кроме того, использование режима авто-
матического запуска Matlab при запуске Excel увеличивает время загрузки
приложения. Поэтому нередко от данного режима отказываются – в этом
случае необходимо отменить флажок опции Start Matlab at Excel startup.
Если установить флажок опции Use MATLAB desktop, то при запуске Ex-
cel приложение Matlab будет запускаться не в режиме командного окна,
а в обычном рабочем режиме (главное окно приложения и вспомогатель-
ные окна). Наличие флажка этой опции не означает автоматический запуск
приложения Matlab при запуске Excel.
Установленный флажок опции Show MATLAB errors означает переход в ре-
жим, при котором в рабочем документе Excel, в случае возникновения со-
ответствующей ситуации, будут отображаться сообщения об ошибках вы-
числительной системы Matlab. Альтернативный режим подразумевает, что
в рабочем документе Excel отображаются только сообщения об ошибках
вычислительной системы Excel.
Если установить флажок опции Force use of MATLAB cell arrays with
MLPutMatrix, перейдем в режим, при котором экспорт данных из рабочего
листа Excel в документ Matlab с помощью функции MLPutMatrix() вы-
полняется в виде массива ячеек.
На заметку
Как мы увидим из дальнейшего, для экспорта данных из диапазонов ячеек табли-
цы Excel в массив в документе Matlab используется функция MLPutMatrix().
Опция Treat missing/empty cells as NaN позволяет контролировать способ
обработки пустых ячеек при экспорте из Excel в Matlab. Если флажок оп-
ции не установлен, пустые ячейки обрабатываются как такие, что содержат
нулевые значения. Если флажок опции установлен, то такие ячейки обраба-
тываются как имеющие нечисловое значение (значение NaN).
Что касается текстового поля в окне настроек Matlab Preferences, то в этом
поле отображается рабочий каталог для приложения Matlab (содержимое
каталога отображается в окне Current Folder после загрузки приложения
Matlab).
Для начала работы с надстройкой Spreadsheet Link EX необходимо, во-
первых, запустить приложение Excel и, во-вторых, загрузить Matlab (загру-
зить из Excel – это важно!). Если Matlab автоматически не загружается при
запуске Excel, необходимо воспользоваться командой Start MATLAB, как
показано на рис. В.6.
Самоучитель Matlab
434
Рис. В.6. В случае необходимости выполняем команду Start MATLAB
После того, как все формальности выполнены, можно приступить непо-
средственно к работе. По большому счету вся "работа" сводится к следую-
щим этапам (в разной последовательности и в разном объеме):
• Экспорт данных из рабочего пространства Excel в рабочее пространство
Matlab.
• Выполнение вычислений и обработка данных в среде Matlab через
команды рабочей среды Excel.
• Импорт данных из рабочего пространства Matlab в рабочий документ
Excel.
При этом непосредственно вычисления в рабочем документе Excel мы
особо не выделяем, поскольку в том нет ничего необычного (во всяком
случае, для пользователей, знакомых с Excel). Рассмотрим небольшой
пример. В нем реализованы все три этапа. А именно, в документе Excel
вводятся элементы некоторой матрицы. Эта матрица экспортируется
в Matlab, там для матрицы вычисляется обратная, и эта обратная матрица
импортируется в Excel.
На заметку
Сразу отметим, что такая задача может быть решена исключительно средства-
ми Excel без привлечения Matlab. Но здесь именно тот случай, когда важен не
результат, а метод его получения.
Рабочий документ Excel, в котором выполняются соответствующие вычис-
ления, представлен на рис. В.7.
Значения элементов исходной матрицы записаны в ячейки диапазона
E2:G4. Для сравнения в ячейках E7:G9 с помощью встроенной функции
Excel МОБР() вычисляется обратная матрица.
Приложение В. Надстройка для работы с Excel
435
На заметку
Для вычисления обратной матрицы выделяем диапазон ячеек E7:G9 и вводим
формулу массива =МОБР(E2:G4) (формула вводится нажатием комбинации
клавиш <Ctrl>+<Shift>+<Enter>).
Но главные события происходят не здесь. Все, что нас интересует в пер-
вую очередь, связано с ячейками C2:C4. Если все вычисления выполнены
корректно, в этих ячейках должны быть нули. В ячейку C2 вводится фор-
мула =MLPutMatrix("A";E2:G4). Эта команда означает, что содержимое
диапазона ячеек E2:G4 экспортируется в Matlab и присваивается в каче-
стве значения переменной A. Первым аргументом функции надстройки
MLPutMatrix() указывается (в двойных кавычках) имя переменной
в рабочей среде Matlab, которой присваивается, в качестве значения, со-
держимое диапазона, который указывается вторым аргументом функции
MLPutMatrix(). В результате выполнения этой команды в рабочем про-
странстве Matlab создается переменная A и ей присваивается соответствую-
щее значение (этот факт мы еще проверим).
На заметку
В русифицированной версии Excel аргументы функций разделяются точкой
с запятой. В оригинальной версии приложения аргументы функций разделяют-
ся запятыми.
Рис. В.7 . Документ Excel с вычислениями
Самоучитель Matlab
436
В ячейку C3 вводится и выполняется формула =MLEvalString("B=
inv(A)"). Функция MLEvalString() позволяет выполнять команды сре-
ды Matlab. Команды (в двойных кавычках) указываются аргументом функ-
ции MLEvalString(). Если команд несколько, они разделяются точкой с за-
пятой. В данном случае команда одна: B=inv(A). Именно такую команду нам
надо было бы выполнить в командном окне Matlab, если бы мы работали не-
посредственно с приложением Matlab. Результат команды такой: в перемен-
ную B записывается результат выражения inv(A), то есть обратная матрица
к той, что записана в переменную A. После того, как обратная матрица вычис-
лена, содержимое переменной B из рабочего пространства Matlab необходимо
импортировать в рабочий документ Excel. Для этого в ячейку C4 и вводится
формула =MLGetMatrix("B";"E12"). Функцией MLGetMatrix() эле-
менты матрицы (первый аргумент функции) рабочего пространства Matlab
копируются в ячейки диапазона, указанного вторым аргументом функции.
Оба аргумента заключаются в двойные кавычки. Если вторым аргументом
указана одна ячейка, то она определяет верхнюю левую ячейку заполняемого
в Excel диапазона. В данном случае диапазон ячеек E12:G14 будет заполнен
элементами матрицы, обратной к исходной (диапазон ячеек E2:G4).
На заметку
В ячейки диапазона E12:G14 копируются числовые значения, а не формулы.
Это обстоятельство достаточно важно для понимания принципов использова-
ния надстройки Spreadsheet Link EX.
Теперь проверим, что произошло в рабочем пространстве Matlab. Для этого
в командном окне проверяем значения переменных A и B, как показано на
рис. В.8.
Видим, что и переменная A, и переменная B содержат корректные значения.
Причем стоит обратить внимание, что непосредственно в рабочем докумен-
те Matlab мы эти переменные не объявляли.
На заметку
Выше мы использовали три встроенные функции надстройки: MLPutMatrix(),
MLEvalString() и MLGetMatrix(). При успешном выполнении функции
возвращают в качестве значения 0. Это характерная ситуация для функций над-
стройки Spreadsheet Link EX. Здесь проявляется принципиальное отличие функ-
ций надстройки от встроенных функций Excel. Встроенные функции Excel воз-
вращают результат, а функции надстройки выполняют действия.
Несмотря на кажущуюся эффективность описанного выше подхода, есть
одна маленькая проблема, которая может стать достаточно большой. Связа-
на она с автоматическим пересчетом содержимого документа Excel (с фор-
мулами на основе функций надстройки Spreadsheet Link EX) при измене-
нии данных в ячейках документа. Проиллюстрируем это на примере с ранее
Приложение В. Надстройка для работы с Excel
437
созданным документом. Для этого меняем, например, значение в ячейке E4
с 0 на 1, как показано на рис. В.9.
Рис. В.8. Проверка значений переменных в командном окне Matlab
Рис. В.9. Изменение содержимого ячейки E4 не приводит к пересчету результата
в ячейках E12:G14
Самоучитель Matlab
438
Если результат в ячейках E7:G9, вычисленный на основе встроенной функ-
ции МОБР(), автоматически пересчитан, то ячейки диапазона E12:G14
остались неизменными. При этом если проверить содержимое переменных
A и B, то значение переменной A изменилось, а значение переменной B – нет
(рис. В.10).
Рис. В.10. Проверка значений переменных A и B
Дело в том, что в Excel при изменении ячеек пересчитываются те ячейки,
которые содержат зависимые ячейки (то есть ячейки, которые содержат
формулы со ссылкой на изменяемые ячейки). Поэтому если изменить ячей-
ку в диапазоне E2:G4, то значение в ячейке C2 пересчитывается, поскольку
формула в ячейке содержит ссылку на диапазон E2:G4. В результате пере-
менная A в рабочем пространстве Matlab получает новое значение. А значе-
ние в ячейке C3 не пересчитывается, поскольку формула в этой ячейке не
содержит ссылок ни на ячейку C2, ни на ячейки диапазона E2:G4.
Проблему можно решать по-разному. Общая идея состоит в том, чтобы из-
менить формулы в ячейках C2 и C3 так, чтобы они изменялись при изме-
нении ячеек в диапазоне E2:G4. Не мудрствуя лукаво, вводим в ячейку C3
формулу =MLEvalString("B=inv(A)")+СУММ(E2:G4), а в ячейку C4
вводим формулу =MLGetMatrix("B";"E12")+C3. В первом случае не
особенно важно, какая использована "дополнительная" функция – глав-
ное, чтобы она содержала весь диапазон ячеек E2:G4 и чтобы значение
этой "дополнительной" функции менялось при изменении значения хотя
бы одной ячейки. В рассматриваемом случае функция СУММ() вполне под-
ходит. В результате при успешном вычислении формулы =MLEvalString
Приложение В. Надстройка для работы с Excel
439
("B=inv(A)")+СУММ(E2:G4) в ячейке C3 отображается сумма ячеек
диапазона E2:G4. Сам по себе этот факт маловажен. Намного важнее то,
что формула содержит ссылку на диапазон ячеек E2:G4. Это означает, что
при изменении ячеек диапазона E2:G4 будет пересчитываться и значение
в ячейке C3, чего мы, собственно, и добивались. Более того, изменение ячей-
ки диапазона E2:G4 приводит к изменению значения ячейки C3. Ссылка
на эту ячейку содержится в формуле =MLGetMatrix("B";"E12")+C3
в ячейке C4. Поэтому пересчитывается значение и в этой ячейке. На
рис. В.11 показан документ Excel с внесенными в него изменениями.
Рис. В.11 . В формулы в ячейках C3 и C4 внесены изменения
Для контроля результата в ячейку E4 вместо исходного значения 0 вводим значе-
ние 1. В результате выполняется пересчет документа, как показано на рис. В.12.
Рис. В.12. После изменения ячейки в диапазоне E2:G4 корректно вычисляются значения
ячеек диапазона E12:G14
Самоучитель Matlab
440
Видим, что обратная матрица, вычисленная путем использования средств
Matlab, совпадает с обратной матрицей, вычисленной средствами Excel.
Разумеется, что в общем случае приложение Matlab используется совмест-
но с приложением Excel для решения более сложных задач – как правило,
таких, которые не могут быть решены (или которые сложно решать), ис-
пользуя только утилиты Excel.
441
Список литературы
Полезные и не очень ссылки
Огласите весь список, пожалуйста!
К/ф "Операция Ы и другие приключения
Шурика"
Далее представлены некоторые ссылки на книги по Matlab и не только, ко-
торые, возможно, будут полезными читателю при изучении методов работы
с Matlab. Разумеется, список достаточно субъективный. С другой стороны,
именно субъективные оценки разных авторов и читателей формируют объ-
ективную картину. Окончательное формирование всей объективной карти-
ны в нашу задачу не входит, но вот внести свою лепту в процесс мы сможем.
Предадимся же субъективизму!
Для большего удобства все книги разбиты на несколько групп. Как и все
в нашем списке, разбиение на группы тоже субъективно.
Базовые методы работы с Matlab
1. Ануфриев И. Самоучитель MatLab 5.3/6.x. СПб.: БХВ, 2002, 736 с.
2. Ануфриев И., Смирнов А., Смирнова Е. Matlab 7. СПб.: БХВ, 2010, 1104 с.
3. Дьяконов В.П. MATLAB 7. Самоучитель. М.: ДМК-Пресс, 2010, 768 с.
4. Кетков Ю., Кетков А., Шульц М. MATLAB 7. Программирование, чис-
ленные методы. СПб.: БХВ, 2010, 752 с.
5. Кетков А., Кетков Ю., Шульц М. MATLAB 6.x: программирование чис-
ленных методов. СПб.: БХВ, 2004, 672 с.
6. Курбатова Е.А. Matlab 7. Самоучитель. К.: Диалектика, 2005, 256 с.
7. Половко А., Бутусов П. MATLAB для студента. СПб.: БХВ, 2010, 320 с.
Прикладные вычисления в Matlab
1. Джон Г. Мэтьюз, Куртис Д. Финк. Численные методы. Использование
MATLAB. К.: Диалектика, 2001, 720 с.
2. Дьяконов В.П. MATLAB R2007/2008/2009 для радиоинженеров. М.:
ДМК-Пресс, 2010, 976 с.
3. Иглин С. Математические расчеты на базе MATLAB. СПб.: БХВ, 2007,
640 с.
Самоучитель Matlab
442
4. Мещеряков В.В. Задачи по математике с Matlab и Simulink. М.: Диалог-
МИФИ, 2007, 528 с.
5. Чарльз Генри Эдвардс, Дэвид Э. Пенни. Дифференциальные уравнения
и краевые задачи: моделирование и вычисление с помощью Mathematica,
Maple и MATLAB. К.: Диалектика, 2007, 1104 с.
Смежные вопросы работы с Matlab
1. Инг Бей. Взаимодействие разноязыковых программ в Microsoft Windows.
Руководство программиста. К.: Диалектика, 2005, 880 с.
2. Леоненков А. Нечеткое моделирование в средах MATLAB и fuzzyTECH.
СПб.: БХВ, 2010, 736 с.
3. Смоленцев Н.К. MATLAB: Программирование на Visual C#, Borland C#,
JBuilder, VBA. М.: ДМК-Пресс, 2010, 464 с.
4. Смоленцев Н.К. Основы теории вейвлетов. Вейвлеты в MATLAB.
М.: ДМК-Пресс, 2010, 448 с.
Математика и численные методы
1. Березин И.С., Жидков Н.П. Методы вычислений. М.: Физматгиз, 1959,
т.1,464с.
2. Березин И.С., Жидков Н.П. Методы вычислений. М.: Физматгиз, 1959,
т.2,620с.
3. Бермант А.Ф., Араманович И.Г. Краткий курс математического анализа.
М.: Наука, 1971, 736 с.
4. Бугров Я.С., Никольский С.М. Высшая математика. М.: Наука, 1989,
464 с.
5. Тихонов А.Н., Самарский А.А. Уравнения математической физики.
М.: Наука, 1977, 736 с.
Кроме того, достаточно неплохой список доступной литературы по вопро-
сам работы с Matlab представлен, например, на сайтах http://matlab.
exponenta.ru/books/default.php или http://www.mathworks.
com/products/matlab/books.html.
Книги издательства «Наука и техника»
—
ваш правильный выбор!
Книги издательства «Наука и техника»
—
ваш правильный выбор!
Группа подготовки издания:
Зав. редакцией компьютерной литературы: М. В . Финков
Редактор: М. А. Финкова
Корректоры: А. В . Громова
ООО «Наука и Техника»
Лицензия No000350 от 23 декабря 1999 года.
198097, г. Санкт-Петербург, ул. Маршала Говорова, д. 29.
Подписано в печать 01.11 .2014. Формат 70х100 1/16.
Бумага газетная. Печать офсетная. Объем 28 п. л.
Тираж 500. Заказ
Отпечатано в ГП ПО «Псковская областная типография»
180004, г. Псков, ул. Ротная, 34.