Автор: Кетков Ю.Л. Кетков А.Ю. Шульц М.М.
Теги: компьютерные технологии программирование линейная алгебра математический анализ дискретная математика математическое обеспечение язык программирования matlab
ISBN: 5-94157-347-2
Год: 2005
1ЬПУ w* ЮЛИЙ КЕТКОВ
< ' АЛЕКСАНДР КЕТКОВ
МИХАИЛ ШУЛЬЦ
Т
ПРОГРАММИРОВАНИЕ,
ЧИСЛЕННЫЕ МЕТОДЫ
Интегральная
среда разработки " -• *V .
i *•**
v:
Графическое ?, •' 3* г
представление данных ^ *>
Программирование
вычислительных процессов
Визуализация
трехмерных объектов
Линейная алгебра . у
*
■4~t>
дифференцирование
и интегрирование
Нелинейные уравнения
и оптимизация
\
Численное j ' к
\t
цД
МАСТЕР
Юлий Кетков
Александр Кетков
Михаил Шульц
MATLAB7
ПРОГРАММИРОВАНИЕ,
ЧИСЛЕННЫЕ МЕТОДЫ
Санкт-Петербург
«БХВ-Петербург»
2005
УДК 681.3.06
ББК 32.973.26-018.2
К37
Кетков 10. Л-, Кетков А. Ю., Шульц М. М.
К37 MATLAB 7: программирование, численные методы. — СПб.:
БХВ-Петербург, 2005. — 752 с: ил.
ISBN 5-94157-347-2
Книга посвящена описанию программных средств разработки
математического обеспечения п среде MATLAB. Особое внимание уделяется
вопросам проектирования пользовательских приложений, представления данных
с максимальным использованием средств программирования и отладки
приложений, а также увязке программ решения задач линейной алгебры,
дискретной математики, математического анализа с основными идеями
соответствующих алгоритмов.
Для инженеров, студентов и преподавателей вузов
УДК 681.3.06
ББК 32.973.26-018.2
Группа подготовки издания:
Главный редактор Екатерина Кондукова
Зам. главного редактора Евгении Рыбаков
Зав. редакцией Григорий Добнн
Редактор Анна Кузьмина
Компьютерная верстка Нотами Смирновой
Корректор Наталия Першакова
Дизайн обложки Игоря Цыру./ьникова
Зав. производством Николай Тверских
Лицензия ИД No 02429 от 24.07.00. Подписано в печать 22.03.05.
Формат 70x100Vle. Печать офсетная. Усл. печ. л. 60.63,
Тираж 3000 экз. Заказ № 899
"БХВ-Петербург". 194354, Санкт-Петербург, ул. Есенина, 5Б.
Санитарно-эпидемиологическое заключение на продукцию N» 77,99.02.953.Д,006421.11.04
от 11.11.2004 г. выдано Федеральной службой по надзору
в сфере защиты прав потребителей и благополучия человека.
Отпечатано с готовых диапозитивов
в ГУП "Типография "Наука"
199034, Санкт-Петербург, 9 линия, 12
ISBN 5-94157-347-2 © Кетков Ю. Л., Кетков А. Ю., Шульи М. М.. 2005
© Оформление, издательство "БХВ-Петербург", 2005
Оглавление
Предисловие 1
Глаиа 1. Краткий обзор 3
1.1. Немного истории 3
1.2. Пакет MATLAB 7 и его расширения 5
Глава 2. Пошаговые вычисления в командном окис 13
2.1. Путешествие по среде MATLAB 7 13
2.2. Переменные рабочего пространства , 20
2.3. Скаляры или массивы? Индексированные переменные 22
2.4. Выбор формата отображения числовых данных 25
2.5. Арифметические выражения , 29
2.5.1. Некоторые свойства вещественных данных 29
2.5.2. Специфика использования комплексных величин 30
2.5.3. Числовые матрицы и векторы, специфика представления 33
2.5.4. Специфика выполнения арифметических и логических
операций 37
2.5.5. Использование элементарных математических функций 39
2.6. Построение графиков функций одной переменной 43
2.6.1. Простые графики в декартовых координатах 43
2.6.2. График функции в полярных координатах 50
2.6.3. Использование логарифмического масштаба 52
2.6.4. Построение графика функции на заданном интервале 52
2.6.5. Средства управления в графическом окне 55
2.6.6. Редактирование графиков 60
Меню Edit 60
Меню View 67
Меню Insert 69
Меню Tools 69
2.6.7. Включение графиков в отчетную документацию 76
2.7. Деловая графика 77
2.7.1. Плоские столбиковые диаграммы 77
2.7.2- Объемные столбиковые диаграммы 81
2.7.3. Круговые диаграммы S3
2.7.4. Площадные диаграммы 86
IV Оглавление
Глава 3. Типы данных 89
3.1. Иерархия типов данных в MATLAB 89
3.1.1. Символьные массивы (char arrays) 90
3.1.2. Целочисленные данные в MATLAB 92
3.1.3. Вещественные данные с одинарной точностью (single arrays) 98
3.1.4. Разреженные матрицы (sparse arrays) 100
3.1.5. Структуры и массивы структур (struct arrays) 101
3.1.6. Массивы ячеек (cell arrays) 104
3.1.7. Массивы указателей на функции (function handle arrays) 105
3.1.8. Логические массивы (logical arrays) 106
3.1.9. Создание массивов из данных разного типа 107
3.2. Программа тестирования данных 108
3.3. Анализ типа данных и состояния элементов массивов 113
3.4. Редактирование массивов 119
Глава 4. Программирование вычислительных процессов 123
4.1. Скрипты и функции 123
4.2. Специфика выполнения операций 127
4.3. Синтаксис операторов MATLAB 127
4.4. Ввод числовых и символьных данных 133
4.5. Вывод результатов вычислений 134
4.6. Типы функций 135
4.7. Параметры функций 137
4.8. Функции era/ и feval 144
4.9. Специфика работы в редакторе m-файлов 146
4.9.1. Меню Text 148
4.9.2. Меню Debug 149
4.9.3. Меню Edit 152
4.10. Отладочные команды 155
4.11. Анализ эффективности программы 160
Глава 5. Обработка символьных данных 165
5.1. Создание символьных объектов 165
5.2. Конкатенация строк 171
5.3. Сравнения символьных данных 174
5.4. Поиск и замена 178
5.5. Преобразования к верхнему и нижнему регистрам 183
5.6. Преобразования строк и чисел 183
5.7. Форматные преобразования (sprint/, sscanf) ..192
5.8. Регулярные выражения и поиск., 198
Глава 6. Работа с файлами 207
6.1. Подготовка файла к работе 209
6.2. Завершение работы с файлами 212
Оглавление V
6.3. Контроль за исчерпанием данных 212
6.4. Работа с двоичными файлами 213
6.4.1. Чтение данных из двоичного файла 214
6.4.2. Запись в двоичный файл 220
6.5. Работа с текстовыми файлами , 223
6.5.1. Последовательное чтение строк из текстового файла 224
6.5.2. Последовательное чтение нескольких символов из файла 224
6.5.3. Форматирование выводимой строки 225
6.5.4. Чтение данных из текстового файла 234
6.6. Форматные преобразования в оперативной памяти 238
6.7. Анализ ошибок в файловых операциях 238
6.8. Альтернативный доступ к текстовым файлам 239
6.9. Числовые файлы с разделителями 250
Глава 7. Иерархия графических объектов и их свойства 255
7.1. Объект Root 260
7.2. Объект Figure , 266
7.3. Объект Ares 274
7.4. Объект Line 283
7.5. Объект Rectangle 287
7.6. Объект Text. 291
7.7. Объект Image 298
7.8. Поиск объектов 312
Глава 8. Проектирование интерфейса 315
8.1. Динамическое создание интерфейсных элементов 321
8.1.1. Командная кнопка 328
8.1.2. Кнопка, фиксирующаяся в утопленном состоянии 335
8.1.3. Рамки, индикаторы альтернативных и неальтернативных
комбинаций 336
8.1.4. Ввод, редактирование и отображение текстов 341
8.1.5. Списки строк 345
8.1.6. Полоса прокрутки 347
8.2. Создание всплывающего меню 350
8.3. Проектирование интерфейса в среде GUIDE 352
8.3.1. Вызов редактора GUIDE ." 353
8.3.2. Управление конструктором графического интерфейса 360
8.3.3. Размещение интерфейсных элементов 365
8.3.4. Инспектор свойств (Property Inspector) 371
8.3.5. Просмотр объектов (Object Browser) 372
8.3.6. Создание меню (Menu Editor) 372
8.3.7. Анатомия файла, создаваемого в среде GUIDE 380
8.3.8. Использование контейнеров 387
VI Оглавление
Глава 9. Стандартные диалоговые окна 393
9.1. Диалоговое окно общего назначения (dialog) 394
9.2. Окно с сообщением об ошибке (errordlg) 395
9.3. Окно со справочной информацией (helpdlg) 396
9.4. Стандартное окно для ввода строк (inputdlg) 397
9.5. Окно выбора из списка (listdlg) 399
9.6. Диалоговое окно с сообщением (tnsgbox) 402
9.7. Интерактивная настройка параметров страницы (pagedlg) 403
9.8. Диалоговая страница (pageseitipdlg) 405
9.9. Окно настройки параметров печати (printdlg) 406
9.10. Диалоговое окно с запросом (qtiestdlg) 408
9.11. Выбор имени файла для чтения (uigetjile) 409
9.12. Выбор имени файла для записи (uiput/ile) 412
9.13. Диалоговое окно для выбора цвета (uisetcolor) 413
9.14. Диалог по выбору параметров шрифта (uisetfont) 415
9.15. Диалоговое окно с предупреждением (warndlg) 416
9.16. Полоса прогресса 417
Глава 10. Визуализация трехмерных объектов 421
10.1. Некоторые задачи и алгоритмы трехмерной визуализации 421
10.1.1. Аффинные преобразования и однородные координаты 421
10.1.2. Растеризация векторных изображений 423
10.1.3. Воспроизведение утолщенных линий 424
10.1.4. Устранение невидимых частей изображения 424
10.1.5. Окрашивание граней полигональных моделей 425
10.2. Создание и отображение криволинейных поверхностей 427
10.2.1. Объект типа Surface и его свойства 427
10.2.2. Отображение проволочного каркаса поверхности 432
10.2.3. Отображение закрашенных поверхностей 436
10.2.4. Управление точкой зрения 437
10.2.5. Выбор алгоритма визуализации 438
10.2.6. Освещение поверхностей 440
10.2.7. Построение линий уровня 442
10.3. Формирование и отображение полигональных тел 448
10.3.1. Объект типа Patch и его свойства 448
10.3.2. Закрашивание объектов типа Patch... 455
10.4. Специальные способы закраски. Призрачность 460
10.4.1. Нанесение изображения на поверхность 460
10.4.2. Прозрачные поверхности 462
Глава И. Полиномы 465
11.1. Представление полиномов 465
11.2. Операции над полиномами, представленными вектором
коэффициентов , 466
Оглавление VII
11.2.1. Значение полинома 466
11.2.2. Сложение и вычитание , , 467
11.2.3. Умножение и деление 468
11.2.4. Дифференцирование и интегрирование 469
11.2.5. Корни полинома 470
11.3. Операции над полиномами, заданными в символьном виде 471
11.3.1. Значение полинома 471
11.3.2. Сложение и вычитание 472
11.3.3. Умножение и деление 473
11.3.4. Дифференцирование и интегрирование 474
11.3.5. Корни и разложение полинома на множители 476
Глава 12. Линейная алгебра 479
12.1. Основные матричные операции 479
12.2. Скалярное и векторное произведение 481
12.3. Стандартные матрицы, фрагменты и блоки 487
12.4. Простые преобразования матриц 488
12.5. Некоторые классы матриц 490
12.5.1. Симметричные и кососимметричпые матрицы 490
12.5.2. Эрмитовы и косоэрмитовы матрицы 490
12.5.3. Ортогональные (унитарные) матрицы 490
12.6. Специальные матрицы 490
12.6.1. Матрица Гильберта и обратная к ней 490
12.6.2. Матрица Адамара 491
12.6.3. Матрица Паскаля 491
12.6.4. Матрица Теплица 492
12.6.5. Матрица Ганкеля 492
12.6.6. Матрица Вандермонда 493
12.6.7. Магический квадрат 494
12.7. Разложение матриц 494
12.7.1. Разложение Эрмита 494
12.7.2. Скелетное разложение 496
12.7.3. LU-разложение 498
12.7.4. Разложение Холецкого 500
12.7.5. QR-разложение 500
12.7.6. Сингулярное разложение 503
12.7.7. Полярное разложение 504
12.7.8. Разложение Шура 505
12.7.9. Разложение Хессенберга 507
12.7.10. Разложение Жордана 509
12.8. Системы линейных уравнений 511
12.8.1. Основные понятия 511
Существование и единственность решения 511
Обратная и псевдообратная матрицы 511
Оглавление
12.8.2. Решение совместной системы 512
12.8.3. Псевдорешение несовместной системы 515
12.8.4. Некоторые приложения 517
Линейные матричные уравнения 517
Система уравнений с формируемой матрицей 519
12.9. Проблема собственных значений 522
12.9.1. Характеристический полином 522
Собственные векторы 523
12.9.2. Вычисление собственных значений 524
Случай кратных корней 525
Случай комплексных корней 526
12.9.3. Обусловленность матрицы , 527
12.10. Линейная алгебра и новые тины данных 529
Глава 13. Интерполяция и аппроксимация 535
13.1. Интерполяционный полином 535
13.2. Сплайны 539
13.2.1. Стандартные сплайны MATLAB 543
13.2.2. Сглаженные сплайны 544
13.2.3. Сплайны с заданными условиями на концах 546
13.3. Параметрическая аппроксимация 549
13.4. Двумерная аппроксимация 553
13.4.1. Аппроксимация на прямоугольной сетке 553
13.4.2. Аппроксимация с помощью, триангуляции 555
Глава 14. Численное дифференцирование и интегрирование 559
14.1. Конечные разности 559
14.2. Численное дифференцирование функций одной переменной 560
14.3. Численное дифференцирование функций двух переменных 562
14.4. Численное интегрирование 563
14.5. Задача Коши для обыкновенных дифференциальных уравнений 572
14.6. Краевая задача для обыкновенных дифференциальных уравнений 580
14.7. Дифференциальные уравнения неявного типа 588
Глава 15. Нелинейные уравнения и оптимизация 595
15.1. Корень уравнения с одним неизвестным 595
15.2. Решение систем нелинейных уравнений 599
15.3. Минимизация унимодальной функции одной переменной 611
15.4. Многомерная безусловная минимизация 614
15.4.1. Функция fminsearch 614
15.4.2. Функция fminunc 618
15.4.3. Функция Isqnonlin 624
15.4.4. Функция fminimax 629
Оглавление
IX
15.5. Условная минимизация 637
15.5.1. Функция fmincon 638
15.5.2. Функции Isqnonlin wfiiiimmax 646
15.6. Управление итерационными процессами 649
Глава 16. Математическое программирование 653
16.1. Линейное программирование 653
16.2. Бинарное линейное программирование 658
16.3. Решение матричных игр 662
16.4. Квадратичное программирование 667
Глава 17. Метод Монте-Карло 675
17.1. Генерация случайных данных 676
17.2. Элементы математической статистики 677
17.3. Линейная интерполяция в многомерном кубе 678
17.4. Вычисление кратных интегралов 683
17.5. Решение уравнений в частных производных 686
17.6. Моделирование случайных процессов 695
17.7. Случайный поиск 699
Приложения 70S
Приложение 1. Помощь в системе MATLAB 707
Поиск по ключевым словам 708
Использование Help-навигатора 710
Поиск функций 713
Приложение 2. Указатель свойств графических объектов 715
Литература и интернет-источники 723
MATLAB 723
Методы вычислений 725
Интернет 727
Предметный указатель.. 728
Предисловие
Система MATLAB представляет собой уникальный сплав универсальных
программных и алгоритмических средств с широкой гаммой
специализированных приложений. Входной язык и среда программирования MATLAB
очень близки к современным системам визуального программирования на
базе универсальных алгоритмических языков типа Basic, C++, Java, Object
Pascal. По ряду аспектов MATLAB уступает указанным системам (режим
интерпретации, небольшой запас визуальных компонентов). Однако с его
библиотекой численных методов ни по объему, ни по качеству не может
сравниться ни одна из систем профаммирования. Кроме того, в пакете MATLAB
тщательно отработаны средства визуализации результатов вычислений и
отображения различных графических объектов. На базе ядра MATLAB созданы
многочисленные расширения, обеспечивающие моделирование и анализ
систем в разнообразных сферах человеческой деятельности.
Многие учебные заведения у нас и за рубежом используют MATLAB при
подготовке специалистов различного профиля. Для современного инженера
и научно-технического работника MATLAB является незаменимым
инструментом моделирования и исследования различных прикладных систем,
прежде всего, за счет использования готовых решений. Но не менее важно
научиться создавать новые приложения, используя программные и
алгоритмические средства MATLAB, а также возможность объединения модулей,
разработанных в разных системах программирования. Использование
системы MATLAB в учебном процессе позволит сблизить дисциплины,
связанные с информатикой и численными методами, которые зачастую читаются
автономно.
Авторы выражают признательность М. В. Шашкову, который на
протяжении ряда лет успешно использует систему MATLAB для проектирования и
исследования сложных динамических систем. Именно он привлек наше
внимание к выразительности программных средств и богатству численных
методов пакета MATLAB. Мы очень обязаны и нашим коллегам,
специализирующимся в различных разделах прикладной математики, которые
помогли нам в формировании глав, связанных с численными методами, и в под-
2
Предисловие
боре соответствующих приложений. Среди них преподаватели факультета
ВМиК Нижегородского университета — М. А. Антонец, А. И. Гавриков,
С. Ю. Городецкий, Н. В. Дерендяев, В. А. Зорин, А. П. Мальцев, В. П.
Савельев. Особой благодарности заслуживает А. И. Кузнецов — сотрудник
научно-исследовательского института прикладной математики и кибернетики
Нижегородского университета, который тщательно прочитал рукопись и
проверил практически все примеры программ. Многие его замечания были
учтены при подготовке настоящего издания.
Глава 1
Краткий обзор
Пакет MATLAB 7 — последняя версия одного из наиболее популярных
продуктов фирмы MathWorks, появившаяся на рынке программного
обеспечения в июне 2004 г. Его основное назначение — моделирование, анапиз и
визуализация динамических процессов, имеющих отношение к
разнообразным сферам человеческой деятельности.
1.1. Немного истории
Историю появления пакета MATLAB связывают с именем профессора
Клива Б. Моулера (Cleve В. Mouler). До перехода в фирму MathWorks он
занимался преподавательской и научно-исследовательской деятельностью на
кафедрах математики и в компьютерных центрах ряда университетов США
(Ыыо-Мехико, Мичиган, Стэнфорд). Он соавтор ряда книг, переведенных
на русский язык ([66, 67]). Примерно 30 лет назад Моулер принимай участие
в разработке пакетов программ на языке Fortran для решения задач
линейной алгебры (UNPACK) и исследованиях проблемы собственных значений
матриц (EISPACK). В 1980 г. на международной конференции AFIPS он
представил доклад "Design of an interactive matrix calculator", в котором, по-
видимому, впервые было озвучено название MATLAB. В реферативном
журнале "Автоматика и вычислительная техника" (реферат 6Б200 за 1980 г.) по
поводу этого доклада появилась следующая аннотация:
"Приведено формальное описание (с помощью синтаксических
диаграмм) входного языка интерактивной программы MATLAB,
предназначенной для матричных вычислений. Программа MATLAB обрабатывает
прямоугольные матрицы, элементами которых являются комплексные
числа. Данные вводятся либо перечислением элементов, либо в цикле
при помощи операторов for и while, либо считыванием из внешнего
файла, либо после выполнения внешней программы. Для выполнения
матричных вычислений помимо 37 встроенных функций программы
MATLAB предусмотрен простой способ обращения к пакету ПП
EISPACK (70 программ выполнения матричных вычислений) и пакету
4
Глава 1
LINPACK (40 программ анализа и решения систем линейных
алгебраических уравнений) и связанных с ними матричных вычислений.
Программа написана на языке Fortran и может работать под управлением
любой системы, допускающей выполнение программ в диалоговом
режиме".
Второе рождение пакета MATLAB связывают с Джеком Лигглом (Jack Little) —
нынешним президентом фирмы MathWorks, который в начале 80-х годов
прошлого века перенес программу MATLAB на более современные
вычислительные платформы VAX, Macintosh и IBM PC. Дальнейшее развитие
пакета происходило под эгидой MathWorks, однако к расширению состава
пакета и сфер его применения были привлечены коллективы
высококвалифицированных математиков и инженерно-технических работников
Старого и Нового света. Об этом свидетельствуют ссылки на многочисленные
книги и перечень благодарностей, которые можно обнаружить в справочных
файлах по всем продуктам пакета. С момента основания фирмы (1984 г.)
К. Моулер является ее бессменным научным руководителем.
Модернизацию и программное сопровождение пакета MATLAB обеспечивают более
1000 сотрудников MathWorks.
К концу 2004 г. реализации пакета MATLAB насчитывают следующие версии:
1. MATLAB 5 — декабрь 1996 г.
2. MATLAB 5.1 — май 1997 г.
3. MATLAB 5.3 (Release 11, Rll) — январь 1999 г.
4. MATLAB 6.0 (R12) — ноябрь 2000 г.
5. MATLAB 6.1 (R12.1) - июнь 2001 г.
6. MATLAB 6.5 (R13) - июнь 2002 г.
7. MATLAB 6.51 (R13SP1) — август 2003 г.
8. MATLAB 7.0 (R14) - июнь 2004 г.
Пакет MATLAB распространяется в двух модификациях —
профессиональная версия и облегченный вариант, ориентированный на использование в
учебном процессе. На самом деле даже в профессиональной версии
некоторые расширения пакета приобретаются по отдельной лицензии.
В нашей стране информация по вопросам использования и распространения
пакета доступна на сайтах www.softline.ru, www.matlab.ru и www.exponenta.ru.
Регулярные научные семинары, посвященные возможностям пакета MATLAB,
проводятся Институтом Проблем Управления РАН РФ и
Консультационным центром MATLAB компании Softline.
О популярности пакета MATLAB свидетельствуют более 600 монографий,
учебных и практических пособий, изданных за рубежом. Отечественная ли-
Краткий обзор
5
тература насчитывает примерно в 15 раз меньше наименований (ели список
литературы и интернет-источников).
Одной из наиболее важных особенностей пакета MATLAB является его
открытость. В его комплекте поставляется довольно много исходных текстов
программных модулей — функций, тестовых примеров. Это предоставляет
возможность пользователям разобраться в алгоритмах, модифицировать их
для своих приложений и расширять сферу применения пакета.
1.2. Пакет MATLAB 7 и его расширения
Перечислим принципиальные новинки MATLAB 7:
П 12 новых компонентов, расширяющих сферу приложений пакета
MATLAB и повышающих функциональные возможности прежних
компонентов;
П 28 компонентов предыдущей версии подверглись существенной
модификации;
П в ряде приложений (линейная алгебра, быстрые преобразования Фурье,
моделирование в среде Simulink) реализована поддержка вычислений с
вещественными данными одинарной точности;
П появилась возможность обрабатывать целочисленные массивы большой
размерности за счет использования целочисленной арифметики;
П существенно изменен интерфейс среды MATLAB и некоторых сервисных
систем;
□ расширились возможности по управлению графическими окнами;
П исправлены замеченные ошибки.
Полный перечень нововведений и исправлений составляет документ
"MATLAB 7.0 Release Notes" объемом 274 с.
Пакет MATLAB 7 предъявляет повышенные требования к РС-совместимому
оборудованию и программному обеспечению:
П персональный компьютер на базе процессоров Pentium III, Pentium 4,
Pentium M, Xeon. AMD Athlon, Athlon XP, Athlon MP;
□ операционная система Microsoft Windows XP, Windows NT 4.0 (Service
Pack 5 или 6a) , Windows 2000 (Service Pack 3 или 4);
П CD-ROM для инсталляции с оптического диска;
П оперативная память не менее 256 Мбайт (рекомендуется 512 Мбайт);
□ размер дисковой памяти зависит от количества установленных
расширений и объема документации и формате PDF. Программа установки
информирует вас об объеме дисковой памяти, необходимой для включения
6
Глава 1
того или иного компонента пакета. В средней комплектации MATLAB
займет на винчестере порядка 1 Гбайт;
П монитор с поддержкой минимум 256 цветов, рекомендуется графический
адаптер (16, 24 или 32 битов), поддерживающий стандарт OpenGL.
В состав дополнительных рекомендаций входят:
□ операционная система должна поддерживать карту графического
ускорителя, принтер и звуковую карту;
П Microsoft Word (Office 2000) или Office ХР необходимы для
функционирования MATLAB Notebook;
□ протокол TCP/IP требуется на всех платформах для использования
лицензионного сервера.
Для генерации собственных тех-файлов понадобится один из следующих
трансляторов:
П Compaq Visual Fortran (версии 5.0, 6.1 или 6.5);
П Microsoft Visual C/C++ (версии 5.0, 6.0 или 7.0);
□ Borland C/C++ (версии 5.0 или 5.02);
□ Borland C++Builder (версии 3.0, 4.0, 5.0 или 6.0);
□ WATCOM (версии 10.6 или 11);
■П Lcc 2.4 (bundled with MATLAB).
Для чтения и/или печати online-документации потребуется Netscape
Navigator (версия 4.0 или выше) или Microsoft Internet Explorer (версия 4.0
или выше), Adobe Acrobat Reader (версия 3.0 или выше).
Одним из наиболее важных приложений пакета MATLAB является
проектирование, имитация и анализ различных динамических систем. До появления
первых цифровых вычислительных машин (ЦВМ) большинство задач,
связанных с созданием и исследованием различных систем автоматического
регулирования, решались на аналоговых вычислительных машинах (АВМ).
В основе АВМ лежали динамические аналогии между поведением
различных акустических, электрических и механических звеньев, описываемых
однотипными системами дифференциальных уравнений. АВМ представляли
собой набор электронных блоков (усилителей, сумматоров, умножителей,
интеграторов, задержек и различных нелинейностей), которые с помощью
коммутационной панели соединялись в схему, эквивалентную исследуемой
конструкции. А затем с помощью осциллографов и самописцев
фиксировалось и изучалось поведение напряжений и токов в различных узлах
электрической модели исследуемого объекта.
В середине 50—60-х годов прошлого столетия пользовались большой
популярностью настольные интефаторы типа ИПТ-5 и МПТ-9, относительно
небольшие лабораторные установки ЭМУ-8, ЭМУ-10 и такие гиганты, как
Краткий обзор
7
МН-8, занимавшие площади по 60—80 кв. м. Самой главной оценкой
мощности АВМ был максимальный порядок системы дифференциальных
уравнений, которую можно было собрать из имеющихся блоков. И колебался он
в диапазоне от 5—6 до 30—40. К основным недостаткам АВМ относились
большая трудоемкость в коммутации блоков, нестабильность их поведения
(дрейф нуля усилителей), относительно малая точность результатов и
затяжной характер исследования. Однажды собранная и отлаженная схема
коммутации блоков должна была сохраняться на протяжении времени исследования
данной системы. На более поздних АВМ появились сменные
коммутационные панели. Повышению эффективности моделирования содействовали
гибридные аналого-цифровые вычислительные системы (ГВС "Русалка").
Однако точность вычислений, обеспечиваемая аналоговыми компонентами,
оставляла желать лучшего.
Пакет Simulink, самый родной среди расширений системы MATLAB
(кнопка для его запуска вынесена па панель инструментов системы),
повторяет идею АВМ на самом современном уровне. Он использует богатую
библиотеку динамических звеньев с различными передаточными функциями,
располагает визуапьными средствами сборки эквивалентной модели,
обладает большим набором вычислительных алгоритмов, обеспечивает высокую
точность и качественное отображение характеристик изучаемых процессов.
Наибольшее количество отечественных публикаций посвящено именно
этому пакету [1, 2, 7, 8, 12, 14, 19, 20, 39]. На его базе построено довольно
много расширений системы MATLAB. Их наименования, как правило,
включают фирменную аббревиатуру Blockset, что можно трактовать как
набор блоков — моделей (файлы с расширением mdl), участвующих в
конструировании моделируемых систем.
Другие расширения MATLAB используют более распространенную
аббревиатуру Toolbox (дословно — ящик с инструментами). Как правило,
основными компонентами таких расширений являются средства решения
различных задач — математические методы, визуализация результатов вычислений.
Большая часть этих приложений представлена m-файлами — программами
на входном языке MATLAB.
Полный перечень дополнительных компонентов версии MATLAB 7
приведен в табл. 1.1. Некоторые из них являются автономными продуктами,
другие эксплуатируются в комбинации с определенным подмножеством
расширений. По номеру версии компонента можно судить как о его "возрасте",
так и об интенсивности его поддержки. Из приведенного перечня видно,
что старейшими приложениями системы MATLAB являются средства
обработки сигналов, моделирования управляющих систем, имитации различных
устройств в режиме реального времени. В первой колонке символом *
отмечены компоненты, подвергшиеся серьезной модификации. Новые
компоненты отмечены символами **.
8
Глава 1
Таблица 1.1
№
п/п
Компонент MATLAB Назначение
1*
2
3**
4
5*
6*
7
8
9
Simulink, ver 6,0
Aerospace Blockset,
ver 1.6
Bioinformatics
Toolbox, ver 1.1
CDMA Reference
Blockset, ver 1.1
Communications
Blockset, ver 3.0
Communications
Toolbox, ver 3.0
Control System
Toolbox, ver 6.0
Curve Fitting Toolbox,
ver 1.1.1
Data Acquisition
Toolbox, ver 2.5
10* Database Toolbox,
ver 3.0
11 Datafeed Toolbox,
ver 1.5
12 Dials & Gauges Block-
set, ver 1.2
13 Embedded Target
Infineon C166
Microcontrollers, ver 1.1
14 Embedded Target for
Motorola HC12,, ver 1.1
15* Embedded Target for
Motorola MPC555,
ver 2.0
Моделирование и анализ динамических систем
Моделирование летательных аппаратов, ракет и
двигательных установок (на базе Simulink)
Математические методы анализа
экспериментальных данных в биологии и генетике
Проектирование и моделирование беспроводных
коммуникационных систем в соответствии со
стандартом IS-95A (code division multiple access, CDMA)
Библиотеки функций для Communications Toolbox
(модуляция, кодирование, декодирование)
Разработка коммуникационных систем и их
моделирование в реальном масштабе времени
Моделирование, анализ и проектирование систем
автоматического регулирования с обратной связью
Обработка экспериментальных данных
(аппроксимация, сглаживание, интерполяция, экстраполяция)
Среда для поддержки измерительных комплексов,
подключенных к персональному компьютеру (ПК).
Организация обмена данными с аналоговыми и
цифровыми подсистемами, включая цифроанапо-
говые преобразования
Анализ и визуализация информации, хранящейся в
базе данных (БД). Отбор данных с использованием
запросов на языке SQL
Организация связи с серверами финансовых
данных
Библиотека графических примитивов для
формирования панелей управления с изображениями
различных шкал и измерительных приборов
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров С166
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров фирмы Motorola
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров фирмы Motorola
Краткий обзор
9
Таблица 1.1 (продолжение)
№
п/п
Компонент MATLAB Назначение
16 Embedded Target for
OSEC/VDX. ver1.1
17** Embedded Target for
Texas Instruments
C2000 DSP, ver 1.0
18* Embedded Target for
Texas Instruments
C6000DSP, ver 2.1
19 Excel Link, ver 2.2
20
21**
22*
23*
24
25
26
27**
Extended Symbolic
Math, ver 3.1
Filter Design HDL
Coder, ver 1.0
Filter Design Toolbox,
ver 3.0
Financial Derivatives
Toolbox, ver 3.0
Financial Time Series
Toolbox, ver 2.1
Financial Toolbox,
ver 2.4
Fixed-Income Toolbox,
ver 1.0.1
Fixed Point Toolbox,
ver 1.0
28 Fuzzy Logic Toolbox,
ver 2.1.3
29 GARCH Toolbox,
ver 2.0.1
30** Genetic Algorithm and
Direct Search Toolbox,
ver 1.0.1
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров OSEC/VDX
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров фирмы Texas Instruments
Проектирование и моделирование измерительно-
управляющих комплексов на базе
микроконтроллеров фирмы Texas Instruments
Организация взаимодействия между функциями
MATLAB и электронной таблицей Microsoft Excel
Расширенный пакет аналитических вычислений
HDL-кодирование в цифровых фильтрах
Проектирование, имитация и анализ цифровых
фильтров
Анализ и визуализация процентных ставок,
финансовых производных и рисков
Анализ данных финансовых рынков методом
временных рядов
Интегрированная среда для решения задач
управления финансами и графического представления
результатов анализа
Прогнозирование фиксированного дохода
Выполнение арифметических операций над
нестандартными форматами чисел (целочисленные,
длиной 1, 2, 4 байта; вещественные с одинарной
точностью)
Моделирование и анализ систем на базе аппарата
"нечеткой логики"
Анализ изменчивости на финансовых рынках с
использованием одномерных GARCH-моделей
(General Autoregressive Conditional Heteroscedasticity)
Генетический алгоритм и прямой поиск
10
Глава 1
Таблица 1.1 (продолжение)
№
п/п
Компонент MATLAB Назначение
31 Image Acquisition
Toolbox, ver 1.5
32 Image Processing
Toolbox, ver 3.2
33* Instrument Control
Toolbox, ver 2.9
34 LMI Control Toolbox,
ver 1.0.9
35 Link for Code
Composer Studio, ver 1.3.1
36** Link for ModelSim,
ver 1.1.1
37 MATLAB Builder for
COM, ver 1.1
38 MATLAB Builder for
Excel, ver 1.2
39* MATLAB Compiler,
ver 4.0
40* MATLAB Report
Generator, ver 2.0
41 MATLAB Web Server,
ver 1.2.3
42* Mapping Toolbox,
ver 2.0.2
43* Model Predictive
Control Toolbox, ver 2.0
44 Model-Based
Calibration Toolbox, ver 2.1
45 Mu-Analysis and
Synthesis Toolbox,
ver 3.0.8
46 Neural Network
Toolbox, ver 4.0.3
Организация обмена графическими данными
Обработка изображений (анализ, фильтрация,
двумерные преобразования, восстановление и т. п.)
Обмен данными и управляющими сигналами с
периферийными приборами в формате протоколов
IEEE-488, HPIB, VISA
Моделирование и анализ систем, описываемых
линейными матричными неравенствами (Linear
Matrix Inequality, LMI)
Организация связи между MATLAB и
интегрированной средой разработки (IDE) фирмы Texas
Instruments (Code Composer Studio, CCS)
Организация связи между MATLAB и средой
твердотельного моделирования ModelSim
Компилятор проектов MATLAB в СОМ-объекты
Конвертирование программ MATLAB в модули
Excel
Компилятор m-файлов в коды С, C++
Создание отчетов в различных форматах (RTF,
HTML, XML, SGML), включая специфику
представления данных и моделей
Сервис Web-сервера, позволяющий пользователям
Интернета выполнять на сервере MATLAB-приложения
Обработка и визуализация цифровых карт
местности
Анализ и управление сложными системами с
большим количеством входных и выходных данных
Проектирование эксперимента, статистическое
моделирование и калибровка сложных систем
Современные методы анализа и синтеза
устойчивых линейных систем управления высокого порядка
Применение искусственных нейронных сетей для
решения трудноформализуемых задач
Краткий обзор
11
Таблица 1.1 (продолжение)
№ Компонент MATLAB
п/п
Назначение
47** ОРС Toolbox, ver 1.0
48* Optimization Toolbox,
ver 3.0
49 Partial Differential
Equation Toolbox,
ver 1.0.5
50** RF Blockset, ver 1.0
51** RF Toolbox, ver 1.0
52 Real-Time Windows
Target, ver 2.5
53* Real-Time Workshop,
ver 6.0
54* Real-Time Workshop
Embedded Coder,
ver 4.0
55 Robust Control
Toolbox, ver 2.0.10
56* Signal Processing
Blockset, ver 6.0
57 Signal Processing
Toolbox, ver 6.0
58 SimMechanics, ver 2.2
59 SirnPowerSystems,
ver 3.1
60 Simulink Accelera-tor,
ver 6.0
61** Simulink Control
Design, ver 1.0
Поддержка промышленных стандартов для обмена
данными в системах реального времени (OLE for
Process Control, ОРС)
Поиск экстремумов функций многих переменных
при наличии ограничений, решение нелинейных
уравнений
Поиск и визуализация решений систем
дифференциальных уравнений в частных производных
Моделирование и исследование беспроводных
систем связи
Моделирование и исследование беспроводных
систем связи
Создание моделей с интерфейсом в стиле Simulink
и управление ими в режиме реального времени
Генерация программ в расширенном С-формате по
блочным диаграммам пакета Simulink
Оптимизация программ, изготовленных пакетом
Real-Time Workshop, по использованию памяти, по
скорости работы, по простоте интерфейса, по
удобочитаемости кода
Анализ и синтез систем управления, устойчивых по
отношению к случайным воздействиям (робастное
управление)
Библиотеки Simulink, предназначенные для
проектирования и моделирования систем цифровой
обработки сигналов. Прежнее название — DSP Block-
set (Digital Signal Processing, DSP)
Обработка цифровых и аналоговых сигналов
Моделирование твердотельных механических
систем на базе аппарата Simulink
Моделирование электрических силовых систем на
базе аппарата Simulink
Повышение производительности программ,
созданных в среде Simulink
Управление процессом построения моделей в
среде Simulink
12
Глава 1
Таблица 1.1 (окончание)
№ Компонент MATLAB
п/п
Назначение
62* Simulink Fixed Point,
ver 1.0
63** Simulink Parameter
Estimation, ver 1.0
64* Simulink Report
Generator, ver 2.0
65* Simulink Response
Optimization, ver 2.0
66** Simulink Verification
and Validation, ver 1.0
67 Spline Toolbox,
ver 3.2.1
68* Stateflow, ver 6.0
69* Stateflow Coder,
ver 6.0
70* Statistics Toolbox,
ver 5.0
71 Symbolic Math
Toolbox, ver 3.1
72* System Identification
Toolbox, ver 6.0.1
73* Virtual Reality Toolbox,
ver 4.0
74* Wavelet Toolbox,
ver 3.0
75 xPC Target, ver 2.5
76 xPC Target Embedded
Option, ver 2.5
Обеспечение расчетов с одинарной точностью в
среде Simulink (прежнее название Fixed-Point
Blockset)
Подбор параметров моделей в среде Simulink
Создание отчетов с включением данных и моделей
пакета Simulink
Проектирование, имитация и анализ систем
автоматического регулирования с нелинейными
ограничениями (прежнее название Nonlinear Control
Design Blockset)
Контроль за правильностью и допустимостью
моделей в среде Simulink
Библиотека процедур для сплайн-аппроксимации
плоских кривых и криволинейных поверхностей
Моделирование систем, управляемых событиями,
на базе теории конечных автоматов
Оптимизация программ, построенных на базе
моделей Stateflow
Набор методов вероятностного анализа и
визуализации результатов статистических исследований
Символьные вычисления на базе ядра пакета Maple
Идентификация систем (восстановление
математической модели) на основе анализа входных и
выходных сигналов
Создание трехмерных сцен виртуальной
реальности на базе языка VRML (Virtual Reality Modeling
Language)
Непрерывные и дискретные вейвлет-
преобразования для анализа и синтеза сигналов и
изображений различной природы
Моделирование и тестирование систем реального
времени в автономном режиме на целевом
компьютере или в связке с сервером
Глава 2
Пошаговые вычисления
в командном окне
2.1. Путешествие по среде MATLAB 7
По умолчанию после запуска пакета MATLAB 7 на экране появляется
комбинированное окно, включающее четыре наиболее важные панели —
Command Window (Окно команд), Command History (История команд). Workspace
(Рабочее пространство) и Current Directory (Текущий каталог). Две
последние панели закрывают друг друга, и для выдвижения нужной панели на
передний план следует щелкнуть по соответствующей вкладке. Три окна,
вписанные в главное окно системы (рис. 2.1), "поставлены на якоря". Они
передвигаются вместе с главным окном системы, вместе с ним изменяют
свои размеры, границы между окнами можно передвигать. Каждое из них
можно снять с якоря (кнопки Undock (Отстыковать) |QJ, размещенные в
правых верхних углах окон), и тогда оно может занимать автономную
позицию на экране'.
Вообще, самой используемой панелью является Command Window (Окно
команд). В ней набираются команды пользователя, подлежащие
немедленному исполнению. Здесь же выдаются результаты выполненных команд.
В командном окне можно обратиться за помощью по поводу того или иного
термина с помощью одной из команд — doc, help или lookfox.
Присутствие двух других окон во время сеанса работы только загромождает экран, и
их целесообразно закрыть (такого рода операции выполняются не только
кнопками, но и командами меню Desktop (Рабочий стол)).
Окно Workspace (Рабочее пространство) отображает текущий набор
переменных, заведенных пользователем в командном окне. Здесь можно увидеть
их имена (колонка Name (Имя)), значения скалярных переменных (колонка
Value (Значение)) и тип представляемых данных (колонка Class (Тип
данных)). Точно такую же информацию можно увидеть в командном окне
после исполнения команды whos. Поэтому постоянное присутствие окна
Workspace (Рабочее пространство) на экране вряд ли оправдано. В него
14
Глава 2
удобно заглядывать в тех случаях, когда вам понадобится откорректировать
значения элементов какого-либо массива с помощью Array Editor (Редактор
массивов). Это новый инструмент, появившийся в 7-й версии. Для его
вызова достаточно щелкнуть по имени переменной в поле Workspace (Рабочее
пространство).
-JfcMATLAB
File Edit Debug Desktop Window Help
■Shortcuts ijrj How to Add £j y^a'sNavy
Workspace |_) x
US-» V- ф 1 f* ' til - Sto*|:-.^jLl
Name '- 1 Value j Class
LD an: 1 double
EBc 0.87758 double
Els 0 47943 double
<1 1 M
Command History щx
,.- . 1 . - 11:
■s=sin(0.5>;
—c=cos(D.5) ;
■3*S+C*C
Ф Start 1
Command window
НПО
0*
» s=sinitl.5) ;
» c=cos (0-5);
» s*s+c*c
ans =
1
»
Рис. 2.1. Общий вид главного окна пакета MATLAB 7
Окно Command History (История команд) хранит все команды, набираемые
пользователем, однако в отличие от содержимого Command Window (Окно
команд) сюда не попадают сообщения системы и результаты вычислений.
Эта информация может оказаться полезной для формирования программы,
исполняемой в автоматическом режиме.
Совершим беглый экскурс по командам главного меню. Команды меню File
(Файл) (рис. 2.2) выполняют обычные функции для большинства систем
программирования. Первая группа команд обеспечивает переход в режим
ввода новой программы (New (Создать)) или извлечение из дискового файла
ранее сохраненной программы (Open (Открыть)). Команда Close Command
Window (Закрыть окно команд) дублирует соответствующую кнопку в
Command Window (Окно команд).
Команды второй группы позволяют сохранить значения всех переменных
рабочего пространства в дисковом файле (Save Workspace As (Сохранить
рабочее пространство как)) или импортировать ранее сохраненные данные
(Import Data (Импортировать данные)).
Пошаговые вычисления в командном окне
15
Flle'l
New
Open...
Close Command Window
Import Data,..
Save Workspace As..,
SetPeth...
Preferences...
Page Setup...
Prin^:...
flirj --.:-1(.-1:-...: .
1 C:\...p5\work\array2vec.m
2 H:\...AB7\work\untiaed.m
3 C:\MATLAB6p5\work\dlfF2.m
4 C;\MATLAB6D5\workl\test.m
ExitMATLAB
t
Ctrl+O
Ctrl+S
Orl+Q
Рис. 2.2. Команды меню File
Команда Set Path (Задать путь) позволяет пополнить список каталогов,
просматриваемых системой, или изменить порядок их просмотра.
Настройка параметров системы выполняется в окне Preferences (Предпочтения).
Четвертая группа команд — традиционная для большинства систем. Она
обеспечивает получение твердой копии с предварительной настройкой
параметров бумаги и принтера.
Под ними расположена часть меню со списком последних файлов, с
которыми работал пользователь. Размер этого списка регулируется, и его
основное назначение — ускорить выборку файлов, открывавшихся в
предыдущем сеансе.
Меню Edit (Правка) (рис. 2.3) содержит характерный для любого редактора
набор команд по вырезанию (Cut (Вырезать)), копированию (Сору
(Копировать)), вставке (Paste (Вставить)), Paste Special (Специальная
вставка)) и удалению (Delete (Удалить)) выделенных фрагментов текстов или
графических объектов. Команда Select All (Выделить все) выделяет
текстовый или графический объект целиком.
Команды Undo (Отменить) и Redo (Повторить) используются,
соответственно, для отмены только что совершенного действия или отказа от
предшествующей отмены.
С помощью команды Find (Найти) можно найти текстовый фрагмент и, при
необходимости, произвести его замену.
Последняя группа команд позволяет произвести очистку соответствующих
окон. Выполнение команд Clear Command Window (Очистить окно команд).
16
Глава 2
Clear Command History (Очистить окно истории команд) и Clear Workspace
(Очистить переменные рабочего пространства) по умолчанию
сопровождается запросом о подтверждении. Эти сообщения системы можно подавить,
устанавливая соответствующие параметры в окне Preferences
(Предпочтения).
Edit]
Undo
CJ_
Copy
Paste
Paste Special...
Select All
Delete.
Find...
Find Files... ■
Clear Command Window
Clear Command History
Clear Workspace
Ctrl+Z
Ctrl+vv
Alt+W
Ctrl+Y
Ctrl+D
-.. :
Рис. 2.3. Команды меню Edit
На командах меню Debug (Отладка) мы остановимся подробнее в разд. 4.9.
Из главного меню MATLAB 7 исчез привычный для пользователей
предыдущих версий набор команд меню View (Вид). Большинство из них
перекочевало в меню Desktop (Рабочий стол) — рис. 2.4.
Команда Undock Command Window (Снять с якоря окно команд) разъединяет
состыкованные окна и позволяет Command Window (Окно команд)
перемещаться самостоятельно.
Команда Desktop Layout (Разметка рабочего стола) определяет количество и
расположение одновременно видимых панелей среды. Вы можете выбрать
конфигурацию среды по умолчанию (Default), которая была приведена на
рис. 2.1, или сохранить на экране только окно команд (Command Window
Only). Команда History and Command Window (Окна истории и команд)
позволяет сохранить два окна — историю команд и окно команд. Команда All
Tabbed (Со вкладками) располагает на экране все окна (рис. 2.5).
При этом одно из окон находится на переднем плане, а любое из
оставшихся выходит на передний план после щелчка по соответствующей вкладке.
В MATLAB 7 появилась возможность сохранить ту или иную конфигурацию
окон на экране, воспользовавшись командой Save Layout (Сохранить
разметку). Файлы, в которых запоминались те или иные конфигурации, могут
Пошаговые вычисления в командном окне
17
иметь произвольные имена. Дпя выбора нужной конфигурации, т. е. одного
из ранее сохраненных файлов, необходимо прибегнуть к команде Organize
Layouts (Организовать разметку).
Desktop
* Undock Command Window
Desktop-Layout ►-
Save Layout...
Organize Layouts...
v Command Window
* Command History
* Current Directory
•• Workspace
Help.
Profiler
v Toolbar
* Shortcuts Toolbar
•'Titles
Default
Command Window. Only
History and Command Window
All Tabbed
Рис. 2.4. Команды меню Desktop
#JtMATLAB
File Edit Debug Desktop Window Help
0 & 1 Ъ Чй Oil «■■> '~Л 1 7? ^ ':? \ Current Director)»;. | KWIATLArWwork
1Command Window
НПО
djs
» s=sin(0.5) ;
» c=cos(0.5);
» s*s+c*c
ans =
1
»
Command Window 1 Command History | Current Directory | Workspace | Help | Profiler |
•Ф Start |
Рис. 2.5. Конфигурация всех окон с вкладками
Следующая группа команд (Command Window (Окно команд), Command
History (История команд), Current Dictionary (Текущий каталог), Workspace
(Рабочее пространство), Help (Справка), Profiler (Профайлер)) позволяет из
меню установить комбинацию окон, которые должны присутствовать на
экране. Включение или отмена галочки у соответствующей строки меню
управляет появлением или исчезновением того или иного окна.
18
Глава 2
Команды последней группы управляют видимостью панели инструментов
(Toolbar), заголовков окон (Titles). С помощью команды Shortcuts Toolbar
(Пользовательская панель) можно создавать пользовательские панели
инструментов.
На панель инструментов вынесены наиболее употребительные команды
главного меню (рис. 2.6). Только три из них дополняют главное меню.
Кнопка Simulink обеспечивает вызов самого популярного расширения
пакета MATLAB — системы имитационного моделирования. Кнопка GUIDE
вызывает конструктор интерфейса, с помощью которого в диалоговом режиме
формируется интерфейс приложения. В правой части панели расположены
две кнопки, обеспечивающие просмотр каталогов (Browse for Folder) и перс-
ход по каталогам на один уровень вверх (Go up one level).
Undo
Redo
■vt MATLAB
File Edit Debug i»e top Window Help
D e£' J
г
Ln
' 6
i- ш «•> ■■-
Lpaste
-Copy
Lent
- Open file
ewh
rt-Fi
e
| H ^ I '5* ' Current Directory | H:\MATLAB7\work jj J £]
l-Help Browse for folder -I
L-GUlDE Go up one level -I
- Simulink
Рис. 2.6. Кнопки быстрого запуска команд меню
На панель окна Workspace (Рабочее пространство) тоже вынесено несколько
кнопок (рис. 2.7), ускоряющих выполнение некоторых операций по
сохранению и восстановлению переменных рабочего пространства, по очистке
рабочего пространства и снятию окна с якоря.
Command Window (Окно команд) превращает MATLAB в великолепный
калькулятор практически с неограниченной памятью. Для того чтобы
многочисленные окна пакета не загромождали экран, можно выполнить
команду Desktop | Command Window Only (Рабочий стол | Только окно команд).
В левом верхнем углу командного окна находятся два знака »,
символизирующие начало текущей строки. В этой строке можно набирать формулы
или команды, удовлетворяющие синтаксису языка MATLAB и
завершающиеся нажатием клавиши <Enter>. Длинные команды, не помещающиеся
целиком в одной строке, можно продолжать в одной или нескольких еле-
Пошаговые вычисления в командном окне
19
дующих, используя условный знак переноса в виде трех подряд идущих
точек (...). Вслед за знаком переноса необходимо нажимать клавишу
<Enter>.
(— New variable
г- Open selection
Г
Delete
Workspace
i Й ® is # 'h | W, - '■ aadcfTrrr]
Lpnnt L i
-Print •- Plot selection
•— Save Undock Workspace ->
■ Load data file
Рис. 2.7. Панель кнопок в окне Workspace
Если все операнды формулы известны, то MATLAB вычисляет значение
выражения, помещая его в системную переменную с именем ans (от англ.
answer— ответ):
» 2*2
ans =
Если в выражении указан операнд, значение которого неизвестно, MATLAB
выдает сообщение об ошибке:
» (х--1)*(х+1)
??? Undefined function or variable 'x'.
Точка с запятой, завершающая набор командной строки, подавляет
автоматический режим вывода результата вычислений. Это позволяет производить
многошаговые вычисления, сохраняя промежуточные результаты в
соответствующих переменных:
» s=sin(0.5);
» c=cos(0.5);
» s.*s+c*c
ans =
1
Если формула для вычислений, располагаемая в правой части оператора
присваивания, достаточно длинная, то ее часть может быть перенесена на
следующую строку. Признаком завершения строки, у которой имеется про-
20
Глава 2
должсние в следующей строке, являются три подряд идущих точки. Все, что
располагается в этой же строке правее знака переноса, MATLAB 7
воспринимает как комментарий:
» x=sin{0.2)*cos(0.5)+ sin(0.5)*cos(0.2)...формула будет продолжена
+cos(0.2)*cos(0.5)-sin(0.2)*sin(0.5) £ продолжение предыдущей строки
х =
i.40'91
2.2. Переменные рабочего пространства
Значения всех промежуточных переменных, использованные в
многошаговых вычислениях, MATLAB запоминает в рабочем пространстве
(Workspace). На выбор имен переменных накладываются примерно такие же
ограничения, как и в других системах программирования:
П можно использовать латинские буквы, цифры и символ подчеркивания;
П большие и малые буквы в именах различаются;
П имя должно начинаться с буквы;
П длина имени не должна превышать 63 символов.
Информацию о переменных рабочего пространства можно получить, набрав
команду who или whos. Первая из них выводит только список имен
переменных, а вторая сообщает более подробную информацию об именах
переменных (Name), их размерности (size), количестве занятых байтов в
оперативной памяти (Bytes) и Классе обьсктов. представляющих
соответствующий тип данных (class):
» whos
Name- Size Bytes Class
ans lxl 8 double array
с lxl 8 double array
s lxl 8 double array
Grand total is 3 elements using 24 bytes
Детали этой информации будут рассмотрены немного позже. Если мы
собираемся продолжить сеанс общения с MATLAB в другой раз, то имена и
значения переменных рабочего пространства можно запомнить в файле,
прибегнув к услугам команды главного меню File | Save Workspace As (Файл |
Сохранить рабочее пространство как) либо набрав аналогичную команду в
текущей строке:
» save qq
Пошаговые вычисления в командном окне
21
MATLAB добавит к имени нашего файла расширение mat и запомнит все
переменные и их значения в файле qq.mat. В начале следующего сеанса
достаточно выполнить команду load:
»load qq
За время сеанса в рабочем пространстве может оказаться довольно много
уже использованных переменных. Они занимают оперативную память и
замедляют работу системы. Поэтому время от времени рабочее пространство
стоит чистить, либо удаляя все переменные, либо только те, которые в
дальнейшем не понадобятся.
Команда clear без параметров удаляет все переменные рабочего
пространства, не задавая никаких вопросов. Однако, будучи набрана с указанием
списка имен, удаляет из рабочего пространства только заданные
переменные (пример 2.1).
; Пример 2.1. Команда clear * , *•-, ■ * -* -, 'у^ > ■» ш \ v„j
» х=1;
» у=2;
» z=3;
» whos
Name Size Bytes Class
x 1x1 8 double array
у lxl 8 double array
z lxl 8 double array
Grand total is 3 elements using 24 bytes
>> clear x у
» whos
Name Size Bytes Class
z lxl 8 double array
Grand total is 1 elements using 8 bytes
При выполнении команды clear возможна ошибка, не замечаемая
системой, — если список имен удаляемых переменных задан через запятые, то
будет удалена только первая переменная списка (пример 2.2). Содержимое
остальных переменных списка будет отображено, если список не
заканчивается точкой с запятой.
! Пример 2.2 Команда clear (продолжение) ^ ■^pt-'-^fh-^ ^"i" V0&* *..~vj
■» х=1;
i
■» y=2;
22
Глава 2
» z=3;
» clear x,y, z
У =
whps
Name
У
z
Size
lxl
lxl
Bytes Class
8 double array
8 double array
Grand total is 2 elements using 16 bytes
Полную очистку рабочего пространства можно выполнить и командой Clear
Workspace (Очистить рабочее пространство) из меню Edit (Правка). Правда,
в этом случае система потребует подтвердить запрос на удаление (рис. 2.8).
•^MATLAB Q
/|\ Are ypu sure you want to clear your workspace?
No I
Yes
Рис. 2.8. Запрос подтверждения
на очистку рабочего пространства
2.3. Скаляры или массивы?
Индексированные переменные
Своим названием пакет MATLAB обязан сокращению от английского
названия Matrix Laboratory — дословно "матричная лаборатория". Поэтому
можно догадаться, что основным видом данных, которые используются в
пакете, являются матрицы. Даже общепринятые скалярные переменные
MATLAB рассматривает как матрицы размерности lxl1. До поры до
времени на скалярных переменных пользователь эту специфику не чувствует, т. к.
1 Традиционно в математической литературе обозначение 1x1 (или, в общем случае,
тхп) соответствует размеру матрицы, а размерность при этом равна 2. Однако в этом
издании указанное обозначение трактуется в понимании авторов. — Ред.
Пошаговые вычисления в командном окне
23
для единственного элемента массива размерности 1x1 указывать индексы не
обязательно:
» х=2
.х =
2
Однако никто не мешает обратиться к единственному элементу массива с
двумя и даже с одним индексом, задавая его в круглых скобках:
» х(1,1)
ans =
2
» х(1)
.ans =
2
Последнее требует объяснения. Дело в том, что вместо обычных индексов,
принятых в математике и апгоритмйческих языках, в компиляторах
используют так называемые приведенные индексы, определяющие позицию
соответствующего элемента массива в оперативной памяти. Так как- оперативная
память использует линейную адресацию своих ячеек, то для одномерного
массива приведенный индекс совпадает с обычным. Для двумерного
массива а с количеством элементов mxn (т — число строк, п — число столбцов)
приведенный индекс к элемента Ai#j зависит от способа распределения
элементов в памяти. MATLAB по аналогии с Fortran использует отсчет
индексов в массивах от 1 и располагает элементы матрицы по столбцам. Поэтому
элементу a-i,j в памяти предшествуют (j-1) столбцов по m элементов в
каждом, и этот элемент расположен на месте с номером k=(j-i) *m+i. MATLAB,
наряду с традиционными индексами в многомерных массивах, позволяет
пользоваться и единственным приведенным индексом, что несколько
повышает скорость вычислений.
Попытка обратиться к несуществующему элементу массива приведет к
выдаче сообщения об ошибке:
» х(2)
?'?? Index exceeds matrix dimensions .
Векторы и матрицы в MATLAB могут быть не только числовыми, но и
символьными (пример 2.3). Однако при формировании строковых матриц
следует задавать значения равной длины для всех элементов массива, дополняя
при этом более короткие строки недостающими пробелами в конце.
2 Зак. SW
24
• Глава 2
; Пример 2.3. Символьные векторы и матрицы. .'$? ?у. -4¾¾¾ J; .• -.,/-^1^1¾¾¾
» а=[ 'abcdefghijk'; 'ABCDEFGHIJK' ,-42345678904
??? Error using ==> vertcat
All tows, in the bracketed expression must have the same
number of columns.
» a=['abcdefghijk'; 'ABCDEFGHIJK'; "1234567890 ']
a =
abcdefghijk
ABCDEFGHIJK
1234567S90
» whos
Name Size Bytes Class
a 3x11 66 char array
Grand total is 33 elements using 66 bytes
Попытка разделить строковые значения пробелами или запятыми приведет
к конкатенации этих строк, т. е. к созданию символьного вектора-строки:
» b=['ABCDEF" '12345']
b =
ABCDEF12345
» whos
Name Size Bytes Class
b lxll 22 char array
Grand total is 11 elements using 22 bytes
Как и в других алгоритмических языках, в MATLAB допускается
существование пустых массивов, не содержащих ни одного элемента (пример 2.4).
! Пример 2.4. Задание пустых массивов • .'.. V \j&.K- ~v? ^
■ Г. !Г. " .'.„.'..■.■....л.-...-.'::-..-..-.-:,..-:;...-..: ::.-;.„^,;;.яйЕ,...,...;....:..ла. ;..;:.:;
» а=[]
а =
[]
» b=ehar([])
Ь =
1 1
» c=uint8([])
с =
[]
Пошаговые вычисления в командном окне
25
> whos
Name
а.
Ь
с
Size
0x0
0x0
0x0
Bytes
0
0
0
Class
double array
char array
uint8 array
Grand total is 0 elements using 0 bytes
Пустыми массивами считаются и такие, у которых максимальное значение
любого индекса равно нулю.
2.4. Выбор формата отображения
числовых данных
Числовые данные, с которыми оперирует MATLAB на IBM-совместимом
ПК, в памяти компьютера представлены вещественными или
комплексными значениями в формате double. Это означает, что каждое вещественное
число занимает 8 байтов в оперативной памяти и принимает по модулю
значения из диапазона |10~308, 10+308]. Количество значащих десятичных
цифр при этом достигает 16—17. Комплексное число, представленное
действительной и мнимой частями в таком же формате, занимает,
соответственно, 16 байтов. Именно с такой точностью MATLAB выполняет все
вычисления. Однако при отображении числовых результатов на дисплее часть
значащих цифр отбрасывается в соответствии с установленным форматом
вывода.
Обычно числа выводятся с небольшим количеством значащих цифр. Целые —
не более чем с 9 цифрами, вещественные с фиксированной запятой — не
более чем с 4 цифрами в дробной части, очень большие или очень
маленькие числа — в формате с плавающей запятой и пятью значащими цифрами.
Отображаемые значения округляются по общепринятым в математике
правилам (табл. 2.1).
Таблица 2.1
Пример отображения
числа
» .4=123456789
х =
; 123456789
| » х=1234567890
! х =
! 1.2346е+009
Пример отображения
числа
» х=10/б
х =
1.6667
» х=100/6
х =
16.6667
Пример отображения
числа
» х=1/100.0 ;
х =
0.0010
» х=1/10000
х =
1.0000е-004
26
Глава 2
Таблица 2.1 (окончание)
Пример отображения
числа
» х=1/60
X =
; 0.0167
» Х = 1/б
; X =
1 0.1667
1 Пример отображения
1 числа
; » х-1000/6
1 х =
; 166.6667
| » х=10000/6
: х =
I 1.6667е+003
j Пример отображения
1 числа
I » к=123.456789
j х =
'; 123.4568
1 » .4=1234.5678 9
1 х =
I 1.2346е+003
По умолчанию система использует формат, обозначаемый служебным
словом short (укороченный)- Однако формат вывода числовых данных может
быть и другим (табл. 2.2).
Таблица 2.2
Пример отображения числа
» format short
; » x=sqrt(2)
х =
j 1.4142
г » format long
j » X
j X =
j 1.41421356237310
» format rational
» X
: X =
i ..393/985
i Пример отображения числа
| » format short e ;
j » x j
: X = |
j 1.4142e+000 j
j » format long e j
j » X j
I x = !
j 1.414213S6237309Se+000 j
В табл. 2.2 использованы основные форматы вывода числовых данных с
фиксированной и плавающей запятой. Последний формат позволяет
отображать числовые значения в виде подходящих рациональных дробей с
минимально возможными числителями и знаменателями. Следует заметить,
что значение переменной х не зависит от установленного формата вывода.
Формат вывода результатов вычислений может быть установлен как
программным путем (именно это и продемонстрировано в табл. 2.2), так и с
помощью изменения параметров Command Window (Окно команд). Для
этого следует войти в меню File (Файл), выбрать команду Preferences (Пред-
Пошаговые вычисления в командном окне
27
почтения) и в раскрывшемся диалоговом окне выделить пункт Command
Window (Окно команд) — рис. 2.9.
tjk Preferences
EGeneral
l+l-Fonts
— Colors
■—Keyboard & Indenting
|—Command History
rT~Edilor/Debugger
■ Help
-Web
Current Directory
—Workspace
Array Editor
GUIDE
Г+Vfigure Copy Template
Command Window Preferences
Text display ■■ ■*■ ■
Numeric format: | short T |
Numeric display:
Display —; ~
Г" Wrap lines
П Llmi matrix cS:
Number or lines i bank
long
short e
longe
short g
longg -
hex
rational
eighty columns
ndow scroll buffer: | 5 OOQ-H
Accessibility
P Arrow keys navigate Instead of recalling history
OK
Cancel Apply
Help
Рис. 2.9. Выбор формата для вывода числовых данных в командном окне
Форматы short g и long g представляют собой гибрид между
соответствующими форматами вывода с фиксированной и плавающей запятой. В
зависимости от отображаемого значения они выбирают то или иное
представление числа (пример 2.5).
[Пример 2.5. ФорЙат short -."
Т^-
'":"?l'gS№""?V!-!
» format short g
» x=sqrt(2)
x =
1.4142
» x=sqrt(2000000)
x =
1414.2
28
Глава 2
» x=sqrt(2е+20)
х =
1. .1.1.426-1 010
Формат bank позволяет оперировать с финансами, сохраняя в дробной части
числа два знака, соответствующие мелким денежным единицам:
» format bank
» х=1000
х =
1000.00
Формат + обеспечивает вывод только знаков чисел, сами значения при этом
не выводятся:
» format +
» х=[-1 2 -3 4 -5];
» х
X =
Формат hex обеспечивает вывод числовых данных в шестнадцатеричном
формате:
» format hex
» х=1
X =
3fi0000000000000
Согласитесь, что наблюдать вещественные данные в шестнадцатеричном
формате во многих случаях смысла не имеет. Эта система счисления хороша
только для целочисленных форматов компьютерных чисел.
В языке MATLAB существуют и другие возможности по изменению
формата выводимых данных. Они построены на базе функции sprintf, хорошо
известной программистам по языку С. С этими возможностями мы
познакомимся позже.
Для выделения результата вычислений или значения переменной MATLAB
вставляет пустую строку перед выводимым значением. В приводившихся
выше примерах с целью экономии места эта пустая строка удалялась
вручную. Однако ее отсутствие в командном окне тоже может оказаться
полезным, т. к. позволит разместить на экране большее количество
результативных строк. Такой режим вывода обеспечивается установкой параметра
Numeric display = compact в соответствующем раскрывающемся списке
окна Preferences (Предпочтения) в разделе Command Windows (Окно команд) —
см. рис. 2.9. Возврат в режим разреженного вывода происходит после
установки Numeric display = loose.
Пошаговые вычисления в командном окне
29
2.5. Арифметические выражения
Основу большинства расчетов составляют вычисления значений
арифметических выражений, в которых в качестве операндов могут выступать константы,
переменные, стандартные и нестандартные функции. Специфика MATLAB
заключается в том, что, в отличие от большинства алгоритмических языков,
здесь допускается использование операндов-массивов. А это означает, что в
результате вычисления выражения может получиться некоторое множество
значений — вектор, матрица или массив большей размерности.
2.5.1. Некоторые свойства
вещественных данных
В отличие от большинства алгоритмических языков, MATLAB довольно
спокойно реагирует на переполнение разрядной сетки. Он выдает
предупреждение, например, о делении на 0, но предлагает в качестве результата
внутреннее представление самого большого (inf = 1.8е+зо&) или самого
маленького (-inf = -i.8e+308) вещественного числа, допустимого в
формате double:
» х=1/0
Warning: Divide by zero.
x =
Inf
» y=-l/0
Warning: Divide by zero.
У =
-Inf
Когда вычисление степенной функции, например, экспоненты, приводит к
переполнению, то в качестве результата возвращается "машинная
бесконечность", но сообщение о переполнении уже не выдается:
» w=exp(710)
w =
Inf
А в тех случаях, когда математический результат не определен, например,
при делении 0 на 0, в соответствующую переменную засылается
специальный признак NaN (от англ. Not a Number— "не число"):
» z=0/0
Warning: Divide by zero.
z =
NaN
30
Глава 2
Дальнейшее использование неопределенного операнда в последующих
вычислениях будет приводить также к неопределенному результату:
» x=z+l
NaN
Среди полезных системных числовых переменных и констант отметим
(пример 2.6):
□ eps — относительную погрешность при вычислениях с плавающей
запятой;
П reaimax — наибольшее положительное число с плавающей запятой;
П reaimin — наименьшее положительное число с плавающей запятой;
П pi — число %.
I Пример 2.6. Отображение значений системных переменных и констант "\
» eps
ans =
2.220446049250313е-01б
» reaimin
arts =
2 .225073858507201е-308
>> reaimax
ans =
1.7976.93134862316e+308
» pi
ans =
3.14159265358979
Изменение системной переменной eps оказывает влияние на точность
вычисления значений некоторых математических функций. Однако другие
функции на эту переменную не реагируют и продолжают вычисления с
минимально допустимой погрешностью.
2.5.2. Специфика использования
комплексных величин
Запись комплексных величин, используемых в формулах, напоминает
общепринятые математические стандарты.
Пошаговые вычисления в командном окне
31
Мнимые части комплексных чисел сопровождаются либо буквой i, либо
буквой j:
» х=1.5-0.51
х =
1.5000 - O.SOOOi
» y=1.5-0.5j
У =
1.5000 - 0.5000i
Если "переменным" i или j не присвоены какие-либо значения, то их
можно применять для формирования комплексных данных, используя знак
умножения и располагая такой "сомножитель" до или после мнимой части:
» а=1;
» x=i*а
х =
0 + l.OOOOi
» y=(i) *а;
» У
У =
О + l.OOOOi
» z=a*i
z =
0 + l.OOOOi
Однако если i или j представляют настоящие переменные, которым уже
присвоены какие-либо значения, то их использование в подобных
выражениях не приводит к появлению комплексных данных:
» i=l
i =
1
» x=i*a
х —
1
Когда полные комплексные числа используются в операциях умножения,
деления или возведения в степень, то для устранения неоднозначности их
заключают в круглые скобки:
» z=(1.5-0.5i)*(2.5+0..8'j)
.? =
4.1500 - O.OSOOi
32
Глава 2
С помощью стандартных функций real и imag можно выделить
вещественную и мнимую части комплексного значения:
» real(z)
ans- =
4.1500
» imag(z)
ans =
-0.0500
Функция complex позволяет сконструировать комплексное значение по паре
вещественных чисел:
» complex(1,-1)
ans =
1.0000 - l.'OOOOi
Функцией conj можно воспользоваться для получения комплексного
сопряженного числа:
» conj(z)
ans =
4.1500 + 0.05001
Такого же результата можно добиться, располагая апостроф вслед за
комплексным значением:
» x=4.15+0.05i'
х =
4.1500 - 0..05001
» у=х'
У =
4.1500" + 0.05001
Математики довольно часто используют и другие формы представления
комплексных чисел:
z = х + i ■ у = р • е1ч> = р (cos ф + i • зin (р).
Здесь р — модуль комплексного числа (р2 = хг+у2), а ф — угол наклона
радиус-вектора, проведенного из начала координат в точку (х,у)- Значения этих
параметров можно определить с помощью стандартных функций abs и
angle (величина угла выдается в радианах).
Над комплексными данными определены все арифметические операции —
сложение, вычитание, умножение, деление, возведение в степень.
Комплексные операнды и выражения могут выступать в качестве аргументов
стандартных функций. Одним словом, в пакете MATLAB реализовано все, с
чем нас знакомили в курсе "Теория функций комплексных переменных".
Пошаговые вычисления в командном окне
33
2.5.3. Числовые матрицы и векторы,
специфика представления
Решение систем линейных алгебраических уравнений — одна из
математических задач, в которой мы встречаемся с векторами и квадратными матрицами:
aiiXi + ai2x2 + апх-з = Ьх;
ajiX]. + а»;Хг + агзХз = Ьг; (2.1)
a^LXi + азгХз + а3зх3 = Ь3.
Если обозначить матрицу коэффициентов через а, вектор-столбец
неизвестных — через х, а вектор-столбец правых частей — через в, то система (2.1) в
векторной форме имеет вид:
а*х = в. (2.2)
В матричной же форме решение системы (2.2) получается умножением
обеих частей равенства на обратную матрицу а"1:
х = а_1*в. (2.3)
Для задания значений компонентов вектора-строки (т. е. элементов
матрицы размерности 1хл) используются квадратные скобки, в которых числовые
данные отделяются друг от друга пробелами или запятыми:
» у=[1 2 3]
У =
12 3
» у=[<5,5,6]
У =
4 5 6
»
Количество пробелов, которое MATLAB вставляет при выводе компонент
вектора-строки, регулируется параметром Tab size (Табуляция) (см. окно
Preferences | Command Window | Keyboard & Indenting (Предпочтения | Окно
команд | Клавиатура и Отступы)). По умолчанию оно равно 4.
Для задания значений компонентов вектора-столбца (т. е. элементов
матрицы размерности лх1) используется тот же прием, но в качестве разделителей
данных выступают точки с запятыми:
» Ь=[1; 4; 2]
Ь =
1
4
2
34
Глава 2
Комбинируя оба варианта разделителей, можно сформировать двумерный
массив коэффициентов:
» а=[1 -1 1; 2 0 2; 0 1 Д.]
а =
1-11
2 0 2
0 11
Формула (2.3) позволяет найти решение системы, написав всего одну
строку, воспользовавшись стандартной функцией обращения квадратной
матрицы (пример 2.7).
| Пример 2.7.Решение системы линейных уравнений; « "~ .-■ '■•-'■"-",..". ■» ■" *?*...[
» x=inv(a)
х =
1
1
1
» whos
"Name
а
b
X
*Ь
Size
З.чЗ
3x1
3x1
Bytes
72.
■24
?4
Class
double
double
double
array
array
array
Grand total is 15 elements using 120 bytes
Как и в других алгоритмических языках, к элементам матриц и векторов
обращаются, используя индексы. В отличие от языка С, в системе MATLAB
индексы отсчитываются от 1 и заключаются в круглые скобки — х(1),
а{2,3). Довольно интересной особенностью языка MATLAB является
возможность выполнения однотипных операций над подмножеством
компонентов векторов или матриц. Для этого вместо индекса указывается
диапазон индексов, разделяемых двоеточием:
» z(2:5)=3
MATLAB предлагает разнообразные средства для создания типовых матриц.
Функции zeros и ones используются для заполнения квадратных или
прямоугольных матриц нулями или единицами соответственно. С помощью
Пошаговые вычисления в командном окне
35
функции eye формируется единичная квадратная или прямоугольная
матрица. Заполнение элементов матриц случайными числами с равномерным или
нормальным распределением обеспечивают функции rand и randn. В состав
пакета входят и специализированные функции, позволяющие создавать
магические квадраты и матрицы, названные именами известных математиков —
Адамара, Гильберта, Паскаля, Уилкинсона, Ханкеля. Пример 2.8
демонстрирует несколько простейших вариантов заполнения матриц.
! Пример! 2v8l Формирование
» a=zeros(5)
а =
6 0
0 0
0 0
0 0
0 0
» b=zeros.(3,
Ь =
0 0
0 0
0 с
» c=ones([2
с =
1 1
1 1
» d=eye(4)
d =
1 0
0 1
0 0
0 0
» e=ra.nd (4)
е —
0.9501
0.2311
0.6068
0.4860
» f=randn(4)
4)
3])
0.
0.
0
0
0
0
0
0
0
0
0
0
1
д.
0
0
1
0
8913
7621
4565
0185
0
0
0
0
0
0
0
0
0
0
0
1
0
■О
0
0
ТИПОВЫХ Mi
0
0
0
0
0
8214 0
4447 0
6154 0
7919 0
атриц
9218
7382
1763
4 057
36
Глава 2
-0.4326
-1.6656
0.1253
0.2877
-1.1465
1.1909
1.1892
-0.0376
0.3273
0.1746
-0.1867
0.7258
-0.5883
2.1832
-0.1364
0.1139
Ранее сформированные массивы могут участвовать в конструировании
новых массивов в качестве их клеток (пример 2.9).
Пример 2.9. Объединение матриц по вертикали
^ш*шт
» g=[e;f]
Я =
0.9501
0.2311
0.6068
0.4860
-0.4326
-1.6656
0.1253
0.2877
0.8913-
0.7621
0.4565
0.0185
-1.1465
1.1909
1.1892
-0.0376
0.8214
0.4447
0.6154
0.7919
0.3273
0.1746
-0.1867
0.7258
0.9218
0.7382
0.1763
0.4057
-0.5883
2.1832
-0.1364
0.1139
Еше больше возможностей по формированию блочно-диагональных матриц
предоставляет функция bikdiag.
В отличие от большинства систем программирования на базе других
алгоритмических языков, MATLAB хранит матрицы в оперативной памяти по
столбцам. Такой способ в свое время использовали все трансляторы с языка
Fortran.
Очень важной особенностью практически всех функций MATLAB является
возможность обработки аргументов, заданных векторами (пример 2.10).
А значения компонентов вектора, образованные но закону арифметической
прогрессии, формируются примерно так же, как и параметры цикла типа
for (начальное значение: шаг: конечное значение).
Пример 2.10. Использование векторных аргументов
» х=[0:0.2:1]
х =
0 0.2000
» y=sin<x)
0.4000
0.6000
0.8000
1.0000
Пошаговые вычисления в командном окне
37
О 0.1987 0.3894 0.5646 0.7174 0.8415
Такого рода приемы часто используются при подготовке табличных
значений функций, необходимых для построения графиков.
2.5.4. Специфика выполнения арифметических
и логических операций
При составлении алгебраических выражений MATLAB разрешает
использование традиционных знаков арифметических операций и символов
специальных операций, список которых приведен в табл. 2.3.
Таблица 2.3
Символы Выполняемое действие
Операции над числовыми величинами
+ Покомпонентное сложение числовых массивов
одинаковой размерности;
добавление скалярной величины к каждому элементу массива
Операции над числовыми величинами
Покомпонентное вычитание числовых массивов одинаковой размерности;
вычитание скалярной величины из каждого элемента массива
* Умножение матриц в соответствии с правилами линейной алгебры
(число столбцов первого сомножителя должно быть равно числу строк
второго сомножителя);
умножение всех компонентов массива на скаляр
- * Покомпонентное умножение элементов массивов одинаковой размерности
/ Деление скаляра на скаляр;
покомпонентное деление всех элементов массива на скаляр:
А/В = А*В'1 = А * inv<B)
(а, в — квадратные матрицы одного порядка)
• / Покомпонентное деление элементов массивов одинаковой размерности
\ " А\в = А"'*в —левое матричное деление (а—квадратная матрица)
А А. \в — покомпонентное деление элементов в на а (левое поэлементное
деление)
" Возведение скаляра в любую степень;
вычисление целой степени квадратной матрицы
' Вычисление сопряженной матрицы
- ' Транспонирование матрицы
38
Глава 2
Таблица 2.3 (окончание)
Символы Выполняемое действие
Логические операции
б Логическое умножение скаляров;
логическое покомпонентное умножение массивов
одинаковой размерности;
логическое умножение массива на скаляр
I Логическое сложение скаляров;
логическое покомпонентное сложение массивов одинаковой размерности;
логическое сложение массива со скаляром
Логическое отрицание скаляра или всех элементов массива
Операции отношения
Проверка на равенство
~= Проверка на неравенство
> Проверка на "больше"
>= Проверка на "больше или равно"
< Проверка на "меньше"
<= Проверка на "меньше или равно"
Но даже такие традиционные операции, как сложение, в выражениях MATLAB
выполняются особым способом. Самым привычным является сложение
скалярных величин (т. е. массивов размерности 1x1), соответствующее
аналогичному действию в большинстве алгоритмических языков. Если обоими
операндами являются массивы одинаковой размерности, то осуществляется
покомпонентное сложение элементов с одинаковыми индексами. Такой
подход в свое время применялся в ранних версиях Basic, включавшего
операторы типа мат а=в+с. Однако если в MATLAB к массиву любой
размерности добавляется скалярная величина, то она добавляется к каждому
элементу массива. По сути дела, добавляемое скалярное значение преобразуется в
массив такой же размерности, что и первое слагаемое (аналог приведения
типов в выражениях с разнокалиберными операндами), и каждый элемент
расширенного массива равен этому значению. Попытку сложить массивы
разной размерности (за исключением случая, когда один из операндов —
массив 1x1) система пресекает с выдачей соответствующего сообщения об
ошибке.
Аналогичное приведение типов выполняется для большинства операций,
когда одним из операндов является массив, а вторым — скаляр.
Пошаговые вычисления в командном окне
39
Впервые знак операции возведения в степень в виде х**у появился в Fortran
(1954 г.)- Вертикальная стрелка Т как знак возведения в степень был
предложен спустя несколько лет в проекте языка Algol 58. Символ Л для этой же
цели взял на вооружение Basic, откуда он и перекочевал в MATLAB. К
сожалению, ни С, ни Pascal не включили аналогичную операцию в набор
элементарных действий (здесь приходится прибегать к услугам библиотечной
функции pow).
Кроме знаков логических операций, приведенных в табл. 2.3, можно
использовать системные функции and(x,у), ог(х,у), хог(х,у) И not(x). При
выполнении логических операций над числами действует соглашение,
принятое в С, — ненулевые значения рассматриваются как истина, а нулевые
как ложь. Если операндами логической формулы являются массивы, то
операция производится над элементами с одинаковыми индексами. Результатом
такой операции является массив такой же размерности, что и операнды,
заполненный нулями и единицами в зависимости от исхода поэлементного
действия.
Аналогичный результат формируется при сравнении матричных операндов
(пример 2.1J).
! Пример 2.11, Сравнение, матричных отера^
» a=[I 2 3; 4 5 6]
а =
12 3
4 5 6
» Ь=[2 2 2; 5 5 5]
b =
2 2 2
5 5 5
i» с=а >=b
с =
Oil
Oil
2.5.5. Использование элементарных
математических функций
В ряде приводившихся выше примеров мы использовапи элементарные
математические функции типа sin(x), cos(x), sqrt(x) и др. В этом разделе
систематизированы библиотечные функции (табл. 2.4), которые доступны
пользователю MATLAB. Обозначения многих функций MATLAB совпадают
40
Глава 2
с названиями аналогичных функций в других атгоритмических языках,
поэтому их назначение в особых комментариях не нуждается. Однако еще раз
напомним, что аргументом большинства математических функций могут
быть комплексные данные и числовые массивы.
Таблица 2.4
Категория функций
Наименования функций
Тригонометрические, аргумент
в радианах
Тригонометрические, аргумент
в градусах
Обратные тригонометрические,
результат в радианах
Обратные тригонометрические,
результат в градусах
Гиперболические
Обратные гиперболические
Степени, логарифмы, корни
Округления
Наибольший общий делитель
Наименьшее общее кратное
Модуль числа
Знак числа
Остаток от деления с учетом знака
делимого
Остаток от деления
Разложение числа на простые
множители
Вычисление факториала
Дробно-рациональная
аппроксимация вещественного числа
Генерация простых чисел,
не превосходящих аргумента
cos, cot, csc, sec, sin, tan
cos.d, cotd, cscd, seed, sind, tand
acos, acot, acsc, asec, asin, atan, atan2
acosd, acotd, acscd, asecd, asind, atand
cosh, coth, csch, seen, sinh, tanh
acosh, acoth, acsch, asech, asin'n, atanh
exp, expml, log, loglp, log2, log.1.0,
nextpow2, pow2, feallog, realsqrt, sqrt
ceil, fix, floor, round
gcd
lem
abs
sign
mod
rem
factor
factorial
rats
primes
В некотором уточнении нуждаются функции округления, их немного
больше, чем в С. Функция round, отсутствующая в С (но существующая в
Пошаговые вычисления в командном окне
41
Pascal), производит округление по математическим правилам. О функции
ceil говорят, что она округляет в сторону +~ (точнее, до ближайшего
большего числа). В отличие от нее, функция floor округляет в сторону -«
(точнее, до ближайшего меньшего числа). Функция fix просто
отбрасывает дробную часть. Результаты работы функций округления приведены в
табл. 2.5.
Таблица 2.5
i Результат работы
I функции
| ceil(l.l) = 2
; ceil(-l.l) = -1
; fix(l.l) = 1
| fix(-1.1) = -1
| floor(1.1) = 1
1 floor(-1.1) = -2
| round(l.l) = 1
( round(-1.1) = -1
j Результат работы
i функции
! ceil(l.S) = 2
| ceil(-1.5) =■ -1
| fix(1.5) = 1
; fix(-1.5) = -1
j floor(1.5) = 1
! floor(-1.5) ■■ 2
! round(1.5) = 2
| round(-1.5) = -2
j Результат работы
! функции
j ceil(1.8) = 2 !
| ceil(-1.8) = -1 j
j fix(1.8) = 1 j
j fix(-1.8) = -1 |
| floor(1.8) = 1 j
| floor(-l.B) = -2 j
j round (1.8) = 2 j
| round (-1.8) = -2 j
Для функций gcd (от англ. greatest common divisor — наибольший общий
делитель) и icm (от англ. least common multiple — наименьшее общее кратное)
приведем очевидные результаты их работы:
gcd(100,25) = 25
Icm (100,25) = 100
Функции, вычисляющие остаток от деления, обычно применяются к целым
числам (хотя и представленным в формате double). Результаты их работы
проще понять на примерах, приведенных в табл. 2.6.
Таблица 2.6
I Результат ра- I Результат работы i Результат работы 1 Результат работы
: боты функции I функции I функции j функции
!mod(7,5)=2 | mod (-7,5) = 3 !mpd(7,-5) =-3 I mod (-7,-5) =-2 !
у i | i -i
! rem(7,5)= 2 j rem(-7,5) = -2 j rem(7,-5) = 2 I rem(-7,-5) = -2 I
42
Глава 2
Функция sign (знак) принимает одно из трех значений: -1 (если аргумент
отрицателен), о (если аргумент равен 0) и +1 (если аргумент положителен).
В MATLAB 7 появилась группа прямых и обратных тригонометрических
функций, работающих с углами в градусах.
Наряду с хорошо знакомыми программистам функциями ехр(х), iog(x) и
sqrt(x) в системе MATLAB представлены некоторые их разновидности:
П функция expmi(x) вычисляет значение expix-i);
П функция logip(x) вычисляет значение ieg(x+u;
П функция pow2 (х) возводит 2 в степень х;
П функция nextpow2(x) определяет наименьшую степень двух,
ограничивающую х сверху (nextpow2 (1000)=10). Такая функция полезна при
работе с быстрыми преобразованиями Фурье.
Функции reailog и reaisqrt вычисляют, соответственно, натуральный
логарифм и корень квадратный для каждого элемента матрицы:
» х=[1 2 4 8];
» reallog(x)
ans =
0 0.693.1 1.3863 2.0794
» reaisqrt(х)
.ans =
1.0000 1.4142 2.0000 2.8284
С помощью функции primes можно сгенерировать последовательность
простых чисел:
» primes(25)
ans =
2 3 5 7 11 13 17 19 23
Функции perms и nchoosek позволяют генерировать перестановки и
сочетания из заданных элементов:
» perms([1 2 4]}
ans =
4
4
2
2
1
1
;hoc
2 1
1 2
4 1
1 4
2 4
4 2
>sek(['A' "В"
Пошаговые вычисления в командном окне
43
ans =
АВ
АС
ВС
Следует заметить, что список функций, приведенных в этом разделе,
составляет крохотную часть от набора библиотечных функций, встроенных в
ядро MATLAB. Об этом можно судить по объему документации,
посвященной описанию функций. Она представлена в виде трех файлов — refbook.pdf,
refbook2.pdf и refbook3.pdf. Их общий объем превышает 15 Мбайт, а в
печатном виде документ занимает порядка 2000 страниц, на которых приведены
достаточно подробные сведения примерно о 850 функциях и командах с
примерами их использования, графиками и таблицами.
2.6. Построение графиков функций
одной переменной
Одним из способов визуализации результатов вычислений является
построение графиков различных функций. MATLAB предоставляет
пользователям достаточно гибкие средства построения и редактирования графиков
плоских и пространственных кривых, трехмерных поверхностей и
некоторых геометрических фигур. Рассмотрим самые простые средства построения
графиков и их ручного редактирования с целью включения в состав
отчетной документации. Более сложным вопросам машинной графики и
соответствующим программным средствам, реализованным в системе MATLAB,
посвящена гл. 10.
2.6.1. Простые графики
в декартовых координатах
Для того чтобы построить график функции y=f(x), достаточно тем или
иным способом сформировать два вектора одинаковой размерности —
вектор значений аргументов (х) и вектор соответствующих значений функции
(у), и обратиться к функции plot (пример 2.12).
I. Пример 2.12. Построение графика фун^цйй^э^^^^^рк. ^lMp.1, ^":ftt^ !jl
» х=0:0.1:6.28,-
» y=sin(x).*ехр(-х);
» plot (х, у)
44
Глава 2
В простейшем случае, которым мы воспользовались при вызове функции
plot, MATLAB автоматически создает окно'с заголовком Figure 1,
размешает в нем стандартное меню и панель инструментов, выделяет в области
клиента прямоугольное поле с графиком функции, производит соответствующее
масштабирование и разметку по обеим координатам (рис. 2.10). Собственно
график функции получен путем соединения смежных точек таблицы
отрезками прямых. Чем меньше точек было бы в таблице отображаемой
функции, тем заметнее была бы кусочно-линейная структура графика.
•J* Figure 1
File Edit View Insert Tools Desktop Window Halp
DcSa©ifei.^^f)®|.«;iDS!i3n '
0.35
0.3
0.25
0.2
0.15
0.1
0.05
0
-0.05
•Л
' I \
7 \
\
I
X
3 12 3 4 5 6
mna
■»
'
1
Рис. 2.10. График затухающей синусоиды на интервале [О, 2л]
Если мы обратимся к функции plot повторно, то она создаст новое окно с
заголовком Figure 2 и разместит в нем следующий график. Мы могли бы
совместить оба графика в одном окне двумя разными способами. В первом
случае перед вызовом функции plot мы должны построить таблицы обеих
функций, например, (xl,yl) и (>;2,у2). А при вызове функции plot указать
их в списке аргументов (пример 2.13).
Пример 2.13. Построение двух графиков в одном окне
»^*£У"
» х1=0:0.2:б.28;
■»■ yl=sin(xl);
Пошаговые вычисления в командном окне
45
» y2=cos(xl);
» plot(xl,yl,xl,y2)
Результат работы этого фрагмента приведен на рис. 2.11.
Ш
0.5
:
■ Й!->
л
:.; А5
/\
/\
/
/
\
Х \ '
v У
Рис. 2.11. Совместное отображение графиков
двух функций в одном окне
Второй способ заключается в блокировании режима создания нового
графического окна с помощью функции hold on (дословно — заморозить
предыдущее окно) — пример 2.14.
| Пример :2.14. Использование функции hold on "*:
» plot(xl,yl)
» hold on
» plot(xl,y2)
i-....-.j;;;;;...V....;.j.,.;.rrtii.^*^:V:l..J
При выполнении примера 2.14 в командном окне обратите внимание на то,
что график второй функции отображен зеленым цветом, тогда как первая
кривая имела синий цвет. MATLAB автоматически сменил цвет
отображения следующего графика. Однако на выбор цвета того или иного графика
может повлиять и пользователь, указав в функции plot дополнительный
параметр — символ, ассоциированный с одним из 8 предусмотренных
цветов (табл. 2.7):
» plot (х, у, 'д')
46
Глава 2
Таблица 2.7
Символ
цвета
У
га
с
г
Цвет графика
Желтый (от англ. yellow)
Малиновый (от англ. magenta)
Циановый (от англ. cyan)
Красный (от англ. red)
Символ
цвета
g
ь
w
к
Цвет графика
Зеленый (от англ. green)
Синий (от англ. blue)
Белый (от англ. white)
Черный (от англ. b/acfc)
На вид графика пользователь может дополнительно повлиять, задав стиль
линии и форму маркера, которым метятся табличные точки. Стиль линии
предусматривает выбор одной из четырех возможностей — сплошная линия
(по умолчанию управляющий символ — тире), пунктирная линия
(управляющий символ — двоеточие), штрих-пунктирная линия (управляющие
символы — тире и точка), штриховая линия (управляющие символы — два
тире). Управляющие символы, определяющие стиль линии, задаются в
строке третьего параметра вместе с цветом. Порядок следования символов —
любой:
» plot(x,y.'g:■)
или
» plot (х, у, ' :д')
Тип маркера задается еще одним символом в этой же управляющей строке.
Всего таких символов — 13, и соответствующие им маркеры приведены в
табл. 2.8.
Таблица 2.8
Символ
о
X
+
*
s
шопе
Маркер
Жирная точка
Кружок
Косоугольный крестик
Прямоугольный крестик
Восьмиконечная снежинка
Квадратик
Отсутствие маркера
Символ
d
V
Л
<
>
р
h
Маркер
Ромбик
Треугольник вершиной вниз
Треугольник вершиной вверх
Треугольник вершиной влево
Треугольник вершиной вправо
Пятиконечная звезда
Шестиконечная звезда
Если в стилевой строке указан тип маркера, но не задан стиль линии, то
табличные точки маркером метятся, но друг с другом отрезками прямых не
соединяются (пример 2.15).
Пошаговые вычисления в командном окне
47
[Пример 2.15. Использование маркеров ,. ' . .
» х=Ц 2 3 4];
» у=[1 2 2 4];
» plot (х, у, 's—')
Соответствующий график с маркерами на штриховой линии привеяен на
рис. 2.12.
4
3.5
3
2.5
■I 2
1.5
1С
У3-
У
1.5 .2
2.5.
1
/
/" "
/ .
/
/
—сГ
3 3.5 '
\
Рис. 2.12. График с маркерами, стиль линии — штриховой
Дополнительные украшения графика заключаются в возможности снабдить
его Заголовком (ФУНКЦИЯ title), Подписать ОСИ (фуНКЦИИ xlabel, ylabel),
нанести координатную сетку (функция grid on) и разместить легенду
(функция legend). Используем все эти возможности на графике синуса и
косинуса (пример 2.16, рис. 2.13).
! Пример 2.16. Оформление графиков . ^ ^ ;>•;;„. '>■: J$i
» .4=0:0.2:6.28;
» yl=sin(х);
» y2=cos(х);
» plot(x,yl,'-\x,y2, ' .')
» legend ('sin','cos',4)
» ylabel('y-axis')
48
Глава 2
» xlabel('x-axis')
» grid on
»' title('Function sin & cos')
Рис. 2.13. График функций с подписями, легендой и сеткой
Легенда позволяет внести ясность в анализ изображения с несколькими
графикам. Третий параметр, в функции legend (на самом деле этот числовой
параметр можно написать в любом месте списка) управляет размещением
легенды в графическом окне:
П -1 — легенда размешается вне поля графика, вверху справа;
По — система выбирает лучшее место в поле графика, не перекрываемое
данными;
П 1 — легенда размешается в правом верхнем углу (по умолчанию — там же);
П 2 — легенда размещается в левом верхнем углу поля графика;
D з — легенда размещается в правом нижнем углу поля графика;
Па — легенда размещается в левом нижнем углу поля графика.
В некоторых случаях совмещение двух графиков в общем окне может
вызвать проблемы, связанные с тем, что диапазоны изменения аргументов или
значений функций не совпадают. Для разрешения этих проблем MATLAB
предлагает функцию piotyy, которая производит двойную оцифровку осей
(пример 2.17). Для первой функции цифруются ось х внизу, ось у слева, а
для второй функции ось х размечается вверху, ось у — справа (рис. 2.14).
Цвет оцифровки при этом совпадает с цветом кривых.
Пошаговые вычисления в командном окне
49
Пример 2.17. Двойная оцифровка осей
тш*>
» х=0:0.1:6.28;
» yl=sin(x);
» y2=sin(x)+eos(х);
» plotyy(x,yl,x,y2)
■- 6.5
0
-0.5-
С
/ \\
V/
. ч У .
] 1 2 3 4 5 6
2
1
0
-i
1
Рис. 2.14. Графики с двойной оцифровкой осей
Может оказаться, что в одном графическом окне необходимо отобразить
большее число графиков. Тогда следует прибегнуть к функции subplot,
которая позволяет разделить область рисования на несколько прямоугольных
областей равного размера, расположенных подобно элементам матрицы
(пример 2.18):
subplot (row, col, cur) ;
Первые два аргумента задают количество рядов (row) и колонок (col).
Третий параметр (cur) объявляет порядковый номер подобласти, в котором
очередная функция plot будет строить свой график (рис. 2.15).
f Пример 2.18. Деление области рисования
» х=0:0.2:2*pi;
» yl=sin(x};
» y2=cos(х);
» y3=yl.*exp(-x);
>> у4=у1.*у2;
~^ЩФ« ^
50
Глава 2
» subplot(2,2,1);plot(x#yl>;
» subplot(2,2,2);plot(x,y2);
» subplot(2,2,3);plot(x,y3);
» subplot(2,2,4);plot(x,y4);
- 1
:.*■?■■
"■ 0.5
0
•' -0.5
■1c
0.4
0.3
0.2
0.1
0
*\
/\
' \ ,
\
) . 5
(\
\
1 5
.-, 1-
1
0.5
0
-0.5
-1
D С
,:f
0
-0.5,
0 (
\
\
\
\
\
l\
\
]
/ ■
/
I
J.
' 5' 1
Л
/
J V
5 1
3 .
D
0
Рис. 2.15. Четыре подобласти в одном графическом окне
2.6.2. График функции
в полярных координатах
Полярными координатами <p,G) точки р (рис. 2.16) называются длина р
радиус-вектора, проведенного из начала координат в точку р, и угол 6,
образованный между осью х и этим вектором. Угол отсчитывается от
положительного направления оси х к радиус-вектору против часовой стрелки.
Довольно многие математические кривые с целью устранения
неоднозначности принято задавать в полярной системе координат. Например,
уравнение кардиоиды имеет вид:
р = а- (1 + cps(p).
Для построения графиков функций, заданных в полярной системе
координат, вместо функции plot используется функция polar (пример 2.19).
Пошаговые вычисления в командном окне
51
У
Рис. 2.16. Полярные координаты
Пример 2.19. Построение графика в полярных координатах
» phi=0:0.1:2*pi;
» ro=5*(l+cos(phi));
» polar(phi,го)
» t itle('Кардиоида')
Результат построения кардиоиды для a=s приведен на рис. 2.17.
Рис. 2.17. График кардиоиды
в полярной системе координат
52
Глава 2
2.6.3. Использование
логарифмического масштаба
Единицы измерения значений ординат и абсцисс далеко не всегда
соответствуют друг другу, и для создания более обозримого графика вдоль одной
или обеих координатных осей приходится выбирать логарифмический
масштаб. Для построения таких графиков используются функции loglo.g
(логарифмический масштаб по обеим осям), semiiogx (логарифмический
масштаб по оси х), semiiogy (логарифмический масштаб по оси у) —
пример 2.20, рис. 2.17.
; Пример.2.20-Использование логарифмического масштаба -^^^^1¾¾¾¾ &у[ 1
» х=0:10:100;
» у=ехр(х);
» semiiogy(х, у)
Рис. 2.18. График с логарифмическим масштабом по оси у
2.6.4. Построение графика функции
на заданном интервале
Довольно интересной модификацией функции plot является функция
fplot, которая строит график функции y=f (х) без предварительного
вычисления векторов (xl,x2, ...) и (у1,у2,...). Базовый формат вызова этой
функции включает два аргумента:
fplot (@nair,e_fun, [limits 1 )'
fplot('name_fun', [limits])
Пошаговые вычисления в командном окне
S3
В первом случае первым аргументом является указатель на функцию с
именем name fun, во втором случае — строка с именем обрабатываемой
функции. Аргумент limits может быть представлен либо двухкомпонентным
вектором [xmin xmax], либо четырехкомпонентным вектором [xmin xmax ymin
ymax]. Укороченный вариант задает пределы изменения аргумента х,
расширенный — дополнительно представляет пределы изменения функции.
Например:
fplot(@sin, [D2*pi])
fplot('sin', [0 2*pi])
По сравнению с plot функция fpiot берет на себя вычисление таблицы
значения функции, проявляя при этом некоторый интеллект — в местах
резкого изменения функции значения аргумента х выбираются с более
мелким шагом. Функция fpiot гарантирует, что относительное уклонение
воспроизводимой функции отличается от ее идеального графика не более чем
на 0,2%. Если вам нужен более точный или более грубый график, то после
двух обязательных аргументов в функции fpiot можно задать желаемую
относительную погрешность — число, меньшее I:
fplot(Gsin, [0 2*pi], 0.05)
В этом случае гарантировано построение графика, отличающегося от
идеальной кривой не более чем на 5%. Еще один дополнительный параметр —
целое натуральное число n требует, чтобы функция fpiot использовала при
построении не менее чем n+i точку. Относительная погрешность и
количество точек могут задаваться в любом порядке:
fplot(@sin, [0 2*рд], 0.05, 20}
fp!ot(@sin, [0. 2*pi], 20, 0.05)
Наконец, как и в функции plot,, среди дополнительных параметров могут
находиться строки, управляющие цветом и маркировкой графика.
Последовательность задания всех дополнительных параметров — произвольная.
Результат выполнения следующего оператора приведен на рис. 2.19:
fpiot(@sin, [0 2*pi], 0.05, 's—'}
Функция fpiot умеет возвращать значения компонентов векторов х и у,
если к ней обратиться следующим образом:
[х у] = fpiot(Gsin, [0 2*р1]);
Функция f, указываемая в качестве первого аргумента fpiot, кроме
независимой переменной х может содержать дополнительные параметры,
например, y=f (x,al, а2). Тогда эти параметры указываются среди
дополнительных аргументов после задания относительной погрешности и минимального
числа точек:
fplot('name_fun'f [xl х2], 0.05, 20, al, а2)
54
Глава 2
Рис. 2.19. Синусоида, построенная по fplot
Довольно интересный пример, демонстрирующий ряд возможностей
функции fpiot, приведен в справочных файлах. Советуем внимательно
разобраться со всеми форматами вызова этой функции (пример 2.21), результат
работы которых отображен на рис. 2.20.
50
°с
5
а
0
"'-Б
Л
\
) \^\
) 0.5 т.. 1
I
*ч
j
■ч. У
I
/
/'
\
/
I
-5; f 0 -.5
ж ,
5
■ 1
0.5
\ /
I
l/WvwvVV.
] 2 :. 4 - 6
J"
ШШГ
■II1
о|||
«:5
-1
Mill
1
Л
1/ V-;
0.02 0.04 -О.0Б 0.DS 0
1
Рис. 2.20. Примеры работы функции fplot
Пошаговые вычисления в командном окне
55
I Пример 2.21. Использование функции fplot
» subplot (2,2,1), £plot[ehumps, Г 0 ] 1 )
» f = inline.('abs (exp[-j*x+ [0:9) )*ones(10,1)) ■) ,-
» subplot(2,2,2), fplot(f,[0 2*pij)
» subplot(2,2,3), fplot('[tan(x),sin(x),cos(x)]',2*pi*[-1 1 -1 1])
» subplot(2,2,4), fplot('sin(1 ./ x) ', [0.01 0.1],le-3)
2.6.5. Средства управления
в графическом окне
Из приводившихся выше примеров видно, что графики функций выдаются
в специальном окне, снабженном меню и панелью инструментов. Это окно
соответствует всем стандартам Windows — его можно перемещать по экрану,
изменять размеры, сворачивать и разворачивать, удалять. По терминологии
MATLAB оно представляет объект типа Figure и как пуповиной связано с
пакетом MATLAB через встроенное меню. Так как термин фигура не очень
удачно передает смысл и свойства этого объекта, мы будем пользоваться
термином графическое окно. В принципе, каждое графическое окно в момент
своего создания кроме автоматически формируемого заголовка (Figure I,
Figure 2 и т. д.) может быть идентифицировано с помощью специального
указателя (в английской терминологии — handle):
hGWl = plot[х,у,...)
Имя указателя выбирает пользователь. В дальнейшем, при работе с
несколькими одновременно существующими графическими окнами указатель
используется для выделения и редактирования компонентов соответствующего
окна.
Если нам нужно поработать с текущим графическим окном, то вместо
своего указателя можно пользоваться соответствующим системным указателем.
Его выдает функция gef (от англ. get handle to current figure — получить
указатель текущего графического окна). Существуют и другие системные
функции, возвращающие указатели, например, на оси графика дса (от англ. get
handle to current axis — получить указатель текущего объекта типа axis (ось)),
на текущий графический объект дсо (от англ. get handle to current object —
получить указатель текущего объект) и др. Использование указателей
подобного рола более подробно рассматривается в гл. 7.
Меню, встроенное в графическое окно, позволяет:
П обратиться к довольно мощному редактору свойств графических объектов;
П сохранить графическое окно в файле с расширением fig;
П перейти в среду MATLAB и выполнить любые действия в командном окне.
:i Зак хад
56
Глава 2
На рис. 2.21 приведены развернутые меню наиболее важных пунктов
главного меню графического окна.
File |
New
Open...
Close
Save-
Save As...
Generate M-Flle...
Import Data...
Save Workspace As...
Preferences...
Export Setup..„
Page Setup...
Print Setup...
Print Preview...
Print...
Edlt|
J-1-.lo ■
tCut
Copy
Clear
Vlew|
" Figure Toolbar
Camera Toolbar
Plot Edit Toolbar
Figure Palette
Plot Browser
Property Editor
SelectAII Ctrl+A
Copy Figure
Copy Options...
Figure Properties...
Axes Properties...
Current Ot
Colormap.
Find Files.
Clear Flgur
sject Properties...
,
e
Clear Command Window
Clear Command History
Clear Wert
space
Insert |
X Label
Y Label
71-Ы
Title
Legend
Colorbar
Line
Arrow
Text Arrow
Double Arrow
TextBox
Rectangle
Ellipse
Axes
Light
Tools |
V Edit Plot
Zoom In ': ,-
Zoom Out
Pan
Rotate 3D
Data Cursor
Reset View ..,
Options
Pin to Axes " '
Snap To Layout Grid
View Layout Grid
Smart Align and Distribute
Align Distribute Tool...
Align
Distribute
>
»
»
Basic Fitting
Data Statistics
Рис. 2.21. Основные команды меню графического окна
Первая группа команд в меню File (Файл) позволяет закрыть графическое
окно (Close (Закрыть)), вызвать в него ранее сохраненный графический
файл (Open (Открыть)) или начать вручную создавать новый график,
используя при этом возможности Property Editor (Редактор свойств)
графического объекта (New Figure (Новый графический объект)).
Команды второй группы позволяют сохранить графическое окно под
прежним (Save (Сохранить)) или новым (Save As (Сохранить как)) именем, а
таюке экспортировать его в нужном вам графическом формате (Export Setup
(Параметры экспорта)). Список графических форматов, который доступен
пользователю MATLAB, приведен в табл. 2.9.
Таблица 2.9
№ Наименование графического формата
Расширение файла
1 Enhanced metafiles
2 Bitmap files
3 EPS (Enhanced PostScript) files
emf
bmp
eps
Пошаговые вычисления в командном окне
57
Таблица 2.9 (окончание)
№ Наименование графического формата
Расширение файла
4 EPS Color files
5 EPS Level 2
6 EPS Level 2 Color
7 Adobe Illustrator files
8 JPEG images
9 TIFF images
10 TIFF no compression images
11 Portable Network Graphics files
12 Paintbrush 24-bit files
13 Portable Bitmap files
14 Portable Graymap files
15 Portable Pixmap files
eps
eps
eps
ai
ipg
tif
tif
png
pcx
pbm
pgm
ppm
Очень интересен результат выполнения команды Generate M-File
(Генерировать М-файл) — в предыдущих версиях такой команды не было. Она
позволяет автоматически создать функцию построения графиков,
расположенных в графическом окне. Например, для графика Двух кривых,
представленного на рис. 2.10, MATLAB автоматически генерирует следующий
файл:
function createfigurefxl, yl, у2)
%:CREATEFIGURE (XI, Yl, Y2)
% XI: vector of x data
% Yl: vector of у data
% Y2: vector of у data
% Auto-generated by MATLAB on 03-Sep-2004 22:3.5:57
%% Create figure
figurel = figure ('PaperPosition', [0.6345 6.345 20.3 15.23],
• Pape.rS.ize ',[20.98 2 9.68]) ;
%% Create axes
axesl = axes(...
'YColor',[0 0 1],
58
Глава 2
■YTick', [-1 -0.5 0 0.5 1.1, ...
'Parent', figure]);
axis(axesl,[О 7 -1 1]);
hold [-axesl,'all');
%% Create plot
plonl = plot(xl,yl,'Parent',axesl);
'%%■ Create axes
axes2 = axes (...
'YColor', [C 0.5 0], . ..
'YAxisLocation','right',...
'YTick',[-2-10 1 2],...
'Parent', figured );
axis(axes2,[0 7 -2 2] ) ;
l-i©ld(axes2, 'all') ;
%% Create plot
plot2 = plot(xl,y2,'Parent*,axes2);
Если этой функции передать в качестве параметров векторы xl, yl и у2, то
она воспроизведет указанный график. Заметим, что наше построение
потребовало всего 3—4 команды. Изобилие строк в автоматически созданной
программе объясняется тем, что в ней предусмотрено создание всех
элементов фигуры — собственно графического окна, осей и их разметки, графика
кривых. Может быть, к такого рода процедуре следует прибегать только в
гом случае, когда пользователь провел вручную достаточно большую
редакторскую правку.
Команды import Data (Импортировать данные) и Save Workspace As
(Сохранить рабочее пространство как) уже упоминались при описании
главного меню.
Команда Preferences (Предпочтения) выводит нас в окно установок
параметров системы MATLAB, но целесообразность ее включения в меню
графического окна вызывает сомнение. Аналогичная возможность входи г в
состав меню File (Файл) командного окна.
Команда Export Setup (Параметры экспорта) вызывает диалоговое окно, в
котором можно просмотреть и изменить значения текущих параметров
графического окна и графика — размеры (Size), способ визуализации (Rendering),
характеристики шрифта (Font) и свойства линий (Lines). После этого
откорректированный график можно сохранить в файле с расширением fig.
Пошаговые вычисления в командном окне
59
Оставшиеся команды последней группы меню File (Файл) связаны с
подготовительными работами по настройке параметров графика, листа бумаги и
принтера перед выдачей окончательной команды вывода (Print (Печать)).
Команда Page Setup (Параметры страницы) вызывает диалоговое окно,
снабженное четырьмя вкладками. Первая вкладка (рис. 2.22) позволяет
вручную (Use manual size and position (Ручная установка размеров и полей
страницы)) установить размеры полей (Тор (Сверху), Left (Слева), Width
(Ширина) и Height (Высота)) поля графика в удобных для пользователя
единицах измерения (Units (Единицы измерения)). В противовес ручной
установке размеров и позиций имеется возможность разместить экранный
образ в центре страницы (Use screen size, centered on page (Использовать
размер экрана, разместить по центру)).
Page Setup - Figure 1 Q
Size and Position I Paper | Lines and Text I Axes and Figure |
Mode ' -~?m
r Use screen size, centered on page
<• Use manual size and position
[-Manual size and position
Top: fe.-m
I
Use defaults
Left
Width:
Height:
20.30
1
Fill page
|l5.23 Щ'
Unlts:| centimeters _£]'
Fix aspect ratio
Center
Sample
Г5Й1
Help..
OK
Cancel
Рис. 2.22. Установка размеров и позиций графика на странице
Вкладка Paper (Бумага) позволяет выбрать формат листа бумаги (в наших
условиях чаше всего А4) и установить его ориентацию (в высоту — Portrait
(Книжная), в ширину — Landscape (Альбомная)). На вкладке Lines and Text
(Линии и текст) можно отказаться от конвертирования цветов, если ваш
принтер умеет печатать в цвете.
Более интересные возможности предлагает вкладка Axes and Figure (Оси и
рисунок) — рис. 2.23. Она позволяет изменить пределы и разметку осей но
60
Глава 2
отношению к образу на экране, изменить фон графика на белый цвет,
включить печать элементов управления, установленных в области
графического окна, произвести пересчет графического образа в зависимости от
выбранного инструмента (ZBuffer, OpenGL и др.).
Page Setup - Figure 1
Hi и .1«
Size and Position | Paper | Lines and Text
-. . ■ ? • * »i ■ ■
Web 111 i lllb dl IU LILtSt,
<* Recompute limits and ticks ■ .■
<*" Keep screen limits and ticks
путы tUIIUUIb i --„ -.
I? Print UlControls, . ■:
*
1 \
,. Backgioiino tuiui
'-<• Force white backflround * _■"
f Keep screen.backflroynd color .
■ Figure rendaiKi .- ■ ■;
|Default(auto mode) т| -
. ■ ' -
, ,r (_
■ -¾.
,>u.:r-
■
-■
Axes arjd Figure |
Ь
sanpfe
IokI
'...
■ .,1
,.
L.j
Help..
,-ur Jw'i
OK J '- Cancel •
.v. ; ..".. .- " -:
Рис. 2.23. Изменение параметров графика
2.6.6. Редактирование графиков
Меню Edit
Меню Edit (Правка) — см. рис. 2.21 — включает набор стандартных команд,
присутствующих в любом текстовом или графическом редакторе — Undo
(Отменить ввод), Cut (Вырезать), Сору (Копировать), Paste (Вставить), Clear
(Очистить) и Select All (Выделить вес).
Команда Edit | Figure Properties (Правка | Свойства графического объекта)
вызывает Property Editor (Редактор свойств), который пристыковывается к
графическому окну (рис. 2.24) и предварительно настроен на изменение
свойств фигуры (Figure). В появившихся окнах редактора отображены
наиболее употребительные параметры фигуры. Вы можете изменить заголовок
графического объекта (Figure Name), сменить цветовую палитру (Colormap),
Пошаговые вычисления в командном окне
61
указать цвет окаймления поля графика (Figure Color), включить или
отключить воспроизведение порядкового номера графического окна (Show Figure
Number). С помощью кнопки Inspector (Инспектор) вызывается Property
Inspector (Инспектор свойств), в котором отображаются все свойства
фигуры. Любое из них, не включенное в наиболее употребительный набор, тоже
может быть изменено. Более подробная информация о свойствах всех
графических компонентов и технике работы с Property Inspector (Инспектор
свойств) приводится в гл. 7 и 8.
Из окна Property Editor (Редактор свойств) можно вызвать диалоговое окно
Export Setup (Параметры экспорта).
■> Figure 1
File Edit View Insert Tools Desktop Window Help
d &a a i|¥l Q ®t f? ®»vM d m \ о m
0.5
0
"'-0.5
(
, Prope
j Figure Name
Cdormap:
1
Figure Color
1
В
4 ' ' ■ '
У / ~s- \
4 V /
J ' 1 2 3 A 5 6
rty Editor - Figure
л
i
0
ж
r.) P Show Fljjure Number Inspector... li
| HI: '$Mjet jj Exponsaup... |
Ф»-|
i
Рис. 2.24. Редактор свойств графического окна (Figure)
Если в графическолг окне выделить оси, щелкнув по одной из них, то в
окнах Property Editor (Редактор свойств) появляются свойства осей (рис. 2.25)
и меняется' заголовок (Property Editor — Axes). Вы можете изменить
заголовок, расположенный над полем графика (Title), установить цвета осей,
подписей и фона поля графика (Colors), включить или отключить изображение
координатной сетки по любой из осей (Grid), включить или отключить
обводку рамки поля графика (Box). Для каждой из координатных осей можно
62
Глава 2
изменить наименование оси (X Label, Y Label, Z Label), минимальный и
максимальный пределы изменения соответствующей переменной (X Limits,
Y Limits, Z Limits), способ масштабирования по каждой из осей (X Scale, Y
Scale, Z Scale), сменить направление оси на противоположное (Reverse).
Кнопка Ticks (Штрихи) вызывает Edit Axes Ticks (Редактор штрихов), вид
которого приведен на рис. 2.26. С его помощью можно выбрать один из трех
вариантов размещения штрихов — автоматический (Auto), ручной (Manual)
или с заданным шагом (Step by), задать автоматический или ручной способ
индикации каждого штриха (X Tick Labels), включить или отключить режим
отображения малых штрихов (Show minor ticks). Кнопка Inspector
(Инспектор) в окне Property Editor (Редактор свойств) вызывает инспектор,
отображающий значения всех свойств координатных осей.
лА Figure 1
File Edit View Insert Tools Desktop Window H<
D с? И в РГД ё*. О ® !'€, Q m □ □
э1р
05
-0 5
Г 4.
/ \ '
0 12 3 4 5
Property Editor - Axes
Title:
X Axis | у Axis | Z Axis | Font |
Colors: c
Grl» Г
Г
XUfcel: I Ticks...
— ' —— 1 X Llrrftsi |0 to |7 Г Auto
x rv Гг , 1 ,_
X Seete: | Li.. j^J \ Reverse
Box
6
11
1
..
1
0
-I
r
X
Inspector... 1;
Рис. 2.25. Редактор свойств осей координат (Axes)
Выделение той или иной кривой (рис. 2.27) приводит к перенастройке
редактора свойств на параметры указанного графика (Property Editor — Line-
series). Раскрывающиеся списки X/Y/Z Label Data Source (Источник
данных) позволяют изменить значения векторов х, у и z, задающих табличную
Пошаговые вычисления в командном окне
63
функцию. После изменения любого из этих элеменюв необходимо нажать
кнопку Refresh Data (Обновить данные), и тогда новые числовые значения
вступят в силу.
-JfcEdit Axes Ticks
jXAxis]) Y AxisI ZAxlsl
□
X Tick Locations:
<*" Auto
С Manual
X Tick Labels:
<*■ Auto
С Manual
Г Step by: J
Locations: Labels:
0 0 _
.... _ 1._ Jl
" . 2 _ 2 ._
... "_ ..3..,. _3 - Л
. 4 J_4
__.....! sj.i ~; ,_
_G !_6-
~7 П "
Insert
Delete
I- Show minor ticks
OK
Apply
Cancel
Рис. 2.26. Редактор штрихов на координатных осях
На рис. 2.28 показаны раскрывающиеся списки и подсказки к
соответствующим окнам. В раскрывающемся списке Plot Туре (Тип графика) вы
можете выбрать один из пяти способов отображения графика функции. По
умолчанию график воспроизводится линией (Line, отсюда и фрагмент
заголовка окна — Lineseries). Четыре других способа воспроизведены на рис. 2.29.
В раскрывающемся списке Line (Линия) задается тип линии (сплошная,
штриховая, пунктирная или штрих-пунктирная). Значение no line (нет)
заменяет линию графика маркерами в заданных точках. Цвет линии и ее
толщина регулируются значениями, установленными при помощи кнопок-
списков, выделяемых подсказками Color (Цвет) и LineWidth (Толщина
линии) соответственно. В списке Marker можно выбрать подходящую конфи-
64
Глава 2
гурацию маркера, размер которого задается значением в раскрывающемся
списке MarkerSize. Цвета контура маркера и его внутренней области
устанавливаются с помощью кнопок-списков MarkerEdgeColor и MarkerFace-
Color соответственно.
-> Figure 1
File Edit View insert Tools" Desktop Window Help
D c? о а (¥|Д $.<"? ®' Щ i D El □ □
1
0.9
0
,0.5
Prope
; DJsplayNnrr
■ V Data Sou
; ZDetoSour
;
ВПЕЗ
.-4 \
/ V \ .-
/ ■" \
■Л .•' /
■V /
.4.. .,-' ,
Э 1 2 3 A 5 6
rty Editor - Lineseries
1
0
f
« | Plot Type- JLlne jj trispertur... |:
се |м»с zi bne l~—Zl los Zi s£" | ~
<ж | J Marten |ic. _^J |бл _J &-( ^,-
-1 zJ
1
1
1
.. i
Рис. 2.27. Редактор свойств
выделенного графика (Lineseries)
Команды Edit | Axes Properties (Правка | Свойства осей) и Edit | Current
Object Properties (Правка| Свойства объекта) вызывают Property Editor
(Редактор свойств) с одновременной настройкой на параметры соответствующего
объекта.
Команда Edit | Find Files (Правка | Найти файлы) появилась только в
MATLAB 7. Она позволяет устроить поиск заданного контекста во всех
файлах текущего каталога. Аналогичным инструментом обладают
практически все оболочки операционных систем и достаточно развитые системы
программирования.
Команды последней группы обеспечивают очистку поля фигуры,
командного окна, окна истории команд и рабочего пространства. По умолчанию
очистка трех последних компонентов сопровождается запросом
подтверждения на выполнение операции.
Пошаговые вычисления в командном окне
65
г Color
Property Editor - Lineseries
Display Nome: j
X Date Source: | auto
V Dale Source: |
d
d
r-Plot Type: Line
Z Data Source: | d
"3
(Trie
"71
Ber
Area
Stelrs
Stem
—Line: | jj 10.5 jj:
Msrtor; | no... jj 16.0 d
Inspector..
Refresh Data
&'\ £'\
MarkerEdgeColor
L MarkerFaceColor
LineWidth
•-MarkerSize
Рис. 2.28. Средства редактирования выделенного графика
Ваг
Area
/ \ \
в
х
■ \ "V
т Л
i
i.«? /
j
w/
Stairs
Stem
Рис. 2.29. Способы отображений табличных функций
Кроме кнопок, обеспечивающих создание, открытие, сохранение и печать
графического объекта, на панели инструментов находятся следующие
кнопки (рис. 2.30):
П Edit Plot — включение режима выделения графического объекта;
□ Zoom In — увеличение масштаба изображения;
□ Zoom Out — уменьшение масштаба изображения;
66
Глава 2
|- New Figure
Г Open File
- Save Figure
Print Figure
■Pan
Rotate 3D
Data Cursor
«^ I'icruire 1
'ile Б It View Insert ool esktop Window Help
йене' fe i «*. s. « ®! «JO Ш\ ь_п
I- Zoom Out
Zoom In
L Edit Plot
L Show Plot Tools
Hide Plot Tools
L Insert Legend
Insert Colorbar
Рис. 2.30. Панель инструментов графического окна
•> Figure
1
File Edit View Insert Tools Desktop VV
1
-1,
1
0.5
\
w-
o\
-0.5 \
.-1 ~*
"^
f 6
8
indow
и П
V
Help
■—r ' 2
4
НПП
■л
0
Рис. 2.31. Вращение плоской кривой
□ Pan — захват кривой с целью ее перемещения в поле фафмка;
П Rotate 3D — вращение изображения (больший эффект достигается для
3D-noBcpxHOCTefi. пример вращения плоской синусоиды приведен на
рис. 2.31);
Пошаговые вычисления в командном окне
67
П Data Cursor — включение режима, при котором точка графика,
попавшая под курсор, сопровождается отображением значений координат
(рис. 2.32);
П Insert Colorbar — включение столбика с палитрой цветов (Colormap),
отражающего распределение высот z;
П Insert Legend — вставка автоматической легенды;
П Show Plot Tools — пристыковка к графическому окну средств
редактирования и просмотра (Figure Palette (Редактор графического окна), Property
Editor (Редактор свойств), Plot Browser (Просмотр графика));
□ Hide Plot Tools — удаление средств редактирования и просмотра.
•> Figure 1
File Edit
View Insert Tools Desktop Window Help
D.c*H_a-fe ®^f)©-RT| DE n □ ■ „■
0.8
0.6
0.4
0.2
0
-0.2
-0.4
-0.6
-0.8
' ,~ V
\
/ \
/ "■
' X 7 i
I Y DE75^
7
/ \
: \
\ /
\ /
\ i
/
\ /
0 12 3 4 5 6
ИПП
■ai
—
7
Рис. 2.32. Идентификация точки на кривой
Меню View
Команды меню View (Вид) позволяют отобразить (команда помечена
галочкой) на экране или скрыть следующие средства редактирования (см.
рис. 2.21):
П Figure Toolbar — панель инструментов графического окна;
П Camera Toolbar — панель инструментов для управления камерой;
68
Глава 2
П Plot Editor Toolbar — панель инструментов для редактирования графика;
П Figure Palette — редактор графического окна;
□ Plot Browser — средство просмотра графических объектов;
□ Property Editor — редактор свойств графических объектов.
Перечисленные средства, исключая описанный выше Property Editor
(Редактор свойств), приведены на рис. 2.33.
•> Figure 1
File Edit View Insert Tools Desktop Window Help '.'
0& Qi \\k\ГСёП?1? ® i чёТП IS ro "rZT"' """""
.S К $:k .ft * *' "L.4. JL_4 L?.||в.1& ©Z Z
* s л_ a_j_» / i^gi>-\\\4TD6|-al
Figure P... *
ИПП
I Figure Toelbar|
I Camera Toolbar I
I Plot Edit Toolbar I
Plot Browser x
■*■ New Subplots
О I'D Axes.
l^.. 3D Axes
Шу
1x63
1x63
V Annotations
\Line
\Ajtuw
X Doubifi A»:xw
^ Text Arrow
T lexi Box
j I Rectangle
Osiqise
1
0.8
0.6
0.4
0.2
0
-0.2
-0.4
-0.6
-0.8
ll
-1
0
' /\
7 \
/ \
\
\
\
■
/
!
/
P/ Axes (no title)
17
Рис. 2.33. Графическое окно со средствами редактирования
Камера (Camera), или точка зрения, определяет позицию человека,
наблюдающего за.объектом, расположенным в поле графика, параметры
источника света, способы распространепия и отражения лучей света. Более
подробно свойства камеры описываются в гл. 10.
Редактор графического окна (Figure Palette) и соответствующая панель
инструментов (Plot Editor Toolbar) рассматриваются ниже.
Окно Plot Browser (Просмотр графика) отображает список графических
объектов, расположенных в поле графика.
Пошаговые вычисления в командном окне
69
Меню Insert
Меню Insert (Вставка) — см. рис. 2.21 — содержит набор команд по вставке
в графическое окно различных элементов оформления — легенды (Legend),
разноцветной полоски (Colorbar), линии (Line), различных стрелок (Arrow,
Double Arrow, Text Arrow), пояснительной подписи (Text Box),
прямоугольников (Rectangle) и эллипсов (Ellipse). Вес эти команды дублируют
возможности Figure Palette (Редактор графического окна) и Plot Edit Toolbar
(Панель инструментов редактирования графика). Команда Insert | Light
(Вставка | Свет) подключает к графическому окну Property Editor (Редактор
свойств) источника света (Property Editor — Light), с помощью которого
можно изменить позицию (Position — х, у, z), стиль (Style) распространения
лучей света (бесконечно удаленный — Infinite, локальный — Local) и цвет
лучей (Color).
Меню Tools
Значительно расширен по сравнению с предыдущими версиями набор
команд меню Tools (Сервис) — см. рис. 2.21. Команды Edit Plot
(Редактировать график), Zoom In (Увеличить масштаб), Zoom Out (Уменьшить
масштаб), Pan (Захватить), Rotate 3D (ЗО-поворот) и Data Cursor (Данные под
курсором) продублированы аналогичными кнопками на панели
инструментов Figure Toolbar (Панель графического объекта). Команда Reset View
(Восстановить вид) возвращает па исходное место график, перемешенный в
режиме Pan (Захватить). Команда Options (Параметры) открывает список
команд (рис. 2.34), с помощью которых можно изменить режим
масштабирования, траекторию перемещения графика, захваченного в режиме Pan
(Захватить), и способ отображения координат точки, выделенной курсором:
П Unconstrained Zoom, Unconstrained Pan — естественное масштабирование
(одновременно по всем координатам) или естественное перемещение
графика (по траектории движения мыши);
□ Horizontal Zoom. Horizontal Pan — масштабирование или перемещение по
горизонтали;
□ Vertical Zoom, Vertical Pan — масштабирование или перемещение по
вертикали;
П Display Cursor as Datatip — значения координат точки, находящейся под
курсором, отображаются рядом с курсором;
П Display Cursor in Window — координаты помеченной точки отображаются
под полем графика.
Для удаления неудачно оцифрованной точки можно прибегнуть к услугам
всплывающего меню (рис. 2.35). Кроме удаления только что сделанной
пометки (Delete Current Datatip), можно удалить все метки (Delete All Datatip),
70
Глава 2
изменить точку привязки цифровой отметки (Mouse Position — в позиции
мыши или Snap to Nearest Data Vertex — в ближайшей табличной точке) и
ее местоположение.
1 * Unconstrained Zoom
Horizontal Zoom
Vertical Zoom
* Unconstrained Pan
Horizontal Pan
Vertical Pan
0.8
06
(14
0,2
n
-0.2
-0 4
-0.6
-0.8
•'(
- /
. /
1
1
7
)
\
i
\
2
-
\
\
\
\
\ V 3 2
Ш
\ / ■
\ /
\ /
\ /
/
'■ /
4x. 3 2
V: -U UMTJ/
Рис. 2.34. Дополнительные возможности команды Options
Selectton Style
- Display Style
Create New Datatip
Delete Current Datstlp
Delete All Datatlps
'.av;t.- " --1 ■ ■-■-
Mouse Position ■
►
Alt-Click
Delete
•* Snap to Nearest Data Vertex
Window Inside Figure
' Datatip
Рис. 2.35. Всплывающее меню
Очень интересные возможности предлагает команда Pin to Axes
(Прикрепить к осям), которой на панели инструментов соответствует кнопка,
напоминающая современную кнопку, используемую для закрепления
объявлений. Например, можно направить копчик стрелки с пояснительным текстом
(Text Arrow) в особую точку графика и "кнопкой" закрепить его. Если теперь
воспользоваться режимом Pan (Захватить) для захвата графика и его пере-
Пошаговые вычисления в командном окне 71
мещения, то кончик стрелки будет всегда следовать за прикрепленной
точкой. Пояснительная надпись, расположенная на другом конце стрелки, при
этом будет оставаться на месте. Если с помощью "кнопки" закрепить и
начало стрелки, то перемещения кривой будут сопровождаться параллельными
перемещениями стрелки и надписи.
С возможностями выравнивания (Align) нескольких графических объектов
по вертикали или горизонтали, выбора вертикальных или горизонтальных
зазоров (Distribute) между объектами, привязки объектов к узлам
координатной сетки (Grid) вы познакомитесь более подробно в разд. 8.3.
Команда Tools | Data Statistics (Сервис | Статистика данных) позволяет
получить стандартные статистические данные о кривой, представленной в
поле графика. Результат исполнения этой команды для функции из примера
2.22 приведен на рис. 2.36.
: "' ..»»..._. —Т • * ;
I Пример 2.22. Аппроксимация графика •'
» х=[0:0.8:6.28];
» y=sin(x);
» plot (х,у)
•JtData Statisti.
SlaHsttcs (or |
Creckto plot statistics on figure:
1
min I
mean i
metfHrT1
sW I
гал^е J^
X 1 1
оГ
SB Г
2еГ
1 96 Г
S.6
v 1 t
-D.53S? Г~
0.9996 fl
-0.0D62/? П
•осгэй Г
0.И9Э .Г
1.ЭЭ6 1
Save to workspace- | Help | Qose |
-> Figure 1
File Edit View Insert Tools Desktop Window Help
BOB
1
0.8
0.6
0.4
0.2
Oii
-0.2
-0.4
-0.6
-C.8
-1
datal
Рис. 2.36. Статистика по графику синусоиды с редко заданными точками
72
Глава 2
Представим, что при построении графика мы неудачно распорядились
шагом по аргументу и получили неудовлетворительную кусочно-линейную
аппроксимацию исследуемой функции.
Конечно, можно переделать соответствующую команду и получить хорошую
синусоиду. Но график функции мог получиться в результате довольно
сложных манипуляций, повторять которые не очень то и хочется. В этом
случае можно поправить дело с помощью команды Tools | Basic Fitting
(Сервис | Базовое сглаживание). В результате ее выполнения появляется
диалоговое окно для выбора способа интерполяции таблично заданной
функции. На рис. 2.37 выбрана интерполяция кубическим сплайном, а
справа отображен результат применения этого метода.
-yk Basic
Select deta: [detal^J
P Center and scale X deta
■Plot (lis- — ———
Check to display tits on figure
1? spErie interpoterfl
Г shape-preserving HerpDlant
P linear
Г~ quadratic
P cubic
1 4th degree polynomial
P 5th-degree polynomial
Г" 6th degree polynomial
P 7th degree polynomial
P 8th degree polynomial
P 9th degree polynomial
P 10th Oeeree polynomial
P Show-equations-
I P
Signlficart digits: J 2
Plot residuals
zl
| Bar plot
"3
ISubrjM
P Show norm ol residuals
Help-
File Edit View Insert Tools Desktop Window.Help
|П X
1
0.8
0.6(-
0.4
0.2
0<i
-0.2
-0.4
-0.6
-0.8
-1
Л-
f
■\
datal
spline
\
\
7
~=*4-
Рис. 2.37. Интерполяция графика кубическими сплайнами
Довольно много средств оформления графиков представлено в окне Figure
Palette (Редактор графического окна) и продублировано соответствующими
кнопками на панели инструментов Plot Edit Toolbar (Панель инструментов
редактирования графика) — рис. 2.38.
С помощью кнопок, обеспечивающих быстрый запуск действий, можно
установить цвет фона на поле графика (Color Face), цвет выделенной линии
(Color Edge), цвет пояснительных подписей (Color Text).
Пошаговые вычисления в командном окне
73
Font
Г
Bold
г Insert Line
Insert Arrow
Insert Double Arrow
Italic
Г
Insert Text Arrow
-> Figure 1
.'File Edit ШП-ert Tools D=^SMQndoW He,P
^^-®1.«!jl ЕВ i QJ3
u Color Text
L Color Edge
L Color Face
Pin to axes
L Align Right
L Align Center
L Align Left
Insert Textbox
Insert Rectangle
Insert Ellips
Рис. 2.38. Панель инструментов Plot Edit Toolbar
Align/Distribute
Шесть следующих кнопок очень напоминают средства управления
характеристиками текста, используемые в редакторе MS Word. Однако диалоговые
окна здесь несколько иные. Например, диалоговое окно выбора шрифта и
его характеристик представлено на рис. 2.39. Кнопки по изменению
характеристик выделенного текста (Bold — жирный, Italic — курсив) и
выравниванию строки в прямоугольнике Textbox (Align Left, Align Right и Align
Center) имеют значки в стиле MS Word.
Очередная группа из семи кнопок дублирует соответствующие строки Figure
Palette (Редактор графического окна) и позволяет вставить на любое место
графического окна отрезок прямой (Insert Line), стрелку (Insert Arrow),
двунаправленную стрелку (Insert Double Arrow), стрелку с пояснительным
текстом (Insert Text Arrow), текст в прямоугольнике (Insert Textbox),
прямоугольник (Insert Rectangle), эллипс (Insert Ellipse). Для вставки нужного
элемента следует выбрать соответствующую команду в Figure Palette
(Редактор графического окна) или нажать аналогичную кнопку на панели
инструментов, переместить курсор мыши в начальную точку графического
окна и, удерживая левую кнопку мыши, протянуть элемент до конечной точки
(примерно такая же технология используется в графическом редакторе
Paint).
На рис. 2.40 продемонстрирован результат работы Figure Palette (Редактор
графического окна).
74
Глава 2
Шрифт
Шрифт:
Начертание:
30
'>Г ©PMingLiU
'•t OSimSun
*Г Academy Engraved LET"
'*Г Amaze
обычный
курсив
жирный
жирный курсив
-Оброзец"
Hafiop символов:
ВЕЗ
Размер:
|Кириллический
8
9
10
11
12
11
16
▲
z\
OK
Отмена
^3
Рис. 2.39. Выбор характеристик шрифта
-> Figure 1
File Edit View Insert Tools Desktop Window Help
Fi« re P ... x
"^ New Sublets
ГЗ
Create tiled subplots
-ffl
ffl
v-VenStiles.
Ну
^ Annotations
N^LITIC
^ Arrow
^ Doutfc Mrow
^ Text Arrow
T TexlBox
[ JRcclaruft:
О Ellipse
1*63
1x63
Cancel
^J
0.5
/
\ /
НПЕЗ
0 5n
Oi-
НбПо, МАТ1.АБ
П
12
05
/
0.5
Рис. 2.40. Результат работы редактора Figure Palette
Пошаговые вычисления в командном окне
75
Для создания четырех полей графика в графическом окне необходимо
щелкнуть по кнопке с пояснительной подписью "Create tiled subplots" и в
появившемся поле выделить нужное количество клеток по горизонтали и
вертикали (очень напоминает технику формирования таблиц в MS Word).
В каждом из появившихся окон вставлены описанные выше графические
примитивы.
Подключение русских текстов доставит головную боль отечественным
пользователям MATLAB 7. В примере с воспроизведением кардиоиды (рис. 2.17)
мы слукавили. Обычно результат работы команды title ('кардиоида')
выглядит так, как показано на рис. 2.41.
«> Figure 1
File Edit View Insert Tools Desktop Window Help
КйОаеТёаг*
& 10
„60
НПО
270
Property Editor - Text
^ I Interpreter: |тех
Alignment; !P| ?
Line Style:
UrejV*fth.
Г
~Б
0.5
Edfie COOK с^з |
Background, ffi^l
~3
Fort: | Helvetica j[] ] 10.0 ][]
Рис. 2.41. Так MATLAB 7 отображает русские надписи
Объяснение тому достаточно простое. В шрифте Helvetica не совпадает
кодировка русских букв. Для восстановления справедливости выделяем
надпись и выполняем команду View | Property Editor (Вид | Редактор свойств).
К графическому окну пристыкуется редактор свойств текста, в котором
следует изменить шрифт. К сожалению, не все шрифты, которые доступны в
76
Глава 2
MS Windows (например, Times New Roman), видны из Property Editor
(Редактор свойств). Поэтому приходится остановить свой выбор на шрифте
Courier с установкой подходящей высоты символов (рис. 2.42). Также можно
воспользоваться такими шрифтами, как Arial Cyr, MS Sans Serif, Small Font.
-> Figure 1
File Edit View Insert_ Tools r^_sktop_^lndow Help
■Kapquouqap
■ A, ■
SO 10
12Cb-- Г-£-~д30
man
Property Editor - Text
1 Line Style: p
H Interpreter. | Tex^]
Inspector-
1 LiraWldth: [ai ~^\ Wijnmenf. Bjgg
Edae Colon |Д-| Fort: | Courier
j Background &,-\
3 hi.o zi
Д' I Normal 3 | Normal ^
Рис. 2.42. Замена шрифта для русификации подписи
2.6.7. Включение графиков
в отчетную документацию
После того как вы построили и отредактировали график, отражающий тот
или иной процесс, его можно включить в состав отчетного документа,
например, набираемого в редакторе MS Word. Делается это. следующим
образом:
1. В момент, когда графическое окно находится на экране, нажимается
комбинация клавиш <Alt>+<Print Screen>, копирующая содержимое
экрана в буфер обмена (clipboard).
Пошаговые вычисления в командном окне
77
2. В редакторе, в котором готовится отчет, необходимо выполнить команду
Edit | Paste (Правка | Вставить). Средства MS Word позволяют после
этого выполнить обрезку изображения, поворот, корректировку яркости
и контраста и др.
Более простой вариант копирования области графика в буфер обмена
выполняет команда Edit | Copy Figure (Правка | Копировать рисунок). В этом
случае вам не понадобится удалять лишние фоновые фрагменты, т. к. в
буфер обмена попадет только поле графика без заголовка графического окна.
2.7. Деловая графика
Довольно много различных приложений, связанных с экономическими,
статистическими и социологическими исследованиями, используют для
визуализации результатов различного рода диаграммы — столбиковые и
круговые, плоские и объемные. Иногда их связывают с термином "деловая
графика". В библиотеке графических функций MATLAB для этой цели
реализована Группа следующих функций: bar, barh, ЬагЗ, ЪагЗп, pie, pie3,
area.
2.7.1. Плоские столбиковые диаграммы
В простейшем случае плоская столбиковая диаграмма, отражающая значения
компонентов вектора у, строится с помощью функции bar (пример 2.23).
! Пример 2.23. СтоЛби^вая диаграмгиа ■. f"" :
» у=[1 2 41;
» length(у)
:ans =
3
» bar(у); colormap(cool)
Функция colormap, к которой мы обратились с аргументом cool,
осуществляет подмену стандартной цветовой палитры, закрепленной за графическим
окном. Палитра, по умолчанию приписываемая графическому окну,
отличается довольно мрачными тонами. Новая палитра представляет набор более
светлых оттенков от бирюзового (cyan) до малинового цвета (magenta). На
рис. 2.43 показана построенная диаграмма. По умолчанию ее столбики
расположены над целочисленными координатами х, принадлежащими
интервалу [l, length (у)]. Ширина столбиков по умолчанию равна 0,8 см (этот
размер точно выдерживается только при выводе на принтер). Надписи
внутри столбиков сделаны вручную с помощью средств управления фафическим
т
78
Глава 2
окном. Вид диаграммы не изменится, если вектор у будет представлен
столбцом с такими же значениями (у= [1,-2,-4]).
4
3.5
Э
2.5:
2
1.5
1
0.5
0
•
у = 1
у = 2
у = 4
-
1 2 3
Рис. 2.43. Диаграмма значений вектора у=[1, 2, 4 ]
Обращение к функции barh с тем же аргументом строит столбики,
развернутые по горизонтали (рис. 2.44):
» barh{y); colormap(cool)
3
2
1
0 0.5 1 1.5 2 25 3 35 Л
Рис. 2.44. Горизонтальная диаграмма
J 1 1 L.
Обращение к функциям bar (пример 2.24) или barh с двумя аргументами (х,
у) позволяет изменить маркировку оси л- (рис. 2.45). Правда при этом требу-
Пошаговые вычисления в командном окне
79
ется, чтобы вектор х был представлен монотонно изменяющимися
значениями (возрастающими или убывающими).
[Пример 2.24. Маркировка оси у диаграммы .
» х=[-1-5,0,2.5];
» у=[1,2,4];
». bar{к,у);
» colormap(cool)
3.5
3
2.Б
2
1.S
1
0.5
0,
-
■
-
-
Э-2-1-0 1 2
3
i
Рис. 2.45. Диаграмма с заданной разметкой оси х
Аргумент w в обращениях bar(y,w) или bar(x,y,w) управляет шириной
столбцов диаграммы. В зависимости от маркировки оси х и заданной
ширины столбиков v/ соседние прямоугольники могут накладываться друг на
друга.
Аргумент у может быть представлен не только вектором, но и матрицей
значений (пример 2.25).
': Пример 2.25. Построение нескольких диаграмм одновременно
» у=[1 2 4; 1.5 3 5]
У =*
1.0000 2.0000 4.0000
1.5000 3.0000 5.0000
80
Глава 2
В этом случае функции bar и barh предлагают два способа группировки
столбиков, представляющих компоненты матрицы:
» bar{у,"grouped*); colormap(cool)
или
» bar{y); colormap(cool)
Любая из приведенных выше строк генерирует две группы столбиков (рис. 2.46).
4
3
" 2
1
0
-V.4
-
у=1
т
" Wit
у=1.5
.
ы
т
:
:-т
*&
-
■
1 2 „
Рис. 2.46. Матричная диаграмма, вариант 1
10
" 9
Л
8
■к /
6
5
4
3
2
|у#^
а? а
гЛ
По
тш
У = 1
г
?&°
1¾
■*;>?.. v '.
If
"л t 1 "
!$..i ■
;«к<. #4
■"■■■■■■■-,-- 1
^%ri-;
= 1.5
Рис. 2.47. Матричная диаграмма, вариант 2
Пошаговые вычисления в командном окне
81
Второй способ группировки элементов этой же матрицы позволяет
разместить столбики друг над другом (рис. 2.47):
» bar(у,'stacked'); colorrnap(cool)
2.7.2. Объемные столбиковые диаграммы
Объемные столбиковые диаграммы строятся с помощью функций ЬагЗ и
bar3h, разница между которыми заключается только в вертикальном или
горизонтальном расположении столбцов.
Функция bar3{z) превращает простую плоскую диаграмму в объемную
(рис. 2.48):
» z=[l,2,3];
» bar3{z); colorrnap(cool)
Рис. 2.48. Простая объемная диаграмма
Если аргумент z представлен матрицей, то столбики размещаются как вдоль
оси у, так и вдоль оси х (рис. 2.49):
» z=[2,3,4;l,2,3];
» ЬагЗ{z); colorrnap(cool)
Столбики двумерной матрицы могут быть перегруппированы двумя
разными способами с использованием аргументов grouped (рис. .2.50) и
stacked (рис. 2.51):
» z=[2,3,4;1,2,3];
» ЬагЗ (z,'grouped') ; colorrnap (cool)
» ЬагЗ(z,'stacked'); colorrnap{cool)
82 Глава 2
Рис. 2.49. Матричная объемная диаграмма
Рис. 2.50. Способ группировки grouped
В приведенных выше примерах разметка осей у и х выполнялась
автоматически. Однако функции ЬагЗ и ЬагЗЬ допускают задание монотонно
возрастающего или убывающего вектора у, с помощью которого может быть
изменена разметка диафаммы вдоль оси у — ЬагЗ (у, z). С помощью еще одного
параметра w можно управлять шириной столбцов — bar3(z,w) или
ЬагЗ {у, z,w>. По умолчанию ширина столбиков равна.0,8 см.
Пошаговые вычисления в командном окне
83
Рис. 2.51. Способ группировки stacked
2.7.3. Круговые диаграммы
Круговые диаграммы, состоящие из плоских или объемных секторов
(аналогов кусков пирога), строятся с помощью функций pie и pie3 (пример
2.26). В простейшем случае вектор q, содержащий к положительных
компонентов, генерирует к секторов, центральный угол которых пропорционален
вкладу каждого компонента в общую сумму. По умолчанию против каждого
сектора помещается его процентный вклад.
! Пример 2.26. Круговая диаграмма
» q = [1,2,4];
>> colormap cool
» pie(q)
» pie3(q)
Построение секторов в плоской диаграмме начинается с "севера" и
осуществляется против часовой стрелки. Для объемных диаграмм начало отсчета
располагается на "северо-западе". Результаты работы указанных команд
приведены на рис. 2.52 и 2.53.
На рис. 2.53 видно, что некоторые надписи расположены не Очень удачно.
Для того чтобы обратить внимание на отдельный сектор или группу
секторов, их принято немного выдвигать из "пирога".
84
Глава 2
'" 57%
l
Рис. 2.52. Плоская круговая диаграмма
Рис. 2.53. Объемная круговая диаграмма
Создание таких вьшеляюшихся элементов обеспечивается заданием еще
одного аргумента такой же размерности, что и вектор q. Выдвигаемым секторам
в новом векторе должны соответствовать ненулевые элементы. Например:
» v=[0,l,0] ;
» pie(g,v); % результат на рис. 2.54
» т=[1,0,0];
» pie3[q,m) % результат на рис. 2.55
Вместо процентных меток мы можем разместить свои надписи,
предварительно сформированные в массиве ячеек (пример 2.27).
29%
14%
4
-;w&jI•k-Vi'- '■ "
Пошаговые вычисления в командном окне
85
Рис. 2.54. Выделен второй сектор
Рис. 2.55. Выделен первый сектор
!;Приме^.27; Метки на круговой диаграмме - д---;. . ■ *=. ■ ^. у- gg \
» z= [1.249-,1, 249,1,249,1,249] ;
» s=('CeBep', ",'Запад ', ",'Юг',",' Восток',");
» pie(z,s); colormap(cool)
В приведенном выше фрагменте кроется небольшой секрет. Во-первых,
чтобы надписи сторон света были точно расположены на своих местах,
пришлось завести для них очень узкие секторы и довести общее количество
секторов до 8. Во-вторых, чтобы надписи Запад и восток не сливались с
изображением, к ним пришлось добавить по паре пробелов. Результат
приведен на рис. 2.56.
86
Глава 2
Запад
^
й-.; -:■ "
Ь_
ч
Север
!'
< I, '■- -- - V
Иг
Воолок
Рис. 2.56. Стороны света на круговой диаграмме
2.7.4. Площадные диаграммы
В площадных диаграммах график первой функции у: (х) строится обычным
образом, отмеряя ординаты yi{xi) от оси х. График второй функции y.v(x)
как бы наслаивается на предыдущий график, отмеряя свои ординаты от
ординат предыдущей функции — yitxil+yHxi). График следующей функции
суммируется с ранее накопленной суммой и т. д. Площадь каждого трафика
выделяется своим цветом, чтобы продемонстрировать вклад очередного
слагаемого в общую сумму.
Пусть, например, итоговый график задан значениями элементов двумерного
массива (пример 2.28).
1 Пример 2.28. Задание площадных диаграмм с помощью массива '
v =
18 3
7 5 '9
4 2 6
Его столбцы определяют значения функций-слагаемых. Это означает, что
график первой функции задан точками (1, 1), (I, 7) и (1, 4), график второй
функции — точками (1, S), (2, 5) и (3, 2), график третьей функции —
точками (1, 3), (2, 9) и (3, 6). Каждый из компонентов в отдельности представлен
графиками в отдельных подокнах (рис. 2.57). Соответствующая площадная
диаграмма воспроизведена в правом нижнем подокне с помощью функции
а-геа:
» у=[1 8 3; 7 5 9 ; 4 2 6];
» yl=[l,7,4];
Пошаговые вычисления в командном окне
87
» у2=[8,5,2];
» уЗ=[3,9,б];
» subplot[2,2,1); plot(у1);grid on
» subplot (2,2, 2).; plot (y2) ;grid on
» subplot(2,2,3); plot(y3);grid on
» subplot(2,2,4); area(y); grid on; colormap(cool)
Рис. 2.57. П/ющадная диаграмма и ее составляющие
<1 3<ш S99
Глава 3
Типы данных
3.1. Иерархия
типов данных в MATLAB
В справочных файлах приведена схема (рис. 3.1), на которой представлены
I6 фундаментальных типов данных (или классов), определенных в MATLAB.
Из схемы явствует, что базовым классом данных является массив (array).
Наряду с пустыми, неинициализированными массивами язык MATLAB
позволяет обрабатывать векторы (массивы размерности lx/j или ях1), квадратные и
прямоугольные матрицы (массивы размерности пхт), массивы более высокой
размерности.
ARRAY
char
cell
NUMERIC
int8. uint8,
int16, uint16,
int32, uint32.
int64, uint64
single
stucture
I
user class
Java class
LOGICAL
function handle
double
I
sparse
Рис. 3.1. Схема иерархии типов данных
В гл. 2 довольно подробно обсуждалась специфика представления числовых
массивов с элементами типа double, положенных в основу большинства
вычислительных процессов и сочетающих в себе представление как вещест-
90
Глава 3
венных, так и комплексных чисел. В этой главе мы остановимся более
подробно на других классах данных.
3.1.1. Символьные массивы (char arrays)
Символьные векторы (массивы размерности lx/z) представляют собой
обычные строки. Для задания их значений в правой части оператора
присваивания записывают цепочку символов, заключенную в одинарные кавычки
(пример 3.1).
; Пример 3.1. Символьный вектор .-..-■>&*■ .£&-\
» sv='abedefgh'
sv =
abedefgh
» whos
Name Size Bytes Class
sv 1x8 16 char array
Grand tonal Is 8 elements using 16 bytes
Мы уже упоминали, что каждый элемент типа char занимает в памяти
2 байта и представлен в кодировке ASCII Unicode. В MATLAB 7 устранены
моменты, имевшие место в ранних версиях и связанные с неприятием
русских букв "с" и "я":
>> гд='пуля'
rs =
пуля
» rs='условие'
rs =
условие
Символьная матрица (массив размера /их/») должна состоять из строк равной
длимы (пример 3.2).
; Пример 3.2. Символьная матрица
» sm=l'abedefgh';Ч234567В']
sm =
abedefgh
12345678
»■ whos
Типы данных 91
Name Size Bytes Class
sm 2x8 32 char array
Grand total is 16 elements using 32 bytes
Дня определения текущих длин, размеров и количества измерений
символьных массивов можно использовать функции length, size и ndims
(пример 3.3).
! Пример 3.3. Определение размеров символьных массивов ,<л. }
» sv='abedefgh';
» whos
Name Size Bytes Class
sv 1x8 16 char array
Grand total is 8 elements using 16 bytes
» size(sv) % возвращает число строк и число столбцов
ans =
1 '8
» length(sv) % возвращает количество символов
ans =
8
» ndIns (sv) % возвращает количество измерений
ans =
.2
» sm=['abedefgh';'12345678']
sm =
abedeigh
12345678
» size(sm) % возвращает число строк й. число столбцов
ans =
.2 8
» length(sm) % возвращает количество символов в строке (!)
ans =
8"
» ndims(sm) % возвращает количество измерений
ans =
2
92
Глава 3
3.1.2. Целочисленные данные в MATLAB
Ни один из универсальных алгоритмических языков не обходится без
целочисленных данных. MATLAB до версии 7 в этом смысле стоял
несколько особняком. Он допускал создание и хранение числовой информации в
виде одно-, двух- и четырехбайтовых форматов со знаком или без знака.
Во всех версиях пакета были предусмотрены функции конвертирования
вещественных и комплексных данных типа double в любой из допустимых
форматов целых и вещественных чисел (табл. 3.1), а также обратные
преобразования. Однако арифметические операции над целочисленными
данными до 7-й версии были запрещены.
Таблица 3.1
Функция Назначение
Диапазон допустимых
значений
int8 Преобразование в формат
однобайтовых целых чисел со знаком
uirvte Преобразование в формат
однобайтовых целых чисел без знака
intl 6 Преобразование в формат
двухбайтовых целых чисел со знаком
uintl 6 Преобразование в формат
двухбайтовых целых чисел без знака
int32 Преобразование в формат
четырехбайтовых целых чисел со знаком
uint32 Преобразование в формат
четырехбайтовых целых чисел без знака
int64 Преобразование в формат
восьмибайтовых целых чисел со знаком
uint64 Преобразование в формат
восьмибайтовых целых чисел без знака
double Преобразование числового аргумента
в формат вещественного числа с
удвоенной точностью
single Преобразование числового аргумента
в формат вещественного числа с
одинарной точностью
от-128 до 127
от 0 до 255
от-32 768 до 32 767
от 0 до 65 535
от-2 147 483 648
до 2 147 483 647
от 0 до 4 294 967 295
от-263 до263-1
от 0 до 264 - 1
От 2.225x1 ГГЗСВ
до 1.798x10+30В (по модулю)
От 1.175x10"38
до 3.403x10+38 (по модулю)
Версия MATLAB 7 принципиально отличается от предшествующих версий
не только тем, что в нее включены восьмибайтовые целые числа. Самое
существенное, что в новых целочисленных классах (кроме int64 и uint64)
Типы данных
93
определены все арифметические операции. Это может послужить важным
аргументом при выборе типа данных для решения целочисленных задач с
большими массивами информации. Например, в задачах обработки
графических изображений цветовые атрибуты пикселов кодируются
однобайтовыми значениями, которым соответствует тип uintB. Некоторые варианты
обработки целочисленных массивов приведены в примере 3.4.
I" "■-■■"" '- г ■"■ V- ;_£? :•"•■" :
! Пример 3.4. Целочисленные массивы -.*•-■ - > ;
» x=intl6(l'2)
х =
12
» whos
Name Size Bytes Class
x lxl 2 intl6 array
Grand to"cal is 1 elements using 2 bytes
» format hex
» x
X =
000c
» y=uintl6([5 25 30])
У =
0005 0019 OOle
» whos
Name Size Bytes Class
x lxl 2 intl6 array
у 1x3 6 uintl6 array
Grand total is 4 elements using 8 bytes
Как вы заметили, вывод целочисленных данных неплохо уживается с
форматом hex. Аргумент, преобразуемый к целому типу, может иметь дробную
часть, и тогда MATLAB использует стандартное округление, принятое в
математике (пример 3.5).
; Пример 3.5. Округление аргументов •' S" '-■. .*
» int8(2.1)
ans =
2
» int8 (2.5)
94
Глава 3
ans =
3
» int8(-2.5)
ans =
-3
» int(2.9)
ans =
3
Максимальное и минимальное значения, соответствующие тому или иному
целому типу, можно определить с помощью функций intmin и intmax:
» intmin('intlб')
ans =
-32768
» intmax('uint8')
ans =
255
Если конвертируемый аргумент выходит за пределы заданного диапазона, то
MATLAB возвращает левую или правую границу:
» int8(450)
ans =
127
» int8(-450)
ans =
-128
Точно такое же обрезание происходит и при получении результата,
выходящего за допустимые пределы:
» intS(100)+int8[150)
ans =
127
Вы можете включить режим выдачи предупреждения о выходе результата
операции за допустимые пределы, обратившись к функции intv/arning с
аргументом 'on':
». intwarning('on')
» x=int8(200)
Warning: Out of range value converted to intmin('int8') or
intmax('int8').
Типы данных ■
95
127
По умолчанию этот режим отключен (intwarningt 'off )).
Функции формирования стандартных матриц ones, zeros и eye могут быть
использованы для формирования целочисленных массивов при условии, что
последним аргументом задается строка с указанием типа (пример 3.6).
^„,.г..^,...^™у^..^...,„у...........?. „ ;...„ ?!,.Г.,..^„„,^....„^^™^... „.„ .,....„.
! Пример 3,6. Формирование стандартных матриц ^Щ^лТ^щ?
» x=ones{2,2,'int8')
х =
1
1
1
1
» y=zeros(2,3,'uint8')
У =
0
0
» г=еуе
z =
1
.0
» whos
Name
X
У
z
0 0
0 0
(2,'intl6'>
0
1
Size Bytes
2x2 4
2x3 6
2x2 8
Class
lnt8 array
uint8 array
intl6 array
Grand total is 14 elements using 18 bytes
Целочисленная арифметика в MATLAB 7 налагает ряд ограничений на
допустимые сочетания операндов, участвующих в выражениях. Так, например,
целочисленные операнды, входящие в формулу, должны быть одного типа.
То есть нельзя складывать однобайтовый скаляр или массив с двухбайтовым
операндом. Однако если один операнд (скаляр или массив) имеет целый
тип, то вторым операндом формулы может быть скаляр типа double
(пример 3.7). MATLAB выполняет такую операцию с удвоенной точностью
и преобразует результат к типу целочисленного операнда. Но когда
количество операндов в формуле больше двух, то вычисления могут привести к
неверным результатам (пример 3.8).
96 Глава 3
\ Пример 3.7. Комбинация целочисленного массива со скаляром типа double .
» int8([I 2 34 5])*0.8
ans =
12 2 3 1
Следует отметить, что версия MATLAB 7, как и любой новый программный
продукт, еще не прошедший достаточную обкатку, содержит определенное
количество ошибок. Одну из них нам удалось обнаружить на примере 3.8.
j Пример 3.8. Ошибка MATLAB.
>> int8(10)/int8[100)*20.5
ans =
О
»■ 20.5*int8(10)/int8(100)
ам =
1
С точки зрения программиста, обрабатывающего формулу слева направо,
приведенные выше результаты можно объяснить, но не оправдать. После
деления двух целых чисел (10/100) получается целочисленный 0, что и
предопределило первый результат. Во второй формуле MATLAB "сообразил",
что результат первого умножения (205) надо преобразовать к типу ints (т. е.
заменить на 127) и после деления на 100 получил целочисленную 1. С точки
зрения математика здесь нарушен закон коммутативности (перестановка
сомножителей привела к разным результатам). Видимо, правильней было бы
выполнить все операции в формате double, получив 2.05, а затем
преобразовать результат в целочисленный, т. е. в 2.
Еще одну несуразицу с перестановкой слагаемых удалось обнаружить на
примере 3.9.
j Пример 3.9. Другая ошибка MATLAB '" •
» 0.5+int8(10)/int8[120)
ans =
1
» CL25+int8(10)/inc8(100)+0.25
ans =
0
Типы данных
97
С точки зрения математика обе формулы идентичны, а результаты
вычислений это не подгверждают.
Над целочисленными операндами без знака можно выполнять поразрядные
битовые операции. Перечень соответствующих функций приведен в
табл. 3.2.
Таблица 3.2
Функция
bitand(ft,B)
bitor(А,В)
bitxor(A,B)
bitcmp(А,п)
bitset(А,п)
bitset(A,n,v)
bitget(A,n)
bitshift(A,n)
Выполняемое действие
Поразрядное логическое умножение
Поразрядное логическое сложение
Поразрядное исключающее ИЛИ
Инвертирование а с сохранением п битов
Установка n-го бита числа А в единицу
Установка n-го бита числа А в значение v (0 или 1)
Опрос значения n-го бита в числе А
Сдвиг двоичного кода А на п разрядов влево (п > 0) или
вправо (п < 0)
В двоичных операциях действуют следующие правила. Оба операнда,
участвующие в логических операциях and, or и хог, должны быть одного типа.
Результат выполнения операций стр и set не должен выходить за
разрядную сетку первого операнда. Те разряды, которые при операции сдвига
выходят за пределы разрядной сетки, теряются. Ниже приведены результаты
выполнения битовых операций над самыми короткими числами, которые
легко проверить.
» A=uint8([0 1; 0 1] ) ;
» B=uint8[[0 0; 1 1] ) ;
» T_AND=bitand(A,B)
T_AND =
0 0
0 1
» T_OR=bitor(A,B)
T_OR =
0 1
1 1
» Т XOR=bitxor{A,B)
98
Глава 3
T_XOR =
0 1
1 О
» C=uint8(5);
» bitcmpfc, &)
ans =
58
» bitset(C,2)
ans =
7
>> bitset [C, 3,0)
ans =
1
» bitget(C,3)
ans =
1
» bitget(C,2)
ans =
0
>> bitshifUC,2)
ans =
20
» bitshift(C,-l)
ans =
.2
3.1.3. Вещественные данные
с одинарной точностью (single arrays)
В отличие от данных типа double, где каждый элемент массива представлен
одним или двумя 8-байтовыми значениями, в массивах типа single (single
arrays) на каждую числовую составляющую отводится по 4 байга и тем
самым экономится 50% памяти. Однако диапазон представления числовых
данных здесь существенно ниже (I038 вместо 10308), да и точность
вычислений гарантирует получение, максимум, 7—8 значащих цифр вместо 15—16 в
стандартном режиме. В отличие от предыдущих версий MATLAB 7
разрешает почти все арифметические операции и над вещественными данными с
одинарной точностью. Воспринимают такие аргументы и многие
элементарные функции.
Типы данных
99
Более того, многие процедуры линейной алгебры в новой версии
адаптированы таким образом, что могут решать соответствующие задачи с такими
данными. При этом пользователь ничего не должен изменять в списке
параметров той или иной процедуры (пример 3.10).
| Пример 3.10 Массивы с одинарной точностью
» x=single(5)
х =
5
» whos
Name Size Bytes Class
x lxl 4 single array
Grand total is 1 elements using 4 bytes
» abs (y)
ans =
1.1180
Следует заметить, что преобразование в формат single может привести к
небольшим искажениям исходных данных. Это объясняется тем, что в
двоичном коде числа может быть достаточно много дробных разрядов, которые
при обрезании мантиссы и принятом правиле округления вызывают
небольшую погрешность:
>>forraat long
» single(3.4)
ans =
3.4000001
Ошибка на одну единицу в 8-й значащей цифре вполне допустима.
Арифметика с одинарной точностью тоже накладывает определенные
ограничения на операнды формулы, которые могут быть либо типа single, либо
комбинироваться со скалярами или массивами типа double. Результат
операции в последнем случае тоже имеет тип single:
» x=single(5)+single{3)
x =
8
>> y=single(5)+3
У =
8
>>■ whqs
100
Глава 3
Name Size Bytes Class
x lxl 4 single array
у lxl 4 single array
Grand total is 2 elements using 8 bytes
Для того чтобы узнать наименьшее и наибольшее значения для данных типа
single, МОЖНО обратиться к функциям realmin и realmax с аргуменгом-
строкой, задающей тип:
» realmin('single')
ans =
1.1754944е-038
>> realmax('single')
ans =
3.4028235e+038
Если при вычислениях с данными типа single результат превосходит
максимально допустимое значение этого типа, то MATLAB возвращает inf:
» realmax('single')*2
ans =
Inf
3.1.4. Разреженные матрицы
(sparse arrays)
Довольно много задач математической физики, теории прочности и
пластичности приводят к решению специфических систем линейных
алгебраических уравнений с так называемыми ленточными или блочными матрицами .
Кроме нескольких диагоналей или небольших блоков, заполненных
коэффициентами, в этих матрицах находится огромное число нулей (sparse
arrays). Держать их в оперативной памяти невыгодно, поэтому в ряде
прикладных программ было предложено хранить наряду со значениями
ненулевых элементов их индексы. Способы такого представления данных могут
быть разными. Например, можно хранить тройки (value, i, j). MATLAB
использует более экономный вариант, при котором разреженная матрица
рассматривается как вектор-столбеи, компонентами которого являются
разреженные векторы-строки. Ненулевые компоненты разреженных строк
требуют задания не двух индексов, а одного, на чем, собственно, и экономится
объем хранимой информации. На самом деле хранятся не индексы
отдельных элементов столбца, а диапазон индексов, соответствующий подряд
идущим ненулевым элементам. В MATLAB предлагается довольно много
функций по обработке разреженных матриц и по их преобразованию в
обычный матричный формат представления данных.
Типы данных
101
Для того чтобы представить себе экономию от хранения разреженных
матриц, приведем пример 3.11.
: —" :■• ....._....)..,. ■■ ■ --;:...-... - ;
; Пример 3.11. Разрежённая матрица ■. ■ ■%.?'■ ч *-*г,^Шш£= \
» а=еуе(100);
» b=sparse(eye(100)) ;
» whos
Name Size Bytes Class
a 100x100 80000 double array
b 100x100 1604 sparse array
Grand total is 10100 elements using 81604 bytes
В разреженных матрицах могут храниться элементы только типа double.
3.1.5. Структуры и массивы структур
(struct arrays)
Структуры, или записи (в C++ и Java — struct, в Pascal — record),
представляют собой тип данных, порожденный общепринятыми таблицами. Для
таблиц характерны строки данных единого формата, определяемого
заголовком таблицы. Каждая строка таблицы представлена последовательностью
полей. Одноименные поля образуют колонки таблицы, в которых
располагаются данные одинакового типа. Друг от друга поля отличаются
идентификаторами, соответствующими заголовкам колонок таблицы. Таблицы
широко используются в реляционных базах данных, они позволяют повысить
эффективность представления данных в памяти ЭВМ. ускоряют обмен с
файлами, повышают наглядность представления результатов работы многих
программ.
Представим себе простейшую таблицу с тремя колонками, содержащими
сведения об авторах (табл. 3.3), которую мы хотим оформить в виде массива
authors, включающего три структуры. Наименования колонок — полей
структуры — продублированы на английском языке, т. к. в идентификаторах
полей употребление русских букв запрещено.
Таблица 3.3
Фамилия, И. О. (Name)
Иванов И. И. ■
Петров П. П.
Сидоров С. С.
Возраст
31
32
33
(Age)
Телефон (Phone)
11-11-11
22-22-22
33-33-33
102
Глава 3
Одним из способов формирования структуры является использование
функции struct (пример 3.12), которая заполняет указанный элемент массива
структур. Аргументами этой функции являются пары, содержащие имя поля
и соотвегствующее значение. Вте предшествующие элементы массива
структур формируются как поля с такими же наименованиями, значения которых
заполнены пустыми матрицами 1x1. Очевидно, что в левой части оператора
присваивания удобнее заполнить последнюю структуру массива, иначе
изначально не будет создан массив нужного размера. Однако это вовсе
необязательно, и в первый раз мы можем вызвать функцию struct для создания
первого элемента массива структур. А потом добавлять последующие строки
таблицы. Дело в том, что размер массивавсе равно будет изменяться в
зависимости от длины значений, присваиваемых полям незаполненных ранее
структур. Тем не менее, формирование массива структур целиком позволит
избежать дополнительных затрат, возникающих при увеличении количества
элементов.
; Пример 3,12. Формирование структуры . ^-.
» authors(3)=struct('Name','Сидоров С.С.','Age',33,...
'Phone','33-33-33'),■
» who.3
Name Size- Bytes Class
authors 1x3 440 struct array
Grand total is 28 elements using 4 40 bytes
Теперь можно заполнить пустые поля в двух предшествующих структурах,
используя индексирование элементов массива и составные имена
соответствующих полей:
» authors(1),Name='Иванов И.И.';
» aut nors(1).Age=31;
» authors(1).Phone='11-11-11' ;
» authors(2).Name='Петров П.П.';
» authors(2).Age=32;
» authors(2).Phone='22-22-22';
С помощью функции fieldnames можно получить информацию об именах
полей указанной структуры:
» f ieldnames(authors)
ans =
'Name'
'Age'
' Phone-'
Типы данных
103
Однако для вывода содержимого полей приходится набирать имя каждой
структуры — элемент соответствующего массива:
» authors(1)
ans =
Name: 'Иванов И.И.'
Age: 31
Phone: 41-11-11'
» authors(2)
ans =
Name: 'Петров П.П. '
Age: 32
Phone: '22-22-22'
» authors(3)
ans =
Name: 'Сидоров C.C.'
Age: 33
Phone: '33-33-33'
Второй способ, который требует существенно меньших затрат по набору
исходных данных, использует групповое задание значений каждого поля в
виде списка ячеек (термин ячейка поясняется в следующем разделе). Список
ячеек заключается в фигурные скобки (пример 3.13).
; Пример 3.13. Список ячеек " !. ^^¾¾ '■■'-
; V.:. "Г. ::....:: ::....;: :....Ж:....:„Ш<т&$&Ж:. ,....*»«.:„: -.:-..,., •
» authors-struct('Name',{'Иванов И. И.','Петров П. П.',...
'Сидоров С. С.'>,'Age',{31,32,33},'Phone', {'11-11-11', '22-22-22', ...
'33-33-33'});
» v/hos
Name Size Bytes Class
authors 1x3 1058 struct array
Grand total is 67 elements using 1058 bytes
Может оказаться полезной и еще одна возможность сформировать массив
структур, содержимое полей которых заполнено одинаковой строкой
таблицы. Она достигается многократным размножением одной структуры с
помощью функции repmat (от англ. repeat matrix — повторить матрицу):
» authors=repmat(struct ('Name','Abe','Age',100,...
'Phone','00-00-00'),1,3);
104
Глава 3
Два последних аргумента функции repmat определяют первый и последний
индексы формируемых структур.
В существующем массиве структур легко добавить новое поле путем
присвоения значения в любом элементе массива:
» authors(2).gonorar=1500;
К двум оставшимся записям автоматически добавится пате с именем gonorar,
которое будет временно заполнено пустой матрицей размерности 1x1.
Для удаления ненужного поля из всех записей используется функция
rmf ield'.
» authors = rmfield(authors,'gonorar');
В качестве значения какого-либо поля структуры может, в частности,
выступать и массив. Тогда, чтобы добраться до конкретного значения в этом
массиве, необходимо использовать два индекса — индекс структуры
(например, d_s) в массиве структур и индекс конкретного элемента массива
(например, if) в заданном поле:
» у = riame_ms (i_s) .name_f (i_f) ;
Здесь через names обозначено имя массива структур, а через name_f — имя
поля в структуре. Как правило, в качестве индексов выступают либо
конкретные числа, либо значения переменных, пробегающие в цикле тот или
иной диапазон. Однако в некоторых задачах и имя массива, и имя поля
может вычисляться программным путем. Тогда имя нужного компонента будет
представлено неявно — как значение переменной символьного типа. В этом
случае для доступа к значениям полей структуры необходимо использовать
одну ИЗ функций — getf ield ИЛИ putf ield:
» у - getLield(var_ms,i_s,var_f,i_f);
>> putfield(var_ms,i_s,var_f,i_f, value);
Параметр value здесь представляет значение, засылаемое в указанное поле.
3.1.6. Массивы ячеек (cell arrays)
Числовые массивы состоят из элементов одного типа. Массивы структур в
простейшем случае представляют набор строк таблицы, устроенной по
единому формату (но в пределах одной записи содержимое полей может быть
разного типа). И тот, и другой тип массивов был хорошо известен в
системах программирования общего назначения. Однако в MATLAB появился
совершенно новый тип массивов cell array, в которых каждый элемент
может быть представлен значением любого типа, независимо от типа
соседних элементов. Каждый такой элемент называют ячейкой (cell) по аналогии с
электронными таблицами, где каждая клетка может содержать индивидуаль-
Типы данных
105
ное значение любого типа. Конечно, единообразные действия, которые
производились для нормальных массивов (например, поиск максимального
элемента, суммирование данных в столбце и т. п.), в массиве ячеек смысла
не имеют.
3.1.7. Массивы указателей на функции
(function handle arrays)
Еще одним типом данных, заслуживающим внимания, является класс
function_handle. С термином handle (произносится — хэндл) многие
программисты сталкивались при работе с файлами при создании подпрограмм
обработки событий в различных визуальных средах. Термин handle пока не
получил единообразной трактовки в отечественной литературе. Под этим
термином скрывается системный способ идентификации некоторых
программных компонентов. Так, например, при работе с файлами вместо их
идентификаторов (имен дисковых файлов или их полных спецификаций) в операторах
обмена указывается тем или иным способом созданный handle. Им может
быть конкретное число, которое операционная система присваивает
открываемым файлам (int fi=open...), или указатель на блок управления файлом
(см. в C++ описание типа file *fi;). Иногда этот термин именуют
дескриптором (т. е. описателем). На наш взгляд, наиболее точно термину handle в
русском языке соответствуют термины указатель или ссылка.
Указатель на функцию (function handle) обеспечивает возможность доступа
ко всей информации, необходимой для вычисления значения этой функции.
Создается такой указатель (а по терминологии MATLAB — массив
указателей) одним из двух следующим способов:
» fjl=@funl;
» f_h=atr2func('funl')
В результате и той, и другой операции создается указатель f_h, который
"смотрит" на функцию с именем funl. Первый вариант очень напоминает
присвоение адреса переменной указателю соответствующего типа в C++
(int х; int *рх=&х;). Указатель f_h может быть передан в качестве
аргумента другой функции:
» у = integral(a,b,f_h);
Для того чтобы функция integral могла воспользоваться значением
функции funl{x), она использует системную процедуру feval:
» z = feval(f_h,х) ;
В фирменных руководствах утверждается, что использование указателей
несколько повышает производительность интерпретатора при многократных
обращениях к функции.
106
Глава 3
3.1.8. Логические массивы (logical arrays)
Логические массивы (logical arrays) появляются в результате различных
проверок, выполняемых с помощью стандартных функций — isietter (проверка
на буквы), isspace (проверка на пробелы), isprime (проверка чисел на
простоту) и др. (пример 3.14). Элементы логического массива занимают в памяти
по одному байту, в котором может находиться либр 1 (логическая истина),
либо о (логическая ложь).
| Пример 3.14. Логический массив ■ ■"'!*3„*:''*"- Г' '«.v"". ]
>> А=[2 3 4 5 6 7 8 9];
>> isprime(А)
ans =
11010100
» who's
Name Size Bytes Class
A 1x8 64 double array
ans 1x8 8 logical array
Grand total .is 16 elements" using 72 bytes
Другим способом создания логических массивов является использование
логических констант true и false, эквивалентных однобайтовым 1 и 0:
» x=[true false true]
х =
10 1
» whos
Name Size Bytes Class
x 1x3 3 logical array
Grand total is 3 elements using 3 bytes
Для создания логических массивов, все элементы которых одновременно
являются либо истиной, либо ложью, можно воспользоваться функциями
true ИЛИ false:
» x=true(2)
х =
1 1
1 1
» y=true(2,3)
Типы данных
107
У =
1 1
1 1
» z=false([2
■z =
0 0
0 0
» а=[5 б];
» v=false(a)
V =
0 0
0 0
0 0
0 0
0 0
1
1
3]>
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Единственный числовой аргумент в указанных функциях задает размерность
квадратной матрицы: два числовых аргумента определяют количество строк
и количество столбцов. Если в качестве аргумента выступает массив с
целочисленными элементами, то их значения и определяют размерность
создаваемого логического массива.
3.1.9. Создание массивов
из данных разного типа
Может быть, это и экзотика, но MATLAB 7 разрешает формировать
символьные, числовые и логические массивы из комбинации данных разного
типа. При этом система руководствуется определением типа
результирующей матрицы по сочетаниям пар типов данных, представленным в табл. 3.4.
Таблица 3.4
Тип char int single double logical
char
int
single
double
logical
char
char
char
char-'
Запрещено
char
int
int
int
int
char
int
single
single
single
char
int
single
double
double
Запрещено
int
s ingle
double
logical
108
Глава 3
Ниже приводится несколько примеров, заимствованных из справочных
файлов. На наш взгляд, пользоваться такими возможностями не стоит
(пример 3.15).
: Пример 3.15. Экзотическое формирование массивов ..--.■ ., ^¾¾¾¾¾¾ •'!
»% Пустой массив в списке значений игнорируется
» А = [5.36; 7.01; []; 9.44]
А =
5.3600
7.0100
9.4400
» % Сочетание данных типа single и double
» х = [single(4.5) single(-2.8) pi 5.73*10Л300]
x =
4.5000 -2.8000 3.1416 Inf
» .%■ Сочетание данных типа int8 к double
>> х = [int8(21) int8f-22) int8{23) pi 45/6]
x =
21 -22 23 3 8
» % Сочетание данных типа char и double
» x = ['А' 'В' 'С 68 69 70]
x =
ABCDEF
» % Сочетание данных типа logical и double
» х = [true false false pi sqrt(7)J
x =
1.0000 0 0 3.1416 2.6458
3.2. Программа тестирования данных
В состав пакета MATLAB включена программа explore, которая
анализирует тип данных, указанных в качестве аргумента, и отображает значения всех
переменных, относящихся к данному аргументу. Программа эта находится в
каталоге ...\MATLAB7\extern\examples\mex, который надо сделать текущим
перед ее запуском:
» cd (' с: \MATLAB7\extern\examples\mex');.
» str='Привет';
» explore(str);
Типы данных
109
Результат работы этого фрагмента таков:
Name: prhs[0]
Dimensions: 1x6
Class Name: char
(.1,1) Привет
Предыдущая версия этой программы из пакета MATLAB 6.5 в качестве
значения параметра Name выводила имя своего аргумента. В новой версии при
любом аргументе программа explore почему-то вьщает одно и то же. Один
из разделов справочной системы предлагает опробовать программу на
некотором наборе данных разного типа, и приводимый ниже протокол получен
по этой рекомендации:
» а=[]; % пустой массив
» explore(а);
Name: prhs[0]
Dimensions: 0x0
Class Мате: double
» а=[1 2 3J; % вектор-строка
» explore(а)
Wame: prhs[0]
Dimensions: lx'3
С]ass Name: double
(1.1) = 1
(1.2) = 2
U,3) = 3
» a=[l;2;3]; % вектор-столбец
» explore(a);
Uame: prhs.[0]
Dimensions: 3x1
Class Name: double
110
Глава 3
(1,1) = 1
(2,1) = 2
(3,1) = 3
» а={1 2 3}; % массив ячеек
» explore(а) ;
Name: prhs.101
Dimensions: 1x3
Class Name: cell
tota] num of cells = 3
Cell Element: (1/1)
Dimensions: lxl
Class Name: double
(1,1) = 1
Cell Element: (1,2)
Dimensions: lx1
Class Name: double
(1,1) = 2
Cell Element: (1,3)
Dimensions: lxl
Class Name: double
(1,1) =-3
» explore 12 3
Name: prhs[0]
Dimensions: lxl
Class Name: char
(1,1) 1
Типы данных
111
Name: prhs[l]
Dimensions: lxl
Clas s Name: char
(1,1) 2
Name : prhs[2]
Dimensions: lxl
Class Name: char
(1,1) 3
» a=int8([l 2 3]);
» explore(a);
Name: prhs[0]
Dimensions: 1x3
ciass Name: int8
(1.1) = 1
(1.2) = 2
(i,3) = 3
» a=sparse(eye(3));
» explore (a) ;
Name: prhs[0]
Dimensions: 3x3
Class Name: sparse
(1.1) = 1
(2.2) = 1
(3.3) = 1
» explore (sttuet ('Name",'Иванов V\. И. ', 'Age', 31, 'Phone', '11-11-11')) ,-
Name: prhs[Q]
Dimensions: lxl
Class Name: struct
112
Глава 3
(1,1).Name
Dimensions: lxll
Class Name: char
(1,1) Иванов И. И.
(1,1).Age
Dimensions: lxl
Class Name: double
(1,1) = 31
(1,1).Phone
Dijiiensions: 1x8
Class Name: char
(1,1) 11-11-11
» explore(1, 2, 3)
Name: prhs[0]
Dimensions: lxl
Class Name: double
(1,1) = 1
Name: prhs[l]
Dimensions: lxl
Class Name: double
(1,1) = 2
Name: prhs[2]
Dimensions: lxl
Class Name: double
(1,1) = 3
Типы данных
113
3.3. Анализ типа данных
и состояния элементов массивов
Довольно многие системные и пользовательские функции допускают в
качестве некоторых параметров данные разного типа. Очевидно, что обработка
таких данных не всегда может вестись по единому алгоритму. Поэтому в
системе MATLAB предусмотрен довольно большой набор функций,
выполняющих анализ на принадлежность данных тому или иному классу и
контролирующих состояние объектов (например, на начичие в числовом
массиве нечисловых данных или бесконечных значений).
Проверка на принадлежность объекта тому или иному типу данных
осуществляется с помощью функции isa!
a = isa(имя_объекта,'класс');
Функция isa возвращает логическую истину (a=i), если объект с указанным
именем принадлежит заданному классу. В противном случае значением
функции isa является логическая ложь (а=о). Список значений аргумента
'класс' приведен в табл. 3.5.
Таблица 3.5
Класс
Функция isa проверяет, является ли ее первый аргумент:
char
numeric
logical
intB
uint8
intl6
uintl6
int32
uint32
int64
uint64
single
double
cell
struct
function handle-
символьным массивом
числовым массивом (целочисленным или вещественным)
логическим массивом
массивом однобайтовых целых чисел со знаком
массивом однобайтовых целых чисел без знака
массивом двухбайтовых целых чисел со знаком
массивом двухбайтовых целых чисел без знака
массивом четырехбайтовых целых чисел со знаком
массивом четырехбайтовых целых чисел без знака
массивом восьмибайтовых целых чисел со знаком
массивом восьмибайтовых целых чисел без знака
массивом вещественных чисел с одинарной точностью
массивом вещественных чисел с удвоенной точностью
массивом ячеек
массивом структур
массивом указателей на функции
114
Глава 3
В качестве аргумента 'класс' у функции isa может выступать
нестандартный класс, объявленный пользователем. В справочных файлах такая
возможность демонстрируется на объекте типа poiynom:
polynom_obj = poiynom([1 0 -2 -5]);
isa(polynom_obj, 'poiynom')
ans =
1
Ко второй группе функций, анализирующих свойства своих аргументов,
относятся более 30 процедур. Их единственным аргументом является имя
объекта, значения компонентов которого подвергаются той или иной
проверке. Размерность результата, возвращаемая любой из этих функций,
совпадает с размерностью аргумента. Проверке подвергается каждый
компонент аргумента, и если анализируемое свойство удовлетворяет
предназначению функции, то в соответствующий элемент результата заносится
логическая истина. В противном случае в соответствующий элемент
результата заносится логическая ложь. Более подробно специфика
некоторых функций обсуждается ниже.
Функция isreai(q) проверяет, являются ли элементы массива q
вещественными или комплексными числами (пример 3.16). Если хотя бы один
элемент указанного массива содержит мнимую часть (даже равную нулю), то
функция isreal возвращает логическую ложь. Если переменная х имеет
вещественное значение, то y=compiex(x) представляет комплексное значение
с нулевой мнимой частью. Но isreal (у) =о. Если аргументом функции
isreal является массив ячеек, отдельные элементы которого —
комплексные числа, то в возвращаемом векторе значений нулевые компоненты
соответствуют комплексным ячейкам, а единичные компоненты — всем
остальным (среди остальных компонентов массива могут быть и нечисловые
ячейки).
| Пример 3.1.6, Демонстрация райоть! функции isreal ()■..■;
» qll, l}-'Text'; %■ строка
» q{l,2}=3; %" число типа double
» g{l,3}=magic(2); % массив 2x2 типа double
» q{l,4}=l+i; % комплексное число
» q{l,5}=isreal(pi); % логическое значение
» q
q =
'Text' [3] [2x2 double] [1.0000+ l.OOOOi] [1]
» for j=l:5, a{j)=isreal(q{l,j}); end
Типы данных
115
» а
а =
1110 1
Функция isnuraeric(q) проверяет, являются ли ее аргументы числовыми
данными, в разряд которых причислены вещественные и комплексные
значения (пример 3.17). А вот символы, строки, логические значения,
структуры и массивы перечисленных данных к группе чисел не относятся.
Для приведенного выше массива ячеек q эта проверка дает следующие
результаты.
j Пример 3.17. Демонстрация работы функции isnumeric() ■, '
» for 3=1:5, a(j)=isnumeric(q{l, j[); end
» a
a =
0 1110
Функция ischar(q) проверяет, являются ли ее аргументы символьными
данными. Для приведенного выше массива ячеек q эта проверка дает
результаты, представленные в примере 3.18.
I Пример 3.18. Демонстрация работы функции ischar()
» for j=l:5, a(j)=ischar(q{l,j}); end
» а
а =
1 о о о о
Функция isiogicai(q) проверяет, являются ли ее аргументы данными
логического типа. Для приведенного выше массива ячеек q эта проверка дает
следующие результаты (пример 3.19).
j Пример 3.19. Демонстрация работы функции Islogical ()
» fox j=l:5, a(j)=islogical(q{l,j}); end
» a
a -
о о о о l
116
Глава 3
Функции iscell(q) и iscellstr(q) позволяют узнать, является ли аргумент
q массивом ячеек и представлена ли каждая ячейка строкой (пример 3.20).
I, Пример 3.20. Демонстрация работы функций iscell (): и iscellstr () ■&- w-:'r i
» iscell(q)
atis =
1
» iscellstr(q)
ans =
0
С помощью функции isstruct можно убедиться, является ли ее аргумент
структурой (пример 3.21).
: Пример 3.21. Демонстрация работы функции isstruct ()
» a.fl='abc';
» a.f2=[0 1 2];
» a.f3=[{'abc,}/l0,l,2}];
» а
а =
fl: 'abc'
f2: [0 1 2]
f3: ('abc' [0] [1] [2]}
» isstruct(a)
ans =
1
Функция issparse(A) проверяет, является ли матрица а разреженной. Если
это так. то функция возвращает логическую истину.
С помощью функции isempty можно убедиться в том, что ее аргумент
представлен пустым массивом (пример 3.22).
| Пример3.22. Демонстрация работы функции isempty 6 ' ч-'у г ..''-
>> х=П,-
» is'empty'(x)
ans =
1
Типы данных
117
Функции isfinite(A), isinf (А) и isnan(A) анализируют значения
элементов вещественного массива а и выясняют, какие из них принадлежат
к допустимому диапазону числовых значений (Finite — конечный), к
бесконечным значениям (infinite — бесконечный), к неопределенным
значениям (NaN — Not a Number) — пример 3.23.
;■ Пример 3^23. Демонстрация работы функций isf inite (), isinf () и ienan ()'Р 'i
» х=[1 0 inf nan];
» y-l./x
Warning: Divide by zero.
У =
1 Inf 0 NaN
» zf=isfinite(y)
zf =
10 10
» zi=isinf(y)
zi =
0 1 D 0
» zn=isnan(y)
zn =
0 0 0 1
Для выделения букв в символьной строке или в символьном массиве можно
воспользоваться функцией is letter (пример 3.24).
; Пример 3.24..Дёмонс1 рация работы функции is letter () Й: .*"•■*; i;w ^'i
» x='alb2c3';
» isletter(x)
ans =
10 10 10
>> y=I'al,;,b2';,c3']
У =
al
b2
c3
118
Глава 3
>> isletter(y)
ans =
1. О
1 О
1 О
Функция isprime(д) выясняет, какие элементы массива а являются
простыми числами. Проверяемые числовые значения должны быть
положительными целыми и не превосходить по величине 232. В противном случае
функция isprime выдает сообщение об ошибке. К спорному моменту
относится значение isprime (1)=0. Ряд математиков относит единицу к простым
числам, т. к. она не имеет других делителей кроме 1 и самой себя.
С помощью функции issorted(v) можно проверить, упорядочены ли по
возрастанию компоненты числового или символьного вектора v
(пример 3.25). Если первым аргументом этой функции является двумерный
массив — issorted(A, "rows'), — то проверка упорядоченности
распространяется на каждый столбец матрицы а.
[Пример 3.25. Демонстрация работц функции issortedO v --
» а=[1 2 3 4 5];
» issorted(a)
ans =
1
» b=[5 4 3 2 1];
» issorted(b)
ans =
0
» c='abc';
'». issorted(c)
.ans =
1
» d='bac';
» issorted(d)
aris =
0
» e=[l 2 3; 2 3 4]
Типы данных
119
12 3
2 3 4
» issorted(е,'rows']
ans =
1
3.4. Редактирование массивов
Массивы, сформированные вручную или полученные в результате
вычислений, хранятся в рабочем пространстве (workspace). Любой из них или
несколько одновременно могут быть подвергнуты коррекции с помощью Array
Edilor (Редактор массивов). Последний вызывается двойным щелчком по
имени массива в рабочем пространстве (рис. 3.2).
Top/Bottom Split
Left/Right Split
Tile
Maximize
Float т
,>MATLAB
File Edit View Graphics Debug Desktop Window Help
Shcdcus .ilHawluAiJd .£|VVbflt-sr4ew
v-'-trhspCCCf .
is tf ® «s *'□ -F
Мяте V | v«*J<t
EBB IJOO.JOO)
EBa ilZJ.4 5 6]
«1 1
rjtfjyiftajjd Window
■-> A=(l 2 3; 4 5 fi]
A -
12 3
(15 6
» B=[iaO;200I
В =
lDi)
200
» X
■■ l\
1 СКИЖ
double
double
jj
.* X
d
riArra Editor
- .
L. i
?. ...
У
■:- - T
..|ГТ
*м a«ii [ - _J
г- <=■ 1
э
-J
±1
i i
vl iool
3
6
7
If
.of
11
'12
Ail
HfilEI
* X
E Ш В ЁР]о]
2 Э
. . I
Рис. 3.2. Редактирование массивов А и В
Для размещения двух или более массивов поле редактора можно разбить
несколькими способами с помошыо управляющих кнопок:
О Tile — в клетках матрицы;
П Left/Right Split — в вертикальных колонках;
5 Зак 8W
120
Глава 3
О Top/Bottom Split — в горизонтальных полосках;
О Float — друг за дружкой;
О Maximize — текущая таблица занимает все поле.
Для изменения значения элемента массива необходимо либо с помощью
клавиш управления курсором, либо используя мышь, выделить нужную
ячейку и набрать в ней новое значение. Ввод изменяемого числа
завершается нажатием клавиши <Enter>. Новое значение немедленно отображается в
соответствующей позиции колонки Value (Значение) в рабочем
пространстве (рис. 3.3).
-ДМАТЬАВ
File Edit View. Graphics Debug Desktcp 'Window Help
StotM: _'J How to Add И WioVs New
t-i&rkspacB * x
■й ill © Вв©1*:Ы -||n.- J
hiame '" j Veiue | Cibm
Ше [I00;20] double
El A [12 3,4 5 6] double
Command Window» i> x
» A=[l 2 3; 4 Ъ 6] ±_
A =
12 3
4 5 6
» B= [100:.2()0]
E = _J
100
f ZOO ZJ
^1 Shirt |
ЙArray Editor
!й 1 * щ ш. О1 и
i i i a,-i
ll ll 2
2 4( ___J,
W - \ - "
6i 1
7 ; :
V
S
10
и
12-
Ia »![b~~4
_ _ _
- ] 'И ' Stoci:|
." ,-. ■«• V
3
-
Г '"
±J
,.,..^1
^^^■^M
1
J..
'J-
_4_
5
6
7:
"fi
* ' ,00
zc
ИПП
2
S
10 |
il
zU
-
—
3
: il
- - ,i
► 1
1
Л
Рис. 3.3. Изменение значения В (2)
Окно с гем или иным массивом можно снять с якоря и перетащить на более
удобное место. В этом случае к окну автоматически приклеивается меню
(рис. 3.4). С помощью команды View | Numeric Array Format (Вид | Формат:
числовой массив) можно выбрать подходящий формат отображения
числовых данных. Команды меню Desktop (Рабочий стол) позволяют вновь
поставить на якорь текущее окно или все окна-массивы, находящиеся в
свободном плавании.
Типы данных
121
Замечание
С помощью Array Editor (Редактор массивов) можно изменять векторы или
матрицы. Массивы более высокой размерности в этом редакторе не
обрабатываются.
Гм]
F^^^^^H
File Edit f Vk
n
2
3
4
s
'6
'■ i i
20
7 I
Bj
9.
<l "
3W Graphics Debug Desktop Wind
tumeric Array Format ► * short .
5oiJpOriciU'va! , shortE
_
long
longE
longG
hex
,„ bank
rational
ow
■ - n|x|
Help
I 6
—
—
•»■
- 3
"▼■ I
► I
'
Рис. 3.4. Окно с массивом В, снятое с якоря
I
Глава 4
Программирование
вычислительных процессов
До сих пор мы использовали командное окно MATLAB в режиме диалога
пользователя с системой. Пользователь набирал в текущей строке очередную
команду и нажимал клавишу <Enter> — система выполняла
соответствующее действие и, при необходимости, выдавала результат этого действия. Все
набираемые команды повторялись в окне Command History (История
команд) и запоминапись в специальном стеке, откуда могли извлекаться для
повторного выполнения ранее набранных действий или для формирования
похожих команд. Однако такой пошаговый режим хорош только для
разового расчета. Даже повторение одной и той же вычислительной схемы с
небольшой модификацией алгоритма или с изменением исходных данных в
пошаговом режиме превращается в обременительное занятие.
4.1. Скрипты и функции
В простейшем случае мы могли бы включить ту же самую цепочку команд в
текстовый файл, записать его на диск, а затем вызвать и уже автоматически
выполнить, не нажимая клавишу <Enter> после очередной команды.
Подобного рода программы по терминологии MATLAB принято называть
скриптами (scripts). В книгах некоторых российских авторов для их
обозначения используют термин сценарий, хотя с этим словом ассоциируются
совершенно другие понятия. Главной особенностью скриптов является то, что
они работают только с переменными Workspace (Рабочее пространство).
Скрипт может извлекать данные из файлов, запрашивать их у пользователя,
обращаться к любым стандартным и нестандартным функциям. Несколько
скриптов могут работать последовательно друг за другом, передавая данные
следующему скрипту через общее рабочее пространство или запоминая
промежуточные результаты в файлах. Однако отсутствие локальных
переменных в скриптах затрудняет Создание цепочек программ из-за
необходимости согласованного использования общих переменных. Скрипт может
быть подготовлен в любом текстовом редакторе и записан в дисковый файл
124
Глава 4
с расширением т. Однако MATLAB располагает собственным редактором
гп-файлов, который вызывается командой File | New | M-File (Файл | Создать |
М-файл) — рис. 4.1.
-Amatlab НПО
File Edit Debug Desktop. Window Help _ _
Save Workspace As.., Orl+S GUI
Ж Editor - Untitled*
File Edit Tert СЫ1 Tools Debug Desktop Window Help
d & a |"v Vsa ^ -• \&i« t. aia'!"ёia ib >» ж^р^з
1 a=l
Z +у,с i=i:5
3 a=a'ri
Д end
5 a
Рис. 4.1. Окно редактора кода.
Строки, набираемые в окне редактора, автоматически нумеруются. Это
позволяет идентифицировать сообщения об ошибках набора, выдаваемых в
командное окно. Обратите внимание на специфику набора строк
программы. Если в языке С каждый оператор завершался точкой с запятой, то в
языке MATLAB точка с запятой в конце оператора подавляет вывод
результата. Вторая неожиданность — формат оператора цикла, который па С
выглядел бы следующим образом:
for(i=l; i<=5; i++)
По аналогии с языками Fortran и Basic единичное приращение
управляющей переменной цикла можно опускать (более полный формат MATLAB —
for i=i:i:5). Наконец, еще одно наследие Basic, в.котором тело цикла for
завершается оператором next. В MATLAB нет операторных скобок, таких
как в С и Pascal, в которые заключаются операторы, образующие тело
цикла. Поэтому для определения его конца необходимо использовать оператор
end. Этим же оператором в MATLAB завершаются и другие структурные
единицы (if, switch, try, while).
Наконец, 5-я строка включена в текст программы только для того, чтобы
увидеть результат вычисления факториала. Конечно, в MATLAB имеются и
другие средства вывода результатов, но мы воспользовались простейшим
вариантом отображения значения переменной.
шли
вэ ш в е [□
Программирование вычислительных процессов
125
Для запуска фрагмента, представленного на рис. 4.1, необходимо выполнить
команду Run (Запуск) в меню Debug (Отладка) или нажать клавишу <F5>.
Результаты его работы появятся в командном окне, т. к. никаких других
окон для визуализации результатов расчета мы не предусмотрели:
а =
120
»
Для запоминания программы, набранной в окне редактора кода, можно
воспользоваться командой File | Save As (Файл | Сохранить как). Пример,
приведенный выше, мы запомнили под именем fact5. Для его повторного
выполнения в текущей строке командного окна достаточно набрать имя
файла:
» facts
а =
120
»
Более удобной разновидностью гп-файлоп являются функции, первой
строкой которых является заголовок, использующий оператор function. В
отличие от скриптов, функции могут получать исходные данные в виде списка
входных параметров и возвращать результаты своей работы также в виде
списка выходных параметров. Если некоторые переменные Workspace
(Рабочее пространство) объявлены глобальными (оператор global) и такое
объявление global с указанием имен общих переменных присутствует в теле
функции, то функция имеет доступ к указанным переменным. Эта идея в
явном виде заимствована из Fortran, хотя там был разработан более гибкий
механизм блоков обшей памяти (оператор соммоь?), позволявший
общающимся модулям называть общие переменные по-разному, сохраняя их
порядок и тип данных в общих блоках. И только имена блоков у них должны
были называться одинаково.
Одной из самых важных особенностей функций является аппарат локальных
переменных. Все переменные, появляющиеся в теле функции, за
исключением глобальных переменных, входных и выходных параметров, считаются
локальными. Они образуют локальное рабочее пространство и доступны
только в теле породившей их функции, и никакие, скрипты или другие
функции воспользоваться ими не могут. Это развязывает руки при
написании программ-функций, т. к. имена локальных переменных не надо ни с
кем согласовывать.
При написании программ-функций требуется, чтобы имя m-фаила, в
котором запоминается программа, обязательно совпадало с именем функции.
Пример более универсальной программы, вычисляющей п!, может быть на-
126
Глава 4
писан так, как представлено в примере 4.1, и должен быть сохранен под
именем factn.m.
I Пример4.1. Функция вычисления факториала €№.;■„■. ■}»'?. -^^Щ^.'-Щ
function y=factn(n)
k=l;
for<i=l:n)
k=k~i;
end
y=k;
Для вычисления 5! достаточно набрать в текущей строке команду:
»k-factn(5)
к =
120
»
В любом m-файле, подобно языку C++, можно описать несколько функций.
Самая первая из них обладает тем преимуществом, что ее можно вызвать извне.
Все остальные функции считаются внутренними и доступны только в рамках
данного m-файла. Их принято называть подфункциями (subfunctions).
Система MATLAB выполняет m-файлы, как правило, в режиме
интерпретации, что существенно снижает скорость решения задач по сравнению с
возможностями компилирующих систем. С целью повышения
производительности MATLAB в режиме интерпретации использует промежуточный
псевдокод (так называемый p-code — от англ. pseudocode). Происходит такая
замена исходного текста при первом обращении к скрипту или функции.
Псевдокод позволяет свести к минимуму работу по синтаксическому
разбору многократно выполняющихся операторов программы. Особенно это
важно при повторных вызовах функций. Псевдокод остается в памяти либо до
конца сеанса, либо до очистки оперативной памяти с помощью одной из
команд:
Clear имя_функции % удаление конкретного, псевдокода
clear functions % удаление псевдокодов всех функций
clear all % удаление всех функций и переменных
Любой m-файл может быть превращен в псевдокод с помощью процедуры
pcode:
pcode имя_п>-файла
Программирование вычислительных процессов ' 127
Результатом ее работы является двоичный файл с тем же именем и
расширением р. Такая предварительная замена исходного текста позволит
сократить время обработки файла при его первоначальной загрузке, а также
сохранить в тайне исходный текст алгоритма.
4.2. Специфика выполнения операций
При составлении алгебраических выражений MATLAB разрешает
использование традиционных знаков арифметических операций и символов
специальных операций, полный список которых приведен в табл. 2.3.
Но даже такие традиционные операции, как сложение, в выражениях
MATLAB выполняются особым способом. Самым привычным является
сложение скалярных величин (т. е. массивов размерности 1x1),
соответствующее аналогичному действию в большинстве алгоритмических языков.
Если обоими операндами являются массивы одинаковой размерности, то
осуществляется покомпонентное сложение элементов с одинаковыми
индексами. Такой подход в свое время наблюдался в ранних версиях Basic,
включавшего операторы типа мат а=в+с. Однако если в MATLAB к массиву
любой размерности добавляется скалярная величина, то она добавляется к
каждому элементу массива. По сути дела, добавляемое скалярное значение
преобразуется в массив такой же размерности, что и первое слагаемое
(аналог приведения типов в выражениях с разнокалиберными операндами),
и каждый элемент расширенного массива равен этому значению. Попытку
сложить массивы разной размерности (за исключением случая, когда один
из операндов — массив 1x1) система пресекает с выдачей соответствующего
сообщения об ошибке.
Аналогичное приведение типов выполняется для большинства операций,
когда одним из операндов является массив, а вторым — скаляр.
При выполнении логических операций над числами действует соглашение,
принятое в С, — ненулевые значения рассматриваются как истина, а
нулевые как ложь. В качестве небольшой странности языка MATLAB отметим,
что такая распространенная логическая операция, как исключающее ИЛИ,
здесь подключена в виде функции хог (х, у).
•
4.3. Синтаксис операторов MATLAB
Входной язык MATLAB насчитывает всего 9 операторов, использующих
14 служебных слов. Соответствующие синтаксические конструкции
приведены в.табл. 4.1.
128
Глава 4
Таблица 4.1
№ Формат оператора
Пояснение
■\ var = expr
2 if условие_1
операторы_1
[elself условие__2
операторы_2
elself услозие_3
операторы_3
else
операторы ]
end
3 switch expr
case vail
олераторы_1
case val2
операторы_2
[ othervise
операторы]
end
4 for var=el:[e2:]eJ
операторы
end
5 while условие
операторы
end
6 try
олераторы_1
catch
операторы_2-
end
7 break
Оператор присваивания. Вычисляет значения
выражения expr и заносит результаты вычислений в
переменную var
Условный оператор. Если справедливо усло-
вие_1, то выполняется группа операторы__1, если
справедливо условие_2. то выполняется группа
операторы_2,... Если все указанные условия
оказываются ложными, то выполняются операторы,
расположенные между else и end
Переключатель по значению выражения ехрг.
Если оно совпадает с величиной vail, то
выполняется группа операторы_1, если оно совпадаете
величиной val2, то выполняется группа
операторы^, ... Если значение ехрг не совпадает ни с
одной из перечисленных величин, то выполняются
операторы, расположенные между othervise и
end
Цикл типа арифметической прогрессии, в котором
переменная var при каждом повторении тела
цикла изменяется от начального значения el с шагом
е2 до конечного значения еЗ
Цикл с предусловием, повторяющийся до тех пор,
пока истинно указанное условие
Попытка выполнить группу операторы_1. При
условии, что в результате их выполнения возникает
исключительная ситуация, управление передается
группе опера торы_2. (обработка сбойных
ситуаций). Если ошибка не возникла, то группа опера-
торы_2 не выполняется
Досрочный выход из управляющих конструкций
типа for, while, switch, try-catch
Программирование вычислительных процессов
129
Таблица 4.1 (окончание)
№ Формат оператора Пояснение
8 function f 1 Заголовок функции
function (*li *2,... — входные параметры; yl, у2, ... —
f2 {xl, х2,...) выходные параметры)
function
y=f3(xl,x2,...)
function
[yl,y2, . ..]=f<l(xl,x2,
9 return Досрочным выход из тела функции
Для ярых поклонников Дейкстры отметим, что язык MATLAB не содержит
оператора goto. В связи с этим в текстах m-файлов отсутствуют метки
операторов. Для идентификации строк, в которых возникают аварийные
ситуации, используются внутренние номера, присваиваемые системой
автоматически.
Комментарии в m-файлах начинаются с символа %. Они могут располагаться
с начала строки или находиться правее любого оператора. Однако при
оформлении m-файлов начальные комментарии выполняют особую роль.
Первая группа строк с подряд идущими комментариями до пустой строки
образует текст, выдаваемый в командном окне по команде help с именем
m-файла. Добавим, например, к приводившейся выше программе
вычисления 5! комментарий (пример 4.2) и сохраним файл fact5.m.
i Пример 4.2. Комментарий-подсказка
% Эта программа находит 5!
а=1;
for 1=1:5.
S=a*i;
end
.а.
Если в текущей строке командного окна обратиться за помощью к этой
явно несистемной функции, то MATLAB выдаст начальный комментарий:
» help fact5
Эта программа находит 5!
130
Глава 4
Обратите внимание, насколько тщательно оформляются системные т-
файлы. В качестве примера мы выбрали программу определения корней
полинома roois.m, расположенную в каталоге c:\MATLAB7\toolbox\MATLAB\
polyfun:
function г = roots(с)
%ROOTS Find polynomial roots.
% ROOTS(С) computes the roots of the polynomial vjhose coefficients
% are the elements of the vector C. If С has N+l components,
% the polynomial is С(1)*ХЛМ + ... + C(W)*X + C(N-H).
%
% Class support for input c:
% float: double, single
%
% See also POLY, RESIDUE, FZERO.
% J.N. Little 3-17-86
% Copyright 1984-2004 The MathWorks, Inc.
:¾ $Revision: 5.12.4.2 $ SDate: 2004/03/02 21:48:0b $
% ROOTS finds the eigenvalues of the associated companion matrix.
if size(c,l)>l S size(c,2)>l
error ('MATLAB:roots:NonVectorInput', 'Input must be a vector.')
end
с = с (:) . ■ ;
n = size(с,2);
r = zeros(0,1,class (c) ) ;
inz = find(c>;
if j sempty(inz),
% All elements are zero
return
end
%■ Strip leading zeros and throw away.
8 Scrip trailing zeros, but remember them as roots at zero.
nnz = length(inz);
с = с 1inz(]):inz(nnz));
r = zeros (n-inz (nnz) , 1};
Программирование вычислительных процессов 131
% Polynomial roots via a companion matrix
n = length(с);
if n > 1
a = diag (ones (l,n-2-) ,-1} ;
a(l,:) = -c(2:n) ./ c(l);
r = [r;eig(a)] ;
end
Справка, выдаваемая системой в командное окно, имеет вид:
» help roots-
ROOTS Find, polynomial roots.
ROOTS(C) computes the roots of the polynomial whose coefficients
are' the elements of the vector C. If С has N+l components,
the polynomial is С(1)*ХЛЫ +...+ C(N)*X + С(N+l).
Class support for input c:
float: double, single
See also POLY, RESIDUE, FZERO.
Как видите, в выдаваемом кадре помощи могут находиться пустые строки,
соответствующие пустым комментариям (т. е. строкам, содержащим
единственный символ %). Обратите внимание на то, что функция roots может
работать не только с обычными данными типа double, но и с
коэффициентами одинарной точности (типа single).
Комментарий в строке, начиная с символа %, является не единственной
возможностью для включения пояснений в текст программы. Мы уже
упоминали, что текст, расположенный в строке правее символов переноса (три
точки), тоже воспринимается как комментарий. Во входном языке MATLAB 7
появилась возможность включения многострочиого комментария. Ему
обязательно должна предшествовать строка, содержащая только два символа — % {.
Признаком конца многострочного комментария является строка,
содержащая также два символа — %};
%(
Первая строка комментария
Вторая строка комментария
%}
132
Глава 4
Многострочный комментарий может включать в себя вложенный много-
строчный комментарий. С помощью признаков начала и конца
многострочного комментария можно отключать фрагменты программы во время ее
отладки.
В арифметических выражениях помимо операндов-массивов допустимо
смешение типов данных. Например, к числовому значению можно
прибавить значение типа char. MATLAB заменит символьное значение его
числовым ASCII-кодом и выполнит предписанное действие, несмотря на
кажущуюся несуразность такой операции:
» х=5+'а'
х =
102
Множественное присваивание, допустимое во многих языках
программирования, в MATLAB запрещено:
» а=Ь=2;
??? Error: Assignment statements cannot produce a result.
» whos
»
Зато набрать в одной строке несколько операторов присваивания, разделяя
их запятыми или точками с запятыми, не возбраняется (пример 4.3).
! Пример 4.3. Оператор присваивания :■«&;:, ■*••-■-- «*-Ц ..-' ' \г ■-.. '"■ ^,,. ё
» х=2; у=3;
» х
X =
2
» У
У =
3
» х=2, у=3
х =
2
У =
3
В условных операторах некоторый протест со стороны пользователей может
вызвать возможность сравнения комплексных чисел. С точки зрения
математики комплексные данные можно сравнивать либо на равенство, либо на
Программирование вычислительных процессов
133
неравенство. Это соответствует и геометрическому представлению
комплексных чисел как точек на плоскости: координата х совпадает с вещественной
частью числа, а координата у — с мнимой. Но никому не приходит в голову
утверждать, что точка (10, 0) больше, чем точка (5, 4). Наиболее
естественные отношения двух точек — одна точка находится левее или правее другой,
расположена выше или ниже. A MATLAB при сравнении комплексных
чисел допускает использование операции отношения "больше", "меньше" и
сопоставляет при этом только вещественные части. '
Большинство операторов языка MATLAB напоминает аналогичные
конструкции языка C++. Одна из немногих особенностей — завершение
управляющих конструкций оператором end — вряд ли смутит программистов,
освоивших даже базовые операторы языка С. Наиболее существенные детали
связаны с программированием функций, допускающих переменное число
аргументов, среди которых могут встречаться массивы, и четкое разделение
параметров на входные и выходные. Этим особенностям и специфике
передачи параметров разного типа мы посвятим отдельный раздел.
4.4. Ввод числовых
и символьных данных
Простейший способ ввода числовой и символьной информации,
набираемой на клавиатуре, использует функцию input. Она допускает два формата
обращения, первый из которых:
х = input['приглашение')
В ответ на приглашение, выданное программой, пользователь может набрать
требуемое значение или ввести выражение, величина которого будет
подсчитана с учетом текущего состояния переменных рабочего пространства и
возвращена в качестве значения функции. Если пользователь в ответ на
приглашение нажимает только клавишу <Enter>, то функция возвращает
пустой массив типа double размером 0x0. Обратите внимание на то, что
текст приглашения выдается в начале следующей строки. Если вы не хотите
набирать вводимую информацию вплотную к подсказке, то можно
предварительно нажать клавишу <Пробел> или переместить курсор
соответствующей клавишей-стрелкой. А можно предусмотреть дополнительный пробел в
тексте приглашения.
Второй формат обращения к функции input: имеет вид:
х = input('приглашение','s')
В этом случае текст, набираемый пользователем, рассматривается как строка
символов, которая и возвращается в качестве значения функции. В обоих
случаях текст приглашения может содержать символы \п, управляющие пе-
134
Глава 4
реводом курсора в начало следующей строки. Это обеспечивает, в случае
необходимости, вывод приглашений, состоящих из нескольких строк.
4.5. Вывод результатов вычислений
Для вывода значения выражения, в частном случае которого может быть
имя любой переменной, достаточно не набрать после него символ "точка с
запятой", подавляющий выдачу результата. В других случаях можно
прибегнуть к функции disp (от англ. display — отобразить), которая отличается от
автоматического вывода только тем, что не выводит имя отображаемого
значения — имя переменной, которой присваивается результат вычислений,
или имя системной переменной ans:
disp(выражение)
В частном случае аргументом функции disp может быть строка,
заключенная в одинарные кавычки.
Функциями error или warning можно воспользоваться дли выдачи
сообщения об ошибке или предупреждения. Их основным аргументом является
текст сообщения, после вывода которого работа программы будет либо
завершена (использована функция error), либо продолжена (использована
ФУНКЦИЯ warning) — Пример 4.4.
I Пример 4.4. Предупреждение и сообщение об ошибке
» wa г ning (' Предупреждение ! ')
Warning: Предупреждение !
>> error('Ошибка'j
??? Ошибка
Вообще говоря, функция warning обладает гораздо более широкими
возможностями и напоминает функцию cprirmf в языке C++. Ее общий
формат таков:
warning('name_w■,■format', список}
Строка name_w используется в качестве идентификатора группы сообщений.
При необходимости вывод всех сообщений одной группы можно
заблокировать, обратившись к процедуре warning следующим образом:
warning('off,'name_w')
При этом не понадобится удалять все строки, содержащие сообщения
данной группы.
Программирование вычислительных процессов
135
Если снова понадобится включить эти сообщения, то вызывается процедура
warning с параметром on:
warning ('on','name_w')
Строка format используется для форматных преобразований элементов
выводного списка, и ее запись в точности повторяет форматные спецификации
языка C++:
warning Сqq:','x=%d y=%8.4f' ,к,у)
Более подробно все форматные преобразования описаны в функции sprintf.
4.6. Типы функций
Существует несколько разновидностей m-функций. В разд. 4.1 мы
познакомились с головными функциями, имена которых совпадают с именами т-
файлов. В фирменной документации они фигурируют под названием
"первичные М-файлы" (Primary M-File Functions). К ним можно обращаться
из других функций или из строк Command Window (Окно команд),
передавать им параметры. Характерной особенностью m-функций является
наличие индивидуального рабочего пространства — механизма локальных
переменных. Наряду с последними, пг-фуикции могут использовать переменные
из других рабочих пространств, где эти общие переменные объявлены как
глобальные.
Вторую разновидность m-функций составляют подфункции (subfunctions),
описания которых расположены в m-файле вслед за головной функцией.
Подфункции т-файла не могут быть вызваны извне. Это своего рода
функции внутреннего пользования. Они могут общаться между собой в пределах
т-файла и обращаться к другим головным функциям, расположенным в
других т-файлах. Цепочку вызовов подфункций инициирует головная
функция т-файла.
В предыдущих версиях MATLAB преобладала идеология, близкая к языку С,
в результате которой каждая функция выступала в роли отдельного
кирпичика — вложения функций друг в друга не допускались. Седьмая версия
сделала шаг навстречу языку Pascal и разрешила использование вложенных
функций:
function yl=fl(pl,p2)
function y2=f2(xrz) S вложена в функцию fl
function y3=f3.(a,b) % вложена в функцию £2
136
Глава 4
end S конец функции f3
end t- конец функции f 2
end % конец функции f1
При вызове вложенных функций соблюдается общепринятое правило: к
вложенной функции может обращаться только непосредственно
окаймляющая ее функция. В приведенном выше примере функция fi может вызвать
функцию f 2-, но не может напрямую обратиться к функции f з.
Вообще говоря, внятного объяснения по поводу преимуществ вложенных
функций авторы MATLAB 7 не дали. До сих пор идеи, заложенные в
Fortran, не признававшем вложенных функций, и в Algol, разрешавшем
вложения, сосуществовали параллельно. В MATLAB 7 было решено их
объединить, но пока не ясно, зачем.
Кроме вложенных (nested functions) в 7-й версии появились анонимные
(anonymous functions) функции. По сути дела, у этих функций нет
собственного имени, вместо которого используется указатель функции. Формат их
объявления таков:
h_F=@(список_параметров) формула
Очевидно, что описания функций такого типа имеют смысл при работе с
достаточно простыми формулами. Например, анонимная функция
возведения в квадрат с указателем sqr может быть описана и использована
следующим образом:
» sqr = @(х) х.Л2;
» sqr([l 2 3])
ans =
14 9
С точки зрения пользователя эта анонимная функция ничем не отличается
от обычной функции с именем sqr. Однако мы допускаем, что реализация
анонимной функции более эффективна.
Указатель на анонимную функцию может быть передан другим функциям в
качестве параметра. Например, мы можем обратиться к функции
вычисления определенного интеграла от х2 на интервале от о до 1 следующим
образом:
» quad(sqr, 0, 1)
ans =
0.3333
Часть m-функций может быть помешена в каталог со специальным именем
private. Эти функции будут доступны только из родительского каталога, со-
Программирование вычислительных процессов 137
держащего каталог private. Функции, хранящиеся в этом каталоге, считаются
частными (private functions). Основное их назначение — заменить некоторые
системные функции одноименными пользовательскими. MATLAB начинает
поиск вызываемых функций с каталога private, поэтому они вызываются в
первую очередь.
Наконец, следует упомянуть еще об одной группе функций, для которых в
литературе используется не очень удачный термин — перегружаемые
функции (overloaded functions). В объектно-ориентированном программировании
широко используется возможность определять несколько функций с
одинаковыми именами, которые отличаются друг от друга либо количеством
параметров, либо их типами, либо типом возвращаемого значения.
Компилятор анализирует очередное обращение к функции и вызывает ту из них,
которая соответствует шаблону вызова.
4.7. Параметры функций
Почти все универсальные алгоритмические языки объединяют входные и
выходные аргументы функций в общие скобки и возвращают в качестве
своего значения единственный результат, обычно присваиваемый имени
функции. Большинство алгоритмических языков использует позиционный
принцип задания аргументов — каждый аргумент расположен на
фиксированном месте в списке параметров. Только некоторые системы (в частности,
ассемблер) наряду с позиционными аргументами позволяют использовать
ключевой способ задания параметров в форме имя=значение. Ключевые
параметры всегда располагаются вслед за списком позиционных аргументов и
могут следовать в любом порядке. Вызывающая функция обычно передает
свои параметры через стек, помещая туда значения или адреса
соответствующих аргументов. Существуют два принципиально разных способа записи
параметров в стек — один из них в стиле С (модификатор edeel) первым
заносит в стек последний аргумент списка, а второй в стиле языка Pascal
(модификатор pascal) первым заносит в стек первый аргумент списка.
Обычно с этим приходится считаться в тех случаях, когда фрагменты
программы реализованы в разных системах программирования. Для функций,
допускающих переменное число параметров, программист или система
программирования наряду с фактическими аргументами функций должны
помещать в стек либо количество передаваемых параметров, либо завершать
их список обусловленным признаком конца.
В языке MATLAB входные и выходные аргументы функций четко
разделены. Все входные параметры используют только позиционный принцип и
задаются в круглых скобках после имени функций. Все выходные параметры
объявляются как массив результатов и в операторах присваивания обычно
записываются в квадратных скобках. Программистам, работающим на языке
138
Глава 4
C++, известно, что иногда функции могут иметь переменное число
параметров (список формальных аргументов в заголовке функции завершается
многоточием), и для создания такого рода программ используются
специальные средства — функции (точнее, макроопределения) vastart, vaend,
V3_arg, va_iist. Нечто похожее имеется и в языке MATLAB. Хотя
переменное число параметров, как входных, так и выходных для m-файлов,
скорее, является правилом, нежели исключением.
MATLAB упаковывает все входные параметры в массив ячеек с именем
varargin и запоминает количество передаваемых функции аргументов в
глобальной переменной nargin. Функция, возвращающая переменное число
значений, обычно начинается с заголовка:
function [varargout] = имя__функции (аргументы)
Это означает, что результаты работы функции должны присваиваться
компонентам массива ячеек varargout. К. таким образом определенной
функции можно обращаться с разным количеством выходных параметров:
Iyl,у2,уЗ1 = имя_функции(аргументы)
[zl,z2] = имя_функции(аргументы)
wl = &1мн_фу'1кций (аргументы)
В первом случае переменной yl будет присвоено значение ячейки
varargoutп}, переменной у2 — значение ячейки varargout{2},
переменной уз — значение ячейки varargout{3}. Во втором случае будут
использованы значения первых двух ячеек, в третьем случае — единственное
значение первой ячейки массива varargout. Чтобы функция вычисляла только
требуемое количество результатов, ей сообщают в глобальной переменной
nargout фактическое число запрашиваемых данных.
Для контроля за допустимым количеством входных и выходных аргументов
m-функции могут использовать функции nargchk И nargoutchk:
msg = nargchk(min, max, nargin);
msg = nargoutchk(min, max, nargout);
Обе функции формируют сообщение msg о недопустимом числе входных
или выходных параметров, которое можно вывести с помощью функции
error (msg). Если количество параметров принадлежит диапазону |min, max],
то сообщение msg представлено пустой строкой и сообщения об ошибке не
последует.
Продемонстрируем использование описанных глобальных переменных на
примерах, которые мы заимствовали из файлов помощи, но слегка
модифицировали в сторону упрощения.
•f
Программирование вычислительных процессов
139
Функция polyline.m получает массив переменной длины с координатами
точек (xi,yi), (х2,у2) и т.д. и строит ломаную линию, соединяющую эти
точки (пример 4.5).
! '■ '" '"""" 1F'";""" :"~ """v' "■•■■••' :
; Пример 4.5. Построение ломаной линии -.?■ ■ ■-;. . л ^. „. *■■>-. ^ -.;
; : '. :^:::..;...;;л: :.:..:;;л..Л д= .?..:&£ .■:; ,^шж&з.л:::гк1&:.:я:^..к;
function polyline(varargin)
for k=l:length(varargin)
x(k)=varargin{k)(1) ;
y(k)=varargin{k)(2) ;
end
axis ([nun (x) raax(x) min(y) max(y]])
plot (x, y)
Результат обращения к этой функции с шестью следующими точками:
» polyline ([2 3], [1 5], [4 8], [6 5], [4 2], [2 3])
приведен на рис. 4.2.
Рис. 4.2. Полигон из 6 точек
Результат обращения к этой же функции с другим количеством точек:
polyline([-1 0],[3 -5], [4 2],[1 1])
приведен на рис. 4.3.
Функция array2vec получает массив размерности лх2, первый столбец
которого содержит координаты xi, х2, ..., а второй — координаты yi, у2, ...
Задача функции разнести строки матрицы по выходным векторам, содер-
140
Глава 4
жатим координаты соответствующих точек— (xi,yi), (х2,у2),...
(пример 4.6).
Рис. 4.3. Ломаная линия из 4 точек
[Пример, 4.6. Передача.аргументов функции . ; ;. - |
function [varargout] = array2vec(a)
for k=l:nargout
varargout{k}=a(k,:);
end
Результат двух последовательных обращений с разным количеством
выходных параметров приведен ниже:
» а1={1 2; 3 4; 5 б; 7 8; 9 1С; 11 12);
» [pi p2]=array2vec(al)
pi =
[1] [2]
р2 =
[3] £4]
» [ql q2 q3 q4 q5]=array2vec(al)
ql =
[1] [2]
q2 =
[3] [4]
q3 =
[S] [61
Программирование вычислительных процессов
141
q4 =
[7]
Ф -
[9]
» whos
Name
al
pi
p2
ql
q2
q3
q4
q5
[8]
[10]
Sizi
6x2
1x2
1x2
1x2
1x2
1x2
1x2
1x2
Bytes
816
136
136
136
136
136
136
136
Class
cell
cell
cell
cell
cell
cell
cell
cell
array
array
array
array
array
array
array
array
Если в качестве входного параметра передать обычный числовой массив, то
результатом работы той же функции будут обычные числовые векторы:
» al=[l 2; 3 4; 5 6; 7 8} 9 10; 11 12];
» [pi p2]=array2vec(al)
р] =
1 2
р2 =
3 4
» [ql qZ q3 q4 q5]=array2vec(al)
ql =
1 2
q2 =
q3
q4 =
q5 =
10
>> whos
Name
al
pl
Size
6x2
1x2
Bytes Class
96 double array
16 double array
142
Глава 4
Р2
qi
q2
q3
q4
q5
1x2
1x2
1x2
1x2
1x2
1x2
16 double array
16 double array
16 double array
16 double array
16 double array
16 double array
Библиотека раздела string.h в системе программирования Borland C++
включает функцию strtok(str, del), с помощью которой осуществляется
выделение лексем в строке str. Второй аргумент этой функции содержит
набор символов, отделяющих одну лексему от другой. Например, при
записи дат могут использоваться такие разделители, как пробелы ('Март 14
1972'), Дефисы ('Март-14-1972'), ПрЯМЫе СЛЭШИ ('Март/14/1972'). ФуНК-
ция strtokfdate," -/") возвращает указатель на первую обнаруженную
лексему и заносит пулевой код на место символа-разделителя. Это
позволяет обработать найденную лексему как строку. Вторая и следующие лексемы
выделяются этой же функцией, если в качестве ее первого аргумента
задается указатель hull. Аналогичная функция с таким же названием содержится
в каталоге MATLAB7\toolbox\MATLAB\strfun. В отличие от своего аналога,
функция strtok.m умеет работать с одним или двумя аргументами, а в
качестве результата возвращать (если попросят) две строки — найденную
лексему и оставшуюся часть строки. Она активно использует глобальные
переменные nargin, nargout, и когда к ней обращаются с единственным
аргументом string, то в качестве разделителей использует так называемые
белые пробелы— символы ASCII с кодами 9, 10, И, 12, 13 и 32. В
примере 4.7 приводится текст этой функции, в котором комментарии переведены
на русский язык и добавлены некоторые пояснения.
I Пример 4.7. Функция strtok
function [token, remainder] = strtok(string, delimiters)
% STRTOK находит лексемы (token) в строке string.
% STRTOK(S) возвращает первую лексему в строке S, завершающуюся
% "бельм пробелом". Лидирующие пробелы игнорируются
«■
%■ STRTOK(S,D) возвращает первую лексему, завершающуюся одним
%- яз. симеолов, заданных в D. Лидирующие разделители игнорируются
%
% [T,R] = STRTOK(...) возвращает остаток исходной строки
% Если лексема в 8 не найдена, то R равно пустой строке, a T=S
%.
if nargirKl, error('Не хватает входных параметров'); end
Программирование вычислительных процессов
143
token = []; remainder = [];
len = length(string);
if len = б
return
end
if (nargin == 1) % Если входной аргумент один
delimiters = [9:13 32]; £■ Коды "белых пробелов"
end
i = 1;
% Пропуск лидирующих разделителей
while (any(string(i) == delimiters))
i = i + 1;
if (i > len), return, end
end
start = i;
% Цикл до появления первого разделителя
while (-any(string(i) =-delimiters))
i = i + 1;
if (i > len), break, end
end
finish = i - l;
token = string{start:finish);
if (nargout =- 2) % Если задам второй выходной аргумент
remainder = string (finish + 1: length (string) ) ,-
end
Вообще говоря, nargin и nargout являются не глобальными переменными,
а функциями. К ним можно обратиться, задав в качестве аргумента имя т-
функции. И тогда они возвращают количество входных и выходных
параметров, указанных в заголовке функции:
» nargin{'strtok')
ans =
■2
» -nargout (' strtok')
ans =
2
Вы уже обратили внимание на то, что функции с фиксированным числом
входных или выходных параметров вовсе не обязаны прибегать к услугам
массивов varargin и varargout. Однако когда число параметров может быть
144
Глава 4
переменным, то их использование способно существенно упростить процесс
программирования. Очень изящно смотрится пример функции построения
графиков, которой можно передать любой набор свойств и значений
объекта типа Line:
function myplot(х,varargin)
plot{x,varargin{:})
К ней, например, можно обратиться с набором следующих аргументов:
myplot(sin(0:.1:1),'color',[.5 .7 .3],'linestyle',':')
И тогда в массиве varargin система сформирует четыре ячейки, элементами
которых будут строка с именем свойства color, массив RGB-составляющих
.[.5 .1 .3], строка с именем свойства linestyle и символ :, управляющий
стилем линии. А в самой функции myplot не нужно прилагать никаких
усилий по распаковке массива varargin и анализу его элементов.
Массивы varargin и varargout могут появляться в заголовках функций в
комбинации с обычными формальными параметрами, однако подобно
ключевым параметрам их следует располагать в конце списка:
function [yl,y2] = funl(xl,x2,varargin)
function [yl, у2, varargout] = fun2{xl,х2,хЗ,х4)
4.8. Функции evalw feval
MATLAB предлагает пользователю две системные функции eval и feval,
прямых аналогов которым нет ни в одной системе программирования
компилирующего типа.
Главным аргументом функции eval (от англ. evaluation — вычисление)
является строка, представленная любым допустимым выражением MATLAB или
командой вызова известного системе m-файла. Функция eval исполняет
(интерпретирует) эту строку, как если бы она была набрана в командном
окне. Так можно вычислить формируемое во время работы программы
выражение, исполнить функцию, введенную пользователем по запросу
приложения. Наиболее распространенными форматами вызова функции eval
являются:
eval (stri)
evai(st.rl,str2)
[yl,y2,...] = eval('fun(xl,x2,...)')
Для формирования выполняемой строки можно использовать операцию
конкатенации строк, преобразования числовых параметров в символьный
формат (int2str) и многое другое.
Программирование вычислительных процессов
145
В справочной документации приводится редкий по изяществу фрагмент,
формирующий в цикле 12 магических квадратов с именами mi, М2, ..., М12
(пример 4.8).
I Пример 4,8. Формирование 12:мат.чфских;кв'адр]^гоВ'^^ » --^У4 ^¾¾^¾
for n = 1:12
magic_str = ['М', int2str(n),' = magic(п)'];
eval(magic_str)
end
Вторая необязательная строка str2 в списке параметров функции eval
задает действия, которые нужно выполнить, если во время исполнения stri
возникла ошибочная ситуация.
В тестовом примере showdemo.m, содержащем всего пять строк,
выполняется одна из демонстрационных программ, хранящихся в каталоге MATLAB7\
toolbox\matlab\demos (пример 4.9).
Г Примерi 4.9. Запуск демонстрационной программы а ;г^'' ^---/^^¾¾½¾¾
function showdemo(demos)
errstring = 'Файла с таким именем в каталоге нет";
п = input['Выберите номер демонстрационного файла: ')
demos(n,:)
eval(demos(n,:),'[errstring demos(n,:)]')
Для запуска этой программы наберите в командном окне две следующие
строки:
>> D = [.'o'dedemo'; 'quademo'; ' fTitdeirio' J ;
»■ showdemo(D)
Первая из них содержит список имен m-файлов, два из которых
действительно находятся в указанном каталоге (odedemo.m — демонстрация методов
решения обыкновенных дифференциальных уравнений и fitdemo.m —
приближение нелинейной функцией экспериментальных данных). После старта
приложения вам предложат ввести одно из чисел I, 2 или 3 для выбора
имени демонстрационного примера. На выбор п=2 последует сообщение о
том, что файл с таким именем в каталоге не представлен.
Функция f eval по логике своей работы отчасти напоминает функцию eval
146
Глава 4
Обычно ей передают указатель hFun на функцию, подлежащую
выполнению, и список параметров, передаваемых косвенно вызываемой функции:
[yl,y2,...] = feval(hFun,xl,х2,...);
Второй формат вызова функции feval предполагает, что ее первым
аргументом является строка с именем функции:
[yl,y2,... . feval{'Name_fun'fxl,x2,...);
Этот вариант считается устаревшим, но его сохранили для преемственности
с ранее разработанными приложениями MATLAB. Следует заметить, что
точными эквивалентами второго формата вызова являются и следующие
обращения:
[yl,у2,..Л = feval(@Name_fun,xl,х2,...};
fy'l, y2, . . . ] = Name_fun(xl, x2, . . .) ;
Основное назначение функции feval — вычисление значения функции в
теле процедуры, которой среди входных параметров передали указатель на
функцию.
4.9. Специфика работы
в редакторе m-файлов
Редактор m-файлов вызывается по команде File | New | M-File (Файл |
Создать | М-файл) или при одинарном щелчке на имени m-файла. Главное
меню редактора несколько отличается от глапного меню MATLAB, да и панель
инструментов здесь гораздо богаче (рис. 4.4).
Cut
Г Сору
Paste
Я Editor - Untitled
Find text Top/Bottom Split
г Show functions Left/Right Split
Step In -i rStepOut Tile
Hie Edit Jfait p! Tods Debud Ctsktop Window 4;lp
Ые?|и I .», 4» №, '■ '■ ■"" #| «j fj К. jpj. -I? Ъ№ Р)вГ |a«t| ~Б gjJBljk?-JD
TnR
Save
Open
file
New M-File
L Print
L- Redo
Undo
Run J L Exit Debug Mode
L Step Float
L Clear Breakpoints in All Files
Set/clear breakpoint Maximize
Рис. 4.4. Панель инструментов редактора m-файлов
Программирование вычислительных процессов
147
Большинство разделов главного меню в редакторе кода совпадает с
аналогичными разделами главного меню среды MATLAB. Однако состав команд в
соответствующих разделах поменялся, в основном в сторону увеличения
количества команд.
Так, например, в меню File (Файл) появились команды Publish То HTML
(Экспортировать в HTML) и Publish То (Экспортировать). С их помощью
программа, набранная в поле редактора, может быть экспортирована в
документ, создаваемый в одном из форматов — HTML, XML, LaTeX, MS Word,
MS PowerPoinl. Документ, экспортированный в формате HTML, сохраняет
раскраску синтаксических единиц, действующую в редакторе кода.
В окне редактора можно открыть несколько m-файлов и одновременно
наблюдать тексты нескольких программ, разделив поле редактора на части
(Tile), горизонтальные (Top/Bottom Split) или вертикальные (Left/Right Split)
полоски, расположив панели с программами друг за другом (Float) или
развернув одну из программ на все окно (Maximize). На рис. 4.5 приведен
вариант горизонтального расслоения поля редактора после вызова программ
array2vec.m и fcrn.m. Имена вызванных программ отображаются в строке
Document Bar (Строка документа).
Q) Editor
File Edit Text Cell Tools Debug Desktop Window Help
^'^sPfS'^T^. .sax \-. ■ т-гг t -
1 function [varargout] = array2vec (a)
2 - foe k=l:narcfout
3- varargout[kl=a(k,:);
4 - end
H:\MATLAB7 work\fern.m
1 , function fern
1 ■■ИГЕТ'.Ы M?.T!A& i^-Lou'.-n-ftliin of г",.;, fractal f-ssn
3 4 MichacL' P:ii n-r'lcy, Frartnlf Kvc:.ywl!'--£.-. Лта^сгс!'-- I't-i-:
4 5 Tils vtrir-iori L-j-JiH f nciv-.i, 01 Jl.NJl :---trT- 1« 1-X)t|lel
5 ? a-_« -jlsc-.: i'lfeii'ISh-t.Ki.
6 - shg
7 - elf reset
8 - set (act, 'coioi:', 'white-', 'iuoi-iub-ai:', 'вопс-', ...
I array2vec in * .[ (em m * "
|fem Kn 1"
ЯПВ
"x i
▲
zl
* X
▲
■=2 '• '1Ч'\
zl
Col 1 \-tif v
Рис. 4.5. Две m-программы в поле редактора кода
Среди разделов главного меню появились новые разделы — Text (Текст),
Cell (Ячейка) и Tools (Сервис).
148
Глава 4
4.9.1. Меню Text
Меню Text (Текст) главным образом ориентировано на управление текстом
программы иа поле редактора (рис. 4.6).
Text
Evaluate Selection
Wrap Selected Comments
Comment
Uncomment
Decrease Indent
Increase Indent
Smart Indent
F9
Ctrl+R
Ctrl+T
Ctrl+t
Ctrl+]
Ctrl+I
Рис. 4.6. Команды меню Text
Команда Evaluate Selection (Вычисление выбранного) обеспечивает
вычисление выделенного выражения, если в этот момент известны значения всех
переменных, входящих в формулу. Результат вычислений отображается в
Command Window (Окно команд).
Команда Wrap Selected Comments (Переносить выбранные комментарии)
имеет смысл только в том случае, когда отключен режим автоматического
перехода на следующую строку при наборе длинных комментариев. В
настройках Preferences | Editor/Debugger | Language (Предпочтения |
Редактор/Отладчик | Язык) имеется возможность управлять форматом
набираемой программы. Во-первых, это список языков программирования —
М (MATLAB), C/C++, Java или HTML. Во-вторых, это подключение или
отключение режима подсветки синтаксических конструкций (Enable syntax
highlighting). В-третьих, это выбор режима отступа (Indenting for Enter key)
для выделения вложенных конструкций. Наконец, это управление длиной
строки комментария (Comment formatting) и его автоматическим
продолжением со следующей строки при превышении установленной границы
(Autowrap comments). Если режим автоматического переноса отключен, а
комментарий набран без соблюдения установленного предела, то любой его
фрагмент (хотя бы один символ) надо выделить. После выполнения
команды Wrap Selected Comments (Переносить выбранные комментарии) длинные
комментарии будут автоматически укорочены за счет переноса избыточных
хвостов в начало следующих строк.
Команда Comment (Комментировать) позволяет закомментировать текущую
строку. Конечно, это можно сделать и вручную, установив символ % в
первой позиции текущей строки. Превращение текущей строки в комментарий
позволяет временно отключить некоторые операторы па время отладки оп-
Программирование вычислительных процессов
149
ределенных фрагментов программы. Команда Uncomment
(Раскомментировать) возвращает закомментированный в текущей строке оператор в
первоначальное состояние.
Термин indent (отступ) означает автоматический отступ текущей строки по
отношению к предыдущей строке. Вы, наверное, наблюдали, как после
оператора for следующая строка автоматически сдвинулась вправо, наглядно
представляя вложенность тела цикла. И все последующие строки тела цикла
начинаются с этой же границы. Иногда полезно вмешаться в этот режим,
например, чтобы очередной оператор end, завершающий тот или иной
программный блок, оказался на уровне заголовка блока. И тут на помощь
приходят команды Decrease Indent (Уменьшить отступ), Increase Indent
(Увеличить отступ) и Smart Indent (Интеллектуальный отступ). Первая из
них смещает текущую строку или выделенный блок строк влево на
установленное число позиций (величина этого смещения регулируется в окне
Preferences (Предпочтения)). Вторая команда осуществляет аналогичный сдвиг
текущей строки или выделенного блока строк вправо. Команда Smart Indent
(Интеллектуальный отступ) реализует интеллектуальный отступ —
например, выравнивает на общую границу пару for.. .end или подравнивает все
внутренние команды блока, если они по какой-то причине начинаются с
разных позиций.
4.9.2. Меню Debug
Меню Debug (Отладка) включает команды, управляющие режимами отладки
(рис. 4.7).
Debug |
* Open M-Flles when Drugging
Step ' ■ F10
Step In Fli
Step Out Shlft+Fll
Ru-i F5
Go Lhtil Cursor _____ __ .
Set/Clear Breakpoint F12
Set/Modify Conditional Breakpoint...
EnableyDlsable Breakpoint _ ■■
Clear Breakpoints in All Files .■ "'*" "
Stop If Errors/Warnings,,. .'■
Exit Debug Mode
Рис. 4.7. Команды меню Debug
150
Глава 4
Команда Run (Запуск) или нажатие клавиши <F5> инициируют
автоматическое исполнение программы.
Команда Step (Шаг) включает режим пошагового выполнения m-файла —
при каждом нажатии клавиши <F10> система интерпретирует очередную
исполняемую строку программы. Режим Step In (Шаг внутрь) устанавливает
точки останова на первых исполняемых строках каждой подфункции. Это
позволяет проконтролировать в отладочном режиме выполнение тех или
иных операторов внутри подфункций. Режим Step Out (Шаг наружу)
исключает подфункции из отладочного режима, предоставляя им возможность
выполняться автоматически.
Во время выполнения программы команда Run (Запуск) подменяется
командой Continue (Продолжить), которая после останова программы вновь
переводит ее в режим автоматического исполнения.
Термин breakpoint (точка прерывания) обозначает строку программы, на
которой компьютер должен приостановить режим автоматического
выполнения, предоставив пользователю возможность произвести некоторые
отладочные действия. Самый простой способ выделения строки в качестве точки
останова — щелчок по знаку "минус", расположенному справа от номера
строки.
Строки, отмеченные как точки прерывания, выделяются красными
маркерами между колонкой номеров строк и первой позиции. Если вы пытаетесь
объявить какую-либо исполняемую строку точкой останова, и вместо крас-
"ного маркера появляется серый, то это означает, что программа в поле
редактора подверглась модификации и еще не была сохранена. После
запоминания ее текста в дисковом файле серые точки останова становятся
красными.
Команда Set/Clear Breakpoint (Установить/Убрать точки прерывания)
выделяет текущую строку как точку останова или отменяет ранее сделанное
выделение. Команда Set/Modify Conditional Breakpoint (Установить/Изменить
условие точки прерывания) открывает диалоговое окно (рис. 4.8), в котором
можно задать дополнительное условие. Если оно будет выполнено, то
произойдет останов на заданной строке программы (точки условного останова
появились только в MATLAB 7). В противном случае точка останова будет
проигнорирована.
Команда Enable/Disable Breakpoint (Восстановить/Отключигь гочку
прерывания) позволяет восстановить или временно отключить точку останова.
В последнем случае красный маркер перечеркивается крестиком, но не
удаляется из программы. Повторное выполнение команды отменяет
предыдущее действие.
Команда Clear Breakpoints in All Files (Удалить точки прерывания из всех
файлов) отменяет все выделения во всех одновременно открытых файлах.
Программирование вычислительных процессов
151
Q
MATLAB Editor
File H-VilATLAB7VworkAarray2vec.m
Cortcftion for lire 4 (for example,x = ЛУ.
□
Note: Itie condition win be checked before tne line is executed.
OK Cancel Help
Рис. 4.8. Окно для набора условия в точке останова
Команда Stop if Error/Warnings (Остановить при ошибке/сообщении)
открывает диалоговое окно (рис. 4.9), в котором имеется 4 вкладки — Errors
(Ошибки), Try/Catch Errors (Ошибки iry/catch), Warnings (Сообщения), Nan
or Inf (Nan или In!7). На каждой из них можно установить один из режимов:
□ Always stop if warning (dbstop if warning) — всегда останавливаться
в соответствующей ситуации;
П Never stop if warning (dbstop if warning) — никогда не останавливаться
в соответствующей ситуации.
Кроме того, системное сообщение о произошедшем событии можно
заменить пользовательским сообщением.
f| Stop if Errors/Warnin...
Errors | Tiy/caich Errors Warnings | f)an oc inf |
f Never stop H warning CdbckKir if warning)
f* Always etop tf warring (dbstop H warning)
F* use itttssage Identifiers (dbstop IT wamirc messaged)
МуТогЛах FlleNotFouldError
|L .Adj..
OK Cancel
Help
Add Message Identifier П
Identifier:
Myl oolbov: FteHotFcunciEricir
Example: MyToolbOJcFfleNotFtwritfci-rar
OK
Cancel J l-lelp |
Рис
4.9. Изменение условий останова при ошибках или предупреждениях
Команда Go Until Cursor (Продолжать ло текущей строки) добавляет к
точкам останова текущую строку.
Прерывание программы в случае выхода на точку останова или в результате
возникновения запланированного события переводит MATLAB в режим
отладки. Отличительным признаком этого режима является изменение под-
6 Зак. SW
152
Глава 4
сказки в командной строке — вместо символов » появляется тройка к».
В качестве рабочего пространства теперь выступает локальное рабочее
пространство отлаживаемой функции, и пользователю доступны все команды
MATLAB. С их помощью он может проанализировать значения тех или
иных переменных, вычислить нужные выражения, предпринять другие
отладочные действия.
Команда Continue (Продолжить) продолжает работу приостановленной
программы. Выход из режима отладки обеспечивает команда Exit Debug
Mode (Выйти из режима отладки).
Первые 10 кнопок на панели инструментов редактора дублируют наиболее
часто используемые команды меню File (Файл) и Edit (Правка). Смысл
большинства кнопок в правой части панели инструментов становится ясным
после знакомства с командами назначения точек останова и управления
режимами отладки.
Кнопка Show function (Показать функцию) позволяет быстро перейти к
тексту нужной подфункции. Щелчок по этой кнопке выдает окно со списком
всех подфункций данного m-файла (рис. 4.10). Последующий щелчок по
имени нужной подфункции переводит курсор в начало выбранной функции.
31 Editor - C:\MATLAB6p5\work.l\calll.ni
File Edit Text Cell Tools Debug Desktep Window Help _
D c£ Й ! ,*■ "fa &, " " | "<S ' "** jJ~Q & i ^ '^ ^т >Ш Ш i.a«dr|iw~l|
1
z
3
4
5
6
7
function varacgout = <
■\ CALLl И-fil-a fi-.i ceJ
Г£]".:.^, by ::?.eJ
U = .-.i'.L.i :.-:;!:h:
2 the -"tiir 1 r.-J '-■
calll
calllJDpeningFcn
call iJXitputftn
f'igurel_ButtonDownFcn
pushbutton2_Callback
r-tii---,-n'-. .
,_L ОГ raiSia:?
■■•■• CST.L1 c-r
"h^ -rXiStili'J
th( lia.ndJe '-.w
Рис. 4.10. Список подфункций файла calH.m
4.9.3. Меню Edit
Быстрые перемещения по программе в поле редактора дополнительно
обеспечиваются командой перехода на строку с заданным номером и
использованием закладок (bookmarks). Эти средства сосредоточены в разделе Edit
(Правка) главного меню редактора (рис. 4.И).
Выполнение команды Go То Line (Перейти к строке) приводит к появлению
диалогового окна (рис. 4.1.2), в котором следует набрать номер искомой
строки.
Программирование вычислительных процессов
153
Edit
. Undo
Redo
Cut
Copy
Paste'
Paste. Special,-..,
■Select All
Delete
Find end Replace...
Find Next
Find Previous
Find Selection
Find Files...
Go To Line
.Set/Clear Bookmark
Next Bookmark-
Prev Bookmark
■ Clear Command Window
Clear Command History
Clear Workspace
Cfrl+Z
Ctrl+Y
Cirl+X ""
Ctrl+C
Ctrl+V
Ctrl+A
Delete
Ctrl+F
F3
Shlft+F3
CM+F3
Ctrl+G
Ctrl+F2
F2
=SJ1ft+F2
Рис. 4.11. Меню Edit
Go To Line
Line number: Щ
П
OK
Cancel
Рис. 4.12. Диалоговое окно перехода
на строку с указанным номером
Bookmarks (закладки) могут быть присвоены наиболее посещаемым строкам
профаммы с помощью команды Set/Clear Bookmark (Установить/Удалить
закладку). Слева от такой строки появляется голубенький прямоугольник
(рис. 4.13). Повторное выполнение, этой же команды, когда курсор
находится в помеченной строке, удаляет закладку. Естественно, что применение
закладок имеет смысл только в длинных программах, текст которых
полностью не отображается на экране.
Переход к ближайшей закладке, расположенной ниже текущей строки,
выполняется с помощью команды Next Bookmark (Следующая закладка). Воз-
154
Глава 4
врат на ближайшую закладку, расположенную выше текущей строки,
осуществляет команда Prcv Bookmark (Предыдущая закладка).
'ДEditor - H:\MATLAB7\work\array2vec.m
File Edit Text Cell Tools Debug Desktop Window Help
D-eg а]'Ль as,~-■'^ \'m\h /.Га~ ё зйш 1вЖ|^[^1Г
1 function [vacargoutl =* acray2vec (a)
2- for: k»l:nargout
3-D vacargoutl k|=a (k, :) ;
4 - end
Рис. 4.13. Закладка возле третьей строки
Работа в любом текстовом редакторе, как правило, предполагает активное
использование так называемых горячих клавиш. Редактор m-файлов
располагает довольно скромным набором таких операций, их перечень приведен в
табл. 4.2.
Таблица 4.2
Клавиша/комбинация Операция
клавиш
<Т> Переход на предыдущую строку
<1> Переход на следующую строку
«—> Возврат на один символ
<—» Переход на один символ вправо
<Ctrl>+<—»> Переход на одно слово вправо
<Ctrl;>+«— > Возврат на одно слово влево
<Ноте> Возврат в начало строки
<End> Переход в конец строки
<Delete> Удаление символа над курсором
<Backspace> Удаление символа слева от курсора
<Shift>+<Home> Выделение текста от начала строки до курсора
<Shift>+<End> Выделение текста от курсора до конца строки
<Ctrl>+<Home> Перемещение в начало файла
<Ctrl>+<End> Перемещение в конец файла
Программирование вычислительных процессов
155
4.10. Отладочные команды
Команды меню Debug (Отладка), обеспечивающие работу с точками
прерывания, и кнопки панели инструментов редактора, дублирующие некоторые
из этих команд, являются не единственным набором отладочных средств.
Кроме них MATLAB предоставляет в распоряжение пользователя группу
команд (функций), к которым можно обращаться из командной строки
(табл. 4.3).
Таблица 4.3
Команда Назначение
dbclear Очистка указанных или всех точек и условий останова
dbcont Продолжение выполнения программы после останова
ribdown Переход на рабочее пространство следующего уровня '
dbquit Выход из режима отладки
ribstack Опрос состояния стека вложенных вызовов функций
d-bs tatus Опрос установленных точек и условий останова
dbstep Задание количества строк, выполняемых на очередном шаге
dbstop Задание точек или условий останова
dbtype Вывод m-файла или его фрагмента с номерами строк
dbup Переход на рабочее пространство предыдущего уровня
С помошыо функции dbtype можно вывести в командном окне текст пт-
файла с номерами строк или фрагмент этого файла:
» dbtype array2vec
1 function [varargout] = array2vec(a)
2 for k-1:nargout
3 varargout{k)=a(k,:);
4 end
» dbtype array2vec 2:3
,2 for k=l: nargout
3 varargout{k)=a(k, :) ;
Такой текст позволит вам выбрать строки программы, которые
целесообразно назначить точками останова. В командном окне для этой цели можно
156
Глава 4
воспользоваться функцией dbstop, обращение к которой допускает
несколько модификаций:
>> dbstop in array2vec at 3
% останов в файле array2vec.ra на строке с номером 3
» dbstop in array2vec
% останов на первой выполняемой строке в файле array2vec.n!
» dbstop in funl at subfun2
% Останов на первой выполняемой строке подфункции subfun2
% в файле funl.т
» dbstop if error
% переход в режим отладки, еслк Будет обнаружена ошибка
»■ dbstop if warning
% переход s режим отладки, если будет выдано предупреждение
» dbstop if naninf
» dbstop if infnan
% переход в режим отладки, если обнаружено НаН или °°
Служебные слова-связки типа if, in, at не являются обязательными и могут
быть опущены. Для набора точек условного останова три первые
модификации допускают расширение типа "if выражение". Останов происходит в том
случае, если при выполнении указанного оператора значение выражения
оказывается истинным. Вообще говоря, количество вариантов останова по
dbstop достигает 17, и с их полным перечнем можно познакомиться, набрав
В окне команд строку help dbstop ИЛИ doc dbstop.
Обращаясь к функции dbstatus, вы можете получить список всех точек
останова, действующих в данный момент (рис. 4.14).
Для отмены конкретной точки останова или всех точек останова можно
воспользоваться услугами функции dbclear:
» dbclear in array2vec at 3
% отмена точки останова в строке 3 файла array2vec.m
» dbclear all in arrayZ-vec
% отмена всех точек останова в файле array2vec.m
Программирование вычислительных процессов
157
» dbclear all
% отмена всех установленных точек останова
» dbclear if error
» dbclear if warning
» dbclear if naninf
% отмена заданных условий останова
f| Editor - C:\MATIAB6p5\work\array2vec.m
File Edit Text Ceil Tools Debug Desktop Window Help
DcS &\ x fee •--.»'!#;« f.:flfi,««S JBfJ|si«cK|i-.u!E J
ИПП
» j и 'x
1швэ|п
1 function [varargout] = array2vec(a)
2* foe k=l:nargout
3<> veeacgout|k|=a(k, :) ;
4 - end
<->MATLAB
File Edit Debug ■ Desktop Window Help
НПО
D G? J Щ Щ Щ *~i Г* j Щ Ы" | ~?S | CurrertDlrectOTt-|c:ViW7LASEp5\work zj jj Ё] '
» dbstop etcay^wec 2
» dbstop cH'i-'dy^vec 3
» dbstatus
Breakpoints for arrayZvec are on lines 2, 3.
»
Рис. 4.14. Установка точек останова и опрос статуса
Останов по любому поводу (попадание в точку останова, выполнение одного
из заданных условий) переводит программу в режим отладки, о чем
свидетельствует появление буквы к перед символами ». В этот момент в
командном окне действует локальное рабочее пространство функции — инициатора
останова. Для пошагового выполнения программы в режиме отладки можно
воспользоваться клавишей <FlO> (эквивалент команды Debug [ Step
(Отладка | Шаг)) или функцией dbstep. Нажатие клавиши <FlO> или вызов
функции dbstep без параметров приводят к выполнению следующей строки
программы. Числовой параметр в функции dbstep обеспечивает выполнение
указанного количества строк на очередном шаге отладки:
» dbstep .5
Если в точке останова находится оператор вызова функции, то возможны
два варианта — воспользоваться командой Debug [ Step In (Отладка | Шаг
внутрь) (эквивалент— клавиша <F11>) или командой Debug [ Step Out
(Отладка | Шаг наружу) (эквивалент — комбинация клавиш <Shift>+<Fll>).
158
Глава 4
В первом случае пошаговый режим выполнения программы
распространяется на операторы вызываемой функции. Во втором случае вызываемая
функция выполняется в автоматическом режиме, а после возврата из нее
восстанавливается режим пошаговой отладки.
После выхода программы на очередную точку останова вы можете
просмотреть переменные локального рабочего пространства в окне, раскрывающемся
по команде View | Workspace (Вид | Рабочее пространство) или при
выполнении команды whes. Если имела место пепочка вызовов, то кроме текущего
локального пространства могут представить интерес и переменные,
принадлежащие предшествовавшим функциям. Перемещения по локальным
рабочим пространствам вперед или назад обеспечиваются командами аьир
(возврат в рабочее пространство предыдущего уровня) и dbdown (переход в
рабочее пространство следующего уровня). Цепочку предшествовавших
вызовов можно проследить по содержимому стека обращений. Оно
отображается по команде dbstack. Находясь в отладочном режиме, можно не только
просматривать текущие переменные, но и менять их значения, а также
выполнять любые команды, которые разрешается набирать в командном окне.
С помощью функции dbquit осуществляется выход из отладочного режима.
Ее эквивалентом в главном меню является команда Debug | Exit Debug Mode
(Отладка | Выйти из режима отладки).
К режиму проверки корректности программы относится ее проверка с
помощью сервисной программы M-Linl, которая вызывается по команде
Tools | Check Code with M-Lint (Сервис | Проверить код с помощью M-Lint).
Идея полного синтаксического контроля программы и выявления в ней
подозрительных мест принадлежит сотрудникам BELL Laboratories. Она была
реализована примерно 30 лет тому назад в виде утилиты lint, через которую
пропускались все программы, написанные на языке С. В профамме lint
проверялись такие ситуации, как неправильное использование типов, ошибки
в передаче параметров функциям, неиспользуемые и неинициализируемые
переменные и многое другое. В том числе она выдавала сообщения о
трудностях переноса программы на компьютеры другого типа, связанные с
разрядностью, количеством регистровых переменных, порядком следования
байтов, размножением знака при сдвиге чисел вправо и т. п. Если
программа проходила такой контроль, то она компилировалась с помощью
достаточно простого компилятора, не предусматривающего столь тщательные
проверки. Своим названием программа lint предположительно обязана
аббревиатуре от Language Inlerprcier (интерпретатор языка).
Попытка реализации аналогичной идеи была предпринята в MAT LAB 7.
Возможно, что работа нал сервисом подобного рода будет продолжена, т. к.
некоторые наши попытки внести ошибки в достаточно простую программу
ставили M-Lint в тупик. На рис. 4.15 приведен результат анализа функции
polyline, не содержащей ошибок.
Программирование вычислительных процессов
159
Э Editor - H:\MATLAB7\work\polyline.m
File Edit Text Cell Tools De^jg Desktop Window Help ■_
DSB1 *■ «h Ш «' «•» ; ¥ I 44' /.-■' e €1 i :Ш *i © ЛЭШ ''stadc|e».^j
1 |function polyline(varargin)
2- for k=l: length (varargin)
3- x(k)=vara.rgin(k) (1) ;
"4- y(k)=vacaL'gin(k) (2) ;
5- end
6 - axis ( [min (x) max (x) min(y) max (y) ])
7- plot(x,y)
fV'M-Lint Code Check Report
File 'Edit View Go Debug Desktop Window Help
__„____
njx
Refresh
J M-Lint Code Checker Report
Report for file H: \MATEAB4-\waEk\polyline
j H:\HATbAB7\trjork\polyline.m
messages ;
3^_ Acray 'x' is constructed using subscripting.
Consider ^reallocating for speed
4:_ Array Ty" is constructed using subscripting.
Consider ^reallocating for speed
Рис. 4.15. Сообщения синтаксического анализатора M-Lint
%VM-Lint Code Check Report
File Edit View Go Debug Desktop Window Help
M-Lint Code Checker Report
Report tor tile i\: \riA'l'IiAB"?\molj~\plj!yli
H:\MATIiAB7\work\polyline.m
4
messages
1: Invalid character
1: Function name 'olyline' will bo known to MA'CLAB
by its file паше: 'polyline'.
'3.: Array 'x" is constructed using subscripting.
Consider praallocatino, for speed
4: Array 'y' is constructed using subscripting.
Consider ^reallocating for spepd
Рис. 4.16. Пример хорошей реакции на ошибку в программе
160
Глава 4
Несмотря на это, M-Lint выдала сообщения о том, что в 3-й и 4-й строках
программы использованы индексированные массивы и не мешало бы
подумать над способами повышения скорости работы программы.
Над попытками включить в программу неинициализированные переменные
анализатор M-Lint надолго задумывался, но никаких сообщений не выдавал.
Зато на использование запрещенного имени функции (вместо polyline мы
набрали noiyiine) выдал очень разумное сообщение (рис. 4.16).
4.11. Анализ эффективности программы
MATLAB 7 отличается от предыдущих версий еще и тем, что в его состав
входит утилита Profiler, которая позволяет построить профиль программы,
т. е. получить статистику по времени ее выполнения вплоть до каждой
строки исходного кода. Это помогает определить узкие места программы,
выделить строки программы, которые никогда не выполняются, узнать
количество обращений к той или иной функции и время ее работы.
Вызов программы Profiler может производиться разными способами: из
среды MATLAB (команда Desktop | Profiler (Рабочий стол [ Профайлер)), из
редактора кода (команда Tools | Open Profiler (Сервис | Открыть профайлер)),
из окна Command Window (Окно команд) с помощью строки profile
viewer. В окне Profiler (Профайлер) в поле раскрывающегося списка Run
this code (Запустить код) набирается имя анализируемой программы
(рис. 4.17) и нажимается кнопка Start Profiling (Создание профиля). Как
видно из приведенных ниже рисунков, анализировалась программа bench.т,
которая используется для определения производительности компьютера и
сравнения ее с лучшими моделями ПК.
Рисунок 4.17 отражает первичную выдачу результатов анализа, которая
начинается со списка выполнявшихся функций. В колонке Function name (Имя
функции) указывается имя функции, в колонке Calls (Вызовы) —
количество ее вызовов, в колонке Total Time (Всего времени) — общее время
пребывания в теле этой функции, включая и время работы всех вызываемых ею
функций, в колонке Self Time (Собственное время) — исключено время
работы вызываемых функций, а в последней колонке графически отображены
оба указанных времени, выделенные разными цветами.
Порядок функций в списке соответствует последовательности их вызовов.
Если щелкнуть мышью но заголовку Function name (Имя функции), то
список перестраивается в алфавитном порядке, что упрощает поиск нужной
функции (рис. 4.18).
Щелчок по имени функции перемещает нас на соответствующий кадр
отчета (рис. 4.19). В нашем примере была выбрана функция ode45.m.
Программирование вычислительных процессов
161
Profiler
♦•чей \'& | «
StwiPiolfevjl fcj\WscCKh£| bench
Г " ~~ ""
Profile Summary
! Generated U-Sep-2004 18:54:26
Function name
1
bench
ode45
newplol
iiewpIot>ObserveAxes>.rextPlot
grapIiicsVprivaleXcIo
1 b_nu|i
membrane
1 rcpmal
iiiiifun\priv!iieVntrp4S
Proite 1 Commend V.1«Jow I
<kSlul|
i Calls
J-
;1
\l
47
1
47
47
2
■
4.
2166
, 1080
Total
1 6.797 s
0.984 s
0.422 s
0.391 s
0.359 s
0.219 s
0.203 s
0.203 s
0.188 s
Self
Time*
4.703 s
0.547 s
0.031 s
0.000 s
0.156 s
0.000 в
0.063 s
0.203 s
0.031 s
r
zl:«>
>то№11те:Л08ёе
Total Time Plot
(dark band = self
time)
шш^шяш
■3
«
it
'■
1
'
■
1
i
i
i
i
i
i
1 .
l
J
/>
Рис. 4.17. Начальный кадр отчета программы Profiler
Profiler
+• <+-С tUIS'M
sort Prolyl Run Ws code | bench
Profile Summary
Generated ll-Sep-2004 21:06:32
■ Function name
■
ancestor
ancestorHsalvpe
autoinc-sh
axes (Opaque-function)
1 axesclieck
; Hsis
nxis^LocSetLiniits
_
Calls
60
120
7
80
5
3
1
Total
Time.
0.063 s
0.031 s
0s
0s
0.016 s
0.031 s
0.016 s
» X
^J ^ProlirilliM-IOjec
Self Total Time Plot
Time* (dark band = self
time)
function is recursive
function is recursive
0.000 s
0.000 s
0.016 s 1 '
0.016 s |
0.016 s ;
Рис. 4.18. Профиль программы с упорядоченным по алфавиту списком функций
162
Глава 4
Profiler
Sail Pnfflre] feJnlhlEccde: Iberch
•*| ♦.ProIllelmeilOKC
ode45 (2 calls, 0.984 sec)'
Generated Il-Sep-2004 21:09:54
M-function in file H:\MATLAB 7'Joolbpx'-iiialliJ>\runliintode45.m
[£.°1&!!° .u£w wjudow lor comparing нш1пр1с..шш?]
Reftosn |
P Show parent files P Show busy lines P Show child files
P Show M-Lini results <* Show file coverage P Show file listing
Parents (calling fund ions)
Filename File Type Calls
bench M-funclion 2
Lines where the most time mis spent
Line Number
Code
Calls
Total
Time
% Time
Time Plot
Protihlr]Cc<fflrflndv»dtiw|
j^StenJ
'il
Рис. 4.19. Начало профиля по функции ode45.m
Profiler
4- ■*• О А «3 *4
Нв1РтоП1пд[ RwltNscooc: ]
bench
Lilies whore the most time was spent
Line Number
■ffl
Ш.
-У.5
325
Й1
Otlier lines &
overhead
Tolals
Code
youI:_riavi = luTirpfl; (tcef, t, у, [I . .
t(:,4) = fevnWocSeFcn. T^liAP), . .
f(j,3] = 1 eve 1 (sdr-F^n. r-hA [2)-. ..
ft:,2) = ipvoHMaFcn. t*h_M.U , ..
Children (called /unctions)
«1
Prolllsr 1 Ccimrnr.dVAWov.' |
^vsiirtj
Calls
■ 1080
■ 1326
t
■ 1326
• 1326
Total
Time
0.23.1 s
0.094 s
0.063 s
0.063 s
0.063 ?
0.469 s
0;9K4 £
_ d
%
Time
23.8%.
9.5%
6.3%
6.3%
6:3%
47.6%
100%
1
¥ X
♦ Prof lo urn, 10 sec
_J
Time
Plot
—
■
■
о
■
—
3
s
Рис. 4.20. Статистика по работе функции ode45.m
Программирование вычислительных процессов
163
В этом фрагменте профиля можно увидеть (рис. 4.20) статистику по
наиболее долго выполнявшимся строкам программы. Следующий кадр (рис. 4.21)
отражает статистику работы вызываемых функций.
♦••*:--. ^а а л
53nrt Prefbnp | RltIWs code: ] bench
Children (called functions)
Filename
&»funiprivaicaihTj45
V(Ip 1
furiftn'jirivaKAocIear^uincirts
ftuiiuiityrivnic lode-final ize
limfiimprivateVodemass
odegel
ftuifimtynvoreXoflecvents
Self time (buill-iiis. overhead,
Totals
i
FrolHer [ccmmendWndow j
ф Start |
File Type
M-fuiicti'on
M-fiuicliou
M-funclion
M-fimction
M-fuiiclion
Ivl-fuiiciioil
M-fiiuction
etc.)
Calls
1080
7956
2
2
2
6
2
Tola! Time
0.188 s
0.109 s
0.063 s
0.063 s
0.016 s
0s
Cs
0.547 s
0.984 s
% Time
19.0%
11.1%
6.3%
6.3%
1.6%
0%
0%
55.6%
100%
J*J ^ Pi'oil* tune
Time Plot
-
a
f
i
i
_J
10 з«
j
Й
Рис. 4.21. Статистика по работе функций,
вызываемых из ode45.m
Предпоследний фрагмент отчета (рис. 4.22) включает предупреждения
программы M-Lint и итоговые результаты профилирования. Самая последняя
часть отчета содержит текст анализируемой программы с указанием времени
работы каждой строки. Не выделенные цветом строки — затратившие
меньше всего времени, слева от их текста ничего не указано. Затем по мере
возрастания времени работы окраска строк изменяется от светло-розовой до
темно-красной (рис. 4.23).
Полученный профиль можно сохранить в файле для последующего
изучения узких мест программы с целью повышения ее производительности.
164
Глава 4
Profiler
«• •* о л. & ;■**
SJ*1Pro№rig[ Run W» coda, jbtnch
. ftl-Luit results
Line number Message
402 ^be value aaaignod hexre to variable 'ignore*
Coverage results
\ Show coverage for parent directory 1
Total lines in file 513
' Non-code lines (comments, blauk lines) 199
Code lines (lines that can run) 283
Code lines that did ran 155
Code I ines that did not run 128
Coverage (did run/can run) 54.77 %
■■«1
Profile* ]-CwnmenflVvVH)ow |
^St»rt|
л X
**] фРгоПскпеЮвое
"" " " ' ' "4
i
ia nisvBE uaecl |
'
1
1
1
1
1
i
i 3
Рис. 4.22. Итоговые результаты профилирования
Profil
4- ■* a
Start Proimg
,!i-.
. US
1
1
1
1
l ■ 11
1 ■ JS
m
."". j:'.-
<l
er
й!<9|«
№iim«i№|b«Kh
mso 32o
ioso _37i
1Э7.6 322
13S5 эгз
U2u _32J
И* -MS
1эгб _Э26
иге я?7
1Л2Й _Э2И
1.326 ЗЭО
i3ze эзз
■s _MZ
5 _33J
ж* _ш
1зг«, ззц
1эгй _эз*.
Praliter I CowAfld window]
Фявп[
< "1." "Г S" -1
nofailed =
while true
hA = h •
ЬВ = h -
£(:,2) =
t(:,2) =
£(:,4) =
«(=.5) =
£(:,6) =
t.new = t
i£ clone
tnew =
end
h = .fcne'-n
ynw = у
£(:,7) -
Г
d
true; Й no faij-ed a-fceem
ф Prnffleffre: 10
A;
B>
teval (odcFcn, t+hA(l) , y+£*hB (.,1), odeArga [ : })
t eval (odeFen, t+hA(2) , y+fhE (:,2), odeArg-sJ : 1 )
fevalfodeFen, t+hA£3 ), У» **"№£: ,3). odeAtKal: )1
fevelCedeFcn, t-i-hAH) ,y+f *hB(: , 4 } , odnAegsJ ; \ )
fevuliDdeFcn, t+hA.£5),y+f *hB(: ,5), adeArnsf : ()
+ hA£S);
tiinal; ft Hie end point exactly.
- tj i Purify h.
*■ £.'hB(:,6j;
fevol fodeFcn, tnew, ynew, odcAraaI:">) ;
1
X
вес
;
1
!
1
1
1,
i
"j
A
4
Рис. 4.23. Текст исходной программы с информацией о работе каждой строки
Глава 5
Обработка символьных данных
5.1. Создание символьных объектов
Чаше всего в системе MATLAB приходится работать с символьными
данными в виде строк (векторов-строк размерности 1х/и), массивов строк
равной длины (матриц размерности пхт) и массивов ячеек, каждая из которых
представлена строками разной длины. Создание соответствующих
переменных происходит при формировании тех или иных символьных значений с
помощью оператора присваивания (пример 5.1).
[: Пример "Й#:уЗри^^
% Формирование вектора-строки
>> str='ABCDE'
str =
ABCDE
» whos
Name Size Bytes Class
str 1x5 10 char array
Grand total is 5 elements using 10 bytes
%■ Формирование массива строк
» st.r_mas=['1234'; 'ABCD']
strjmas =
1234
ABCD
» whos
Name Size Bytes Class
str_mas 2x4 16 char array
Grand cotal is 8 elements using 16 bytes
% Формирование массива символьных ячеек
» str cell=[{'123',,ABCD');{,4567,f*abc'}]
166
Глава 5
str cell =
423'
'4567■
» vjhos
Name
str .cell
'7ABCD'
■abc'
Size
2x2
Bytes Class
263 cell array
Grand total is 18 elements using 268 bytes
На каждый символ во внутреннем представлении отводится по 2 байта в
кодировке ASCII Unicode. Однако для программистов, привыкших к
однобайтовой кодировке ASCII (в Windows — кодовая страница 1251), никаких
вопросов с числовыми кодами букв латинского алфавита не возникает:
char(65)=A char{66)=3 ... char(90)=Z
int8('A'|=65 LntB('B'}='66 ... int8('ZM=90
char(97)=a char(9-8)=b ... chart 122 )=z
int8('.a')=57 intS('b')=9S ... intS t 'г' )=122
Для преобразования символа в числовой код можно воспользоваться любым
ДОПУСТИМЫМ форматом — uintS, intib, uintlE, int32, uint32, single.
double. Однако с типами inte или uinte вас могут поджидать
неожиданности, т. к. в этом преобразовании участвуют только 7 или S младших битов.
Если преобразуемый код выходит за пределы допустимого интервата, то
результат заменяется соответствующим граничным значением:
int8('fl')=127 uinc8(,R,)=255
Дело в том, что для символов русского алфавита используется настоящая
двухбайтовая кодировка:
chart 1040) =А char (1041)=Б ... char. (10.71 )=Я char(1025)-E
апсШ'А'НЮЗ intl6('B*)=10'1 ... intl6('Я')=107 intl6 ('Е')=1025
0 1 1
char(1072)=a char(10/3)=6 ... спаг(1103)=я char(1105)=е
intl6('a')=107 intl6('6')=107 ... intl6('я')=110 intl6('e')=1105
2 3 3
Аргументом функции char может быть не только целое положительное
значение в формате double, но и любой числовой массив с такими же
компонентами:
» char([48 49 50; 65 66 67; 1088 1089 1090])
ans =
012
ABC
рст
Обработка символьных данных
167
С помощью индексной конструкции типа сокращенного цикла (п1.-л2) и
функции ehar можно сформировать строки, представляющие наиболее
употребительные фрагменты таблицы ASCII (пример 5.2).
\ Пример 5.2* Печать таблицы ASCI! ^^4Ш0^&^'-:^^^^^Ф^ -.-:$■ i
» char(32:64}
ans =
!"#$%&' ()*+,-./0123456789:;<=>?@
» char(65:96)
ans =
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]Л_"
» char(97:126)
ans =
abcdefghijklmnopqrstuvwxyztI}~
» char(1025 1105)
ans =
Ее
» char(1040:1071)
ans =
АБВГДЕЖЗИЙКЛШОПРСТУФХЦЧЖЦЬЫЪЗЮЯ
» char(1072:1103)
ans =
абвгдежзийк.пмнопрстуфхцчшщъыьэюя
Если в качестве аргументов функции char выступают строки разной длины,
то функция возвращает символьный массив, дополняя более короткие
аргументы пробелами справа:
» char('ABC, 4234')
ans =
ABC
1234
Наконец, аргументом функции char может быть массив ячеек, каждая из
которых, в свою очередь, представлена строкой. И в этом случае функция
char в качестве результата тоже возвращает символьный массив, размещая в
каждой его строке очередную ячейку и выравнивая длины строк
(пример 5.3).
168
Глава 5
|Пример 5.3. Преобразование массива ячеек в символьный массив. ^\^$^ШЦ 1
» S=char(f 'ABC, 4234*})
S =
ABC
1234
» whos
Name Size Bytes Class
S 2x4 16 char array
Grand total is 8 elements using 16 bytes
Таким образом, с помощью функции char допустимо формировать
символьные строки или массивы строк. И в качестве ее аргументов могут
выступать не только отдельные строки, но и символьные массивы.
Для доступа к любому фрагменту строки можно использовать пару
индексов, разделенных двоеточием (пример 5.4).
г Пример 5.4. Выделение фрагментов строки ^'^^4™:^!:#^1'|^:^й?'^>йж-Т Т Л
» S='C Новым Годом!';
» S(l:2)
ans =
С
» S(3:8)
ans =
Новым
» S(9:end)
ans =
Годом!
Служебное слово end заменяет максимальное значение индекса.
Из массива строк с помощью двух индексов i и j (i — номер строки, j —
номер столбца) можно извлечь любой символ (пример 5.5).
I Пример 5.5. Извлечение символа из массива строк Ci-,f-a -л-':' ко *--м-4 ■ ■"■^i
» s=char([48 49 50; 65 66 67; 1088 1089 1090])
012
Обработка символьных данных
169
ABC
рст
» s(2,3)
ans =
С
Для того чтобы извлечь из массива строк нужную строку, можно
воспользоваться одной из индексных конструкций, представленных в примере 5.6.
» s (2,:)
ans =
ABC
» s (2,l:end)
ans =
ABC
Из массива ячеек с помощью индексных выражений можно извлечь
конкретную ячейку, строку или столбец ячеек (пример 5.7).
; Примеру fcf/';'Vl-«-?^,,^/>"Tj£:jv'"1k" v "" . -j
» s_c=H423', 'ABCD');{'4567', 'abc'l]
s_c =
'123' 'ABCD'
•4567' 'abc'
» s_c(l,2)
ans =
■ABCD'
» s_c(l:2)
ans =
• 123' •4567•
» s_c(l,:)
ans —
'123' '.ABCD'
Особую роль в символьных данных играют пробелы, обычно выступающие в
качестве разделителей слов. Иногда их приписывают в начало или в конец
строки для того, чтобы произвести соответствующее выравнивание по левой
границе или по длине. Для формирования строки, содержащей заданное
170
Глава 5
количество пробелов, можно воспользоваться функцией blanks (п).
Лидирующие и концевые пробелы можно удалить с помощью функции debiank.
Если в строке присутствуют начальные и конечные пробелы, то, не изменяя
длину строки, с помошью функции strjusu можно ее значимое содержимое
разместить строго по центру, прижать к левой или правой границе
(пример 5.8).
Т- : '"""ШШ
У Пример 5.8: Выравнивание строки<
» 5=' 12345
S =
12345
» SL=strjuat(S,'left')
SL =
12345
» SC=strjusc(S,'center'J
SQ =
12345
» SR=Ftrjust(S,'right')
SR =
12345
» SRl=strjust(S)
SRI =
12345
>> whoe
Name Size
S lxll
SC lxll
SL lxll
SR lxll
SRI lxll
* - Iм5,1 .,■
Bytes
22
22
22
22
22
з®,Ш-
Class
char array
char array
char array
char array
char array
Grand total is 55 elements using 110 bytes
В отличие от языка С, строки MATLAB не завершаются нулевым байтом.
Это означает, что набор символьных данных класса char хранит длину
текущего значения строки, которое может быть опрошено с помощью
функции length:
» length{'ABC')
ans =
3
Обработка символьных данных
171
Применение функции length к символьному массиву позволяет определить
длину любой его строки:
» S=['ABC '; 4234']
S =
ABC
123.4
» length(S)
ans =
4
MATLAB позволяет работать со строками практически неограниченной длины.
Строку или массив строк, заполненные одним и тем же символом, можно
создать с помощью функции repmat (размножение матрицы) — пример 5.9.
;■■ ■■"■■"•••• v-'-'i";""--?--^^^
г Пример 5Д, Запо^нщ^ро^01^Щ^Ш^Ш^-' *f^M$?V^# >",* ,, г!
» repmat {' = ', 1,4}
ans =
» repmat С*', 3,4)
ans =
■*■*-* +
А--* А*
5.2. Конкатенация строк
В простейшем случае результатом конкатенации двух строк si и S2 является
строка, получаемая приписыванием значения S2 вслед за значением si.
Такая процедура носит название горизонтальной конкатенации и выполняется с
помощью функции strcat:
S = strcat(SI, S2, S3, ...)
Если аргументами функции strcat являются строки, то она возвращает
строку, полученную в результате последовательного присоединения
значений входных операндов друг за другом (пример 5.10).
I Пример 5.10. Конкатенация строк \ .^--^-.- - ^у--,;/-^-.^ ' ->«_. ч ' 3¾¾
» S=strcat('123','ABCDEFG')
S =
123ABCDEFG
172
Глава 5
» whos
Name Size Bytes Class
S 1x7 14 char array
Grand total is 7 elements using 14 bytes
Однако в качестве аргументов этой функции могут выступать и символьные
массивы, содержащие одинаковое количество строк. В этом случае
результатом работы функции strcat является символьный массив, каждая строка
которого получена как горизонтальная конкатенация соответствующих строк-
операндов (пример 5. II).
ГПример5:1иЙ:о$|э^ =^$£»f ?4$ЩЩ
» S=strcat[[,123,;,ABC'],['5678';'abed'])
S =
1235678
ABCabcd
» whos
Name Size Bytes Class
S 2x7 28 char array
Grand total is 14 elements using 28 bytes
Аргументами функции strcat могут быть и массивы ячеек, содержащие
строки разной длины. В этом случае результирующий массив также будет
состоять из ячеек, полученных с помощью горизонтальной конкатенации
содержимого соответствующих ячеек (пример 5.12).
;.Пример 5.12. Конкатенация массивов ячеек ■ ■■^■«■-ф ^■^■^^v.-b.^,.,.^^.^^
» S=strcat({'12-3',*ABCD'I,['45678','xz'})
S =
'12345678' 'ABCDxz'
» whos
Name Size Bytes Class
S 1x2 148 cell array
Grand total is 16 elements using 148 bytes
Применяя горизонтальную конкатенацию, не забывайте об одной тонкости
ее выполнения — в отличие от аналогичной операции сцепления строк
массива функция strcat игнорирует пробелы в конце строки (пример 5.13).
Обработка символьных данных
173
» strcatCC ','Новым ','Годом!')
ans =
СНовымГодом!
» strcat('С1,1 Новым',' Годом! ')
ans =
С Новым Годом!
» ['С ', 'Новым ','Годом!'!
ans =
С Новым Годом!
» [' С.', ' Новым', ' Годом! ' ]
ans =
С Новым Годом!
Кроме горизонтальной конкатенации строк MATLAB предлагает и
вертикальную конкатенацию, выполняемую с помощью функции strvcat
(пример 5.14).
цПример 5.14.'Вертикальная конкатенация строк М$^:^^Ш^'^^^^^^М^
» S=strvcat('123','ABCDEFG')
S =
123
ABCDEFG
» whos
Name Size Bytes Glass
S 2x7 28 char array
Grand total is 14 elements using 26 bytes
В отличие от горизонтального присоединения операндов при вертикальной
конкатенации "объединяемые" строки подписываются одна под другой,
создавая столбец в результирующем массиве. Это происходит и в том случае,
когда операндами являются массивы строк (пример 5.15).
i Прим6р;5?15. Вертикально "•*'■ г??*.. >■ ]
» S=strvcat(I'123';'ABC'],['5678';'abed']}
S =
123
174
Глава 5
две
567S
abed
» whos
Name Size Bytes Class
S 4x4 32 char array
Grand total is 16 elements using 32 bytes
Вертикальная конкатенация массива ячеек, состоящего из строк,
преобразует свой единственный операнд в символьный массив (пример 5.J6).
г ' ' V- ;; .■...«....■v.»-.......».../.-;.^-,,»—".■..•■..■ : y...^........^^...^................^.^ .„,
; Пример 5.16. Вертикальная конкатенации массива ячееклйй t^ Д&д*:?",.-^1 '-л* ч щМ
;Л ™...,.-..fc..:si'...;;!j:'.i '......Г. i...^.s.a..%i:v.;.iVwtf.^.i.;W.i'i:.::.\.^
» S=strvcat(('123','ABCD'})
S =
123
ABCD
» whos
Name Size Bytes Class
S 2x4 16 char array
Grand total is 8 elements using 16 bytes
Несмотря на то, что процедура горизонтальной конкатенации напоминает
функцию с аналогичным названием из библиотеки С (раздел siring.h),
возможности ее в системе MATLAB гораздо шире за счет использования
операндов-массивов.
5.3. Сравнения символьных данных
Так как символьные данные представлены в памяти компьютера числовыми
кодами своих символов, упорядоченными в алфавитном порядке, то их можно
сравнивать примерно как и значения числового типа. В- большинстве
алгоритмических языков именно так и поступают, выясняя, равны или не равны
сравниваемые строки, какая из них меньше или больше. Два последних
соотношения позволяют определить порядок следования строк при их
лексикографическом упорядочивании (т. е. при сортировке в алфавитном порядке).
В большинстве систем программирования, конечно, возникают разного рода
проблемы, связанные со сравнением русскоязычных строк или с
преобразованием символьных данных к верхнему или нижнему регистрам. Например, в
кодовой странице MS-DOS с номером 866 между кодами малых букв "п" и "р"
затесались символы псевдографики, а коды букв "ё" и "Ё" расположены не на
Обработка символьных данных
175
своих законных местах. Такого же рода участь постигла буквы "ё" и "Ё" в
кодовой странице Windows с номером 125L
Функции сравнения символьных данных, представленные в MATLAB,
производят проверку только на равенство или неравенство операндов, в
качестве которых могут выступать не только строки, но и массивы строк. В
последнем случае операция сравнения выполняется над каждой парой
элементов с одинаковыми индексами. Результат каждого такого сравнения
вырабатывает логический признак 1 (истина) в случае совпадения значений
и логический признак о (ложь) в случае несовпадения. Если все
промежуточные сравнения выработали единичные признаки, что свидетельствует об
абсолютном тождестве сравниваемых данных, то функция возвращает
логическое значение 1. Если хотя бы в одном промежуточном сравнении
обнаружено расхождение, то функция возвращает логическое значение о. Если
сравниваемые данные представлены массивами ячеек одинаковой
размерности, то функция сравнения возвращает логический массив той же
размерности, где каждый элемент равен 1 или о в зависимости от совпадения или
несовпадения значений соответствующих ячеек.
Для сравнения символьных данных язык MATLAB предлагает четыре
функции: stremp, strempi, strnemp и stmempi. Первая из них производит
посимвольную проверку на равенство или неравенство всех элементов
сравниваемых операндов, вторая выполняет аналогичное сравнение, игнорируя
разницу между кодами больших и малых букв, третья сравнивает только
заданное количество начальных символов, четвертая сочетает в себе
возможности второй и третьей (пример 5.17).
%Сравне'ние векторов-строк
» S1='ABCDEFGH';
» S2='ABCDefgh';
» ЭЗ-'АВСаЬс';
% Сравнение на абсолютное совпадение всех символов
» stremp(S1,S2)
ans =
О
% Сравнение с игнорированием разницы между большими и малыми буквами
» strempi(S1,S2)
ans =
1
176
Глава 5
1
» whos
Name
SI
S2
S3
ans
Size
1x8
1x8
1x6
lxl
% Сравнение на абсолютное совпадение первых 3 символов
» strncmp(Sl,S2,3)
ans =
Bytes Class
16 char array
16 char array
12 char array
1 logical array
Grand total is 23 elements using 45 bytes'
% Сравнение символьных массивов
» SM1=['1234567';' ДБВГДЕЕ'];
» SM2=['1234567';' АБВГдее1];
» strcmp(SMl,SM2)
ans =
1
» strncmp(SMl,SM2,4)
ans =
1
» strcrapi(SMl,SM2)
ans =
0-
» SM3=['123456';' АБВГДЕ'];
» SM4=['123456';' ДБВгде'];
» strcmpi(SM3,SM4)
ans =
1
% Сравнение массивов символьных ячеек
» SC1=[{Ч234'},{'ABCDEFGH'}] ;
» SC2=[{'1235'},{'ABCDefgh'}];
» strcmp(SCl,SC2)
ans =
0 0
» strcmpi(SCl,SC2)
ans =■
0. 1
Обработка символьных данных
177
» whos
Name Size Bytes Class
SCI 1x2 14 4 cell array
SC2 1x2 144 cell array
ans 1x2 2 logical array
Grand total is 30 elements using 290 bytes
» strncrep(SCl,SC2,3)
ans =
Обратите внимание на результаты сравнения массивов (smi, sm2) и
(бмз, SM4) с помощью функции strcmpi. В операционной системе Windows
ХР буквы "Ё" и "ё" сравниваются нормально, несмотря на то, что разница
между их числовыми кодами отличается от разницы между числовыми
кодами больших и малых букв русского алфавита. В предыдущих версиях
MATLAB результат такого сравнения был противоположным.
Одним из аргументов в операции сравнения может быть скалярная
величина, и тогда она сопоставляется с каждым элементом второго аргумента —
массива строк или ячеек. Возвращаемый результат в этом случае будет
логическим массивом.
К группе процедур сравнения следует отнести функции isspace и isletter,
операндами которых могут быть строки, массивы строк или массивы
символьных ячеек. Обе функции возвращают логический массив такой же
размерности, как и размерность операнда. Функция isspace заносит в
позицию результата, соответствующую каждому проверяемому символу, 1
(логическая истина) или о (логическая ложь) в зависимости от того,
является или не является анализируемый символ белым пробелом. Множество
белых пробелов составляют символы НТ (горизонтальная табуляция — код
0x09), LF (перевод строки — код Оход), VT (вертикальная табуляция — код
Охов), FF (новая страница — код Охос), CR (возврат каретки — код OxOd) и
настоящий пробел (код-0х2о). Функция isietter анализирует, является или
не является проверяемый символ буквой (пример 5.18).
[; Примё£5:18. Проверка наличия пробелов й символов в;«троке^й^ ".__; *": !
» isspace('С Новым Годом!')
ans =
Columns 1 through 11
01000001000
Columns 12 through 14
0 0 0
178
Глава 5
» isletter('С Новым Годом!'>
ans =
Columns 1 through 11
10111110111
Columns 12 through 14
110
» whos
Name Size Bytes Class
ans 1x14 14 logical array
Grand total is 14 elements using 14 bytes
5.4. Поиск и замена
Функции findstr и strf ind предназначены для поиска всех вхождений
одной строки в другую (пример 5.19). Разница между ними заключается в том.
что функция findstr демократичнее и позволяет задавать операнды в
любом порядке — сначала более длинная строка, а потом более короткая, и
наоборот. Функция strfind выполнена в стиле стандартов универсальных
алгоритмических языков, и искомая подстрока обязательно должна быть
представлена вторым аргументом.
[ Пример 5". 1'9. ПриЬк в символьных данных • !'y^r ^-1 J ;'"
» S1='00\-
» S2='2O03';
» S3='100002';
» findstr(SI,S2) % Порядок операндов роли не играет
ans =
2
»■ findstr(S2,SI) % Порядок операндов роли не играет
ans =
2
» strfind(SI,S2) % Порядок операндов важен
ans =
[1
■>> strfind(S2,Sl) % Порядок операндов важен
ans —
2
» 33.= 400002 4-
Обработка символьных данных
179
» findstr (S3, S.I.) % Пример множественного вхождения
ans =
2
.» whos
Name
SI
S2
S3
ans
3
Size
1x2
lx<5
1x6
1x3
Bytes Class
4 char array
В char array
12 char array
24 double array
Приведенные выше функции возвращают результат поиска в виде числового
массива типа double, каждый элемент которого определяет индекс символа,
с которого обнаружено очередное вхождение.
Другой вариант поиска можно осуществить в массиве строк или в массиве
ячеек с помощью функции strmatch (пример 5.10). Ее особенность
заключается в том, что в массиве, представленном первым аргументом,
отыскиваются строки, начинающиеся со значения второго аргумента. Внутреннее
вхождение поискового образа здесь во внимание не принимается. При
добавлении третьего аргумента 'exact' функция strmatch возвращает номера
только тех строк первого операнда, которые в точности совпадают с
поисковым образом.
| Пример 5.20. Поиск в символьных данных с использованием функции s/
I strmatch ~ !
% Поиск- в массиве строк
%====,====
» SM=strvcat{"com','compare','computer')
SM =
corn
compa re
computer
» strmatch('com',SM) % поиск строк, начинающихся с 'com'
ans =
1
2
3
» strmatch('com',SM, 'exact') % поиск точного совпадения
ans =
1
180
Глава 5
» S=423com';
» strmatch('com',S) % внутреннее вхождение игнорируется
ans =
U
% Поиск в массиве ячеек
». SC={'com';'compare';'computer')
SC =
'com'
'compare'
'computer'
» strmatch('com',SC)
ans =
1
2
3
» whos
Name
S
SC
SM
ans
Size
1x6
3x1
3x8
3x1
Bytes Class
12 char array
216 cell array
48 char array
24 double array
Как можно заметить из приведенного примера, возвращаемое значение
функции strmatch представлено числовым массивом типа double.
Функция strrep(strl,str2,Str3) предназначена для поиска в строке strl
всех вхождений заданной цепочки символов str2 и замены каждой из них
новым значением str3 (пример 5.21). Если поиск не увенчался успехом, то
функция strrep возвращает строку strl.
Пример 5.21 ;„Поиск.и замена в символьных данных -1^^:.- V-= ti- *.-:> ^¾^
» S='12341234';
» Sl=strrep(S,'123','ABCD')
51 =
ABCD4ABCD4
» S2=strrep(S,424','ABCD')
52 =
12341234
Обработка символьных данных 181
Замещающее значение может быть пустой строкой, и таким образом легко
удалить ненужную цепочку символов (пример 5.22).
I Пример ^22. Удаление цепочки символов --¾¾¾^¾¾¾¾^ . *'Щ:~*^'&Щ£%&^^ \
» S3=st.rrep (S, ' 123', " )
S3 =
44
Если один из аргументов функции strrep представлен массивом ячеек, то
возвращаемый результат тоже преобразуется в массив ячеек (пример 5.23).
(Пример 5.23. Поиск и замена в массиве ячеек ^^¾¾ £^--.- {?fc^£?£?&й£Г 4^.1
» Sl='12341234';
» S2=strrep(Sl,'123\ ( " ))
52 =
■44'
» whos
Name Size Bytes Class
51 1x8 16 char array
52 lxl 64 cell array
Термин лексема обозначает цепочку символов, завершающуюся тем или
иным разделителем. Например, в предложении лексемами являются слова,
признаком конца которых могут быть разные разделители — пробелы,
запятые, точки, тире и др. При разработке трансляторов довольно часто
приходится выделять лексемы типа служебных слов, имен функций, операндов,
выражений и т. п. Облегчить эту работу вам поможет функция strtok,
основным аргументом которой является анализируемая строка. По умолчанию
данная функция рассматривает в качестве символа-разделителя любой
белый пробел. Выходных аргументов у этой функции два:
lt,r]=strtok(S)
В строку t заносится найденная лексема, а в с фоку г — оставшаяся часть
строки s (пример 5.24).
[Пример 5:24. Выделение лексем .."'- ' >■ ■* /'"* Л",г" ^-¾^^ " '* ' Щ^Щ
» S='C Новым Годом!';
» [tl,rl]=strtok(S)
182
Глава 5
tl =
G
rl =
Новым Годом!
» [t2,r2]=strtok(rl)
t2 =
Новым
г2 =
Годом!
» [t3,r3]=strtok(r2)
t3 =
Годом!
r3 =
Empty string: l-by-0
Второй необязательный аргумент функции strtok позволяет задать
нестандартный набор символов-разделителей (пример 5.25).
; Пример 5.25. Выделение лексем с'нестандартными разделителями
» S='a+b*c';
» [tl,rl]=strtok(S,'+*')
tl =
а
rl =
+b*c
» [t2,r2]=strtok(rl,'+*')
t2 =
b
r2 =
*c
» [ t3, r31 «strtok (i:2 ,■ + *')
t3- =
С
r3 =
Empty string: l-by-0
Обработка символьных данных
183
5.5. Преобразования к верхнему
и нижнему регистрам
Функция strcmpi позволяет сравнивать строки, игнорируя разницу между
большими и малыми буквами. На самом деле для выполнения такой
процедуры можно воспользоваться одним из двух алгоритмов — предварительно
преобразовать коды всех символов к нижнему (т. е. к строчным буквам) или к
верхнему (т. е. к прописным буквам) регистру, а затем произвести
посимвольное сравнение. Такое преобразование, если оно понадобится в вашей
программе, можно выполнить с помощью одной из функций — lower или upper
(пример 5.26).
I Пример 5.26. Преобразование регистра •• -%-г %%■*£-■ *%Щ
>> lower('Happy New Year - С Новым Годом!1)
апз =
happy new year - с новым годом!
» upper ('Happy New Year - С Нозьел Годом!')
ans =
HAPPY NEW YEAR - С Новым Годом!
MATLAB 7, в отличие от предыдущих версий, правильно обрабатывает
строки, содержащие буквы "ё" и "Ё":
» lower('ЁЛКА')
ans =
ёлка
» upper('ёлка')
ans =
EUKft
5.6. Преобразования строк и чисел
Значения числовых скалярных величин и элементов массивов типа double
могут быть преобразованы из машинного представления в соответствующие
символьные строки с помощью функций num2str и int2str. Первая из них
преобразует компоненты единственного аргумента с четырьмя цифрами в
дробной части (пример 5.27).
7 Чак SB9
184
Глава 5
» num2str(pi)
arts =
3.1416
» whos
Name Size Bytes
ans 1x6 12
.Grand total is 6 elements using 12 bytes
Второй необязательный аргумент в этой функции определяет количество
цифр в дробной части результата, однако бесполезно задавать его значение
большим, чем это предусмотрено форматом double (пример 5.28).
I Пример 5.28. Преобразование; числа в'чйрс^^^^НнЬй'тотност^!^^!1^^
» num2str(pi,10)
ans =
3.141592654
» num2str(pi,20) % Больше 17 цифр формат double не хранит!
ans =
3.1415926535897931
Аргумент функции num2str может быть и комплексным числом
(пример 5.29).
!'"'Пример^5;2£::Пре0бразовШй'е'-кЬч^^
» x=sqrt(-2)
x =
0 + 1.4142i
» num2str(x, 10)
ans =
0+1.414213562i
» whos
Name Size
ans 1x14
x lxl
Grand total is 15 elements
Class
char array
Bytes Class
28 char array
16 double array (complex)
using 44 bytes
Обработка символьных данных
185
Вообще, функция num2str допускает гибкое управление форматом
преобразования числовых данных (пример 5.30) подобно тому, как это делает
процедура sprint f.
[Пр^^р^^^ spj
» num2str(pi,'pi=%6.2f')
ans =
pi= 3.14
» whos
Name Size Bytes Class
ans 1x9 18 char array
Grand total is 9 elements using IB- bytes
Функция int2str предварительно округляет компоненты своего числового
аргумента до целых чисел и сохраняет в возвращаемом массиве строк все
значащие цифры. Иногда обилие нулей может удивить даже опытных
программистов (пример 5.31).
а встроку^К*4^ftW-.n4s-tTl
Пример 5.31. Преобразование целого числа в строку
» х=[[0'.1 0.5 0.8];[100.1 100.5 100.8]]
х =
0.1000 0.5000 0.8000
100.1000 100.5000 100.8000
» int2str{x)
ans =
0 11
100 101 101
» whos
Name Size Bytes Class
x 2x3 48 double array
ans 2x13 52 char array
Grand total is 32 elements using 100. bytes
» x=NaN;
» int2str(x)
ans =
NaN
» x=Inf ;
» int2str(x)
186
Глава 5
ans =
Inf
» x=realmin
x =
2.2251e-308
»■ int2str(x)
ans =
0
» x=realmax
x =
1.7977e+30.8
» int2str(x)
ans =
1797693134862315700000000000000000000000000000000000000000000000000000000
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
0000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000
» length (ans)
ans =
309
Если в качестве аргумента функции int2str задано комплексное число,
то преобразование выполняется только над вещественной частью
(пример 532).
; Пример 5.32. Преобразование комплексного числа в строку "' .'£''■"* 'Й?.'
! функцией infc2s.tr1 'А\.. >",■- - ,-■,.■■ £_ .- ";> r-.-.s^ ^¾ . й';р. в|
» x=sqrt(-2)+5.8
х =
5.8000 + 1.4142i
» int2str(x)
ans =
6
Обратные преобразования числовых данных из символьного представления
в машинный формат типа double выполняются с помощью функций
str2double и str2num. Первая из них осуществляет преобразование
единственного значения, в символьном представлении которого использованы все
Обработка символьных данных
1В7
допустимые знаки — цифры, точка, плюс или минус, буква е,
предшествующая порядку числа, запятые, разделяющие число тысяч, буквы i или j,
символизирующие мнимую часть комплексного числа (пример 5.33).
■ Пример 5.33. Преобразование строки в число :-.^^i,'f^'Myj-yr^.' -£*■■«■■..№.■;;- .■<
: ,...:.;.?л;.ж:,:;...л„:^:.,.й;;../.^ , ....... : 1..;.; ::..^::¾¾.¾ £ :....■ а«5|ЯЖлц^й?;'«Ллййл- ... '^-.аад
». Sl=str2double('3.14ISS265')
SI =
3.1416
» Sl=str2double('1,000, 000')
SI =
10000CO
» Sl=str2double{'le6'>
SI =
1000000
» Sl=str2double{'1-2j')
SI =
1.0000 - 2.0000i
Функция str2num позволяет преобразовать числовые данные,
представленные элементами символьного массива (пример 5.34).
I. Пример 5.34. Преобразование символьного массива в число'■.'- ""*■■'... :j
» S=['1 2'; ■3 4']
S =
1 2
3 4
» str2num(S)
ans =
1 2
3 4
» whos
Name Size Bytes Class
S 2x3 12 char array
ans 2x2 32 double array
Grand total is 10 elements using 44 bytes
188
Глава 5
В символьной записи чисел не должно быть лишних пробелов, т. к. это
может привести к труднообнаруживаемой ошибке (пример 5.35).
L Пример 5.35. Влияние пробелов на преобразование строки в число i$fei/i&£Sl
» x=str2num('1-2 j')
х =
1.0000 - 2.0000i
» y=str2num('1 -2j'}
У =
1.0000 0 - 2.0000i
» whos
Name Size Bytes Class
x lxl 16 double array (complex)
у 1x2 32 double array (complex)
В первом случае результатом преобразования является единственное
комплексное число, тогда как во втором случае — вектор из двух чисел.
В отдельную группу функций следует выделить процедуры преобразования
числовых данных, символьное представление которых зависит от
используемой системы счисления, — dec2bin, dec2hex, dec2base, bin2dec,
hex2dec, base2dec, hex2num. Шесть первых функций имеют дело с целыми
десятичными числами (dec — от англ. decimal) и их символьным
представлением в двоичной (bin — от англ. binary) и шестнадцатеричной (hex — от
англ. hexadecimal) системах, а также в любой другой системе счисления с
заданным основанием (base) в диапазоне от 2 до 36. Цифра 2 в названии
каждой функции ассоциируется с предлогом "в" (англ. two — "два" и to — "в"
звучат одинаково). Эти функции осуществляют прямое и обратное
преобразования между целыми десятичными числами формата double и
соответствующим символьным представлением этих же чисел в заданной системе
счисления. Функция dec2base очень напоминает функцию itoa из
библиотеки C++. Для тех, кто недоумевает по поводу диапазона основания
системы счисления от 2 до 36, поясним, что для обозначения цифр в системах с
основанием больше 10 используются буквы латинского алфавита. Поэтому
10 цифр и 26 букв латинского алфавита обеспечивают представление чисел в
системе с максимальным основанием 36.
Функция dec2bin[N> преобразует целочисленный положительный аргумент,
не превосходящий 252, в строку с двоичным представлением аргумента
(пример 5.36).
Обработка символьных данных
189
» dec2bin(792) % Перевод в двоичную систему
ans =
1100011000
Второй необязательный аргумент функции dec2bin(N,k> задает количество
двоичных цифр, которое следует сохранить в результате. Его не имеет
смысла указывать меньше, чем фактическое количество разрядов в двоичном
представлении числа:
» dec2bin(792,5) % Перевод в двоичную систему с 5 цифрами
ans =
1100011000
» dec2bin(792,12) % Перевод в двоичную систему с 12 цифрами
ans =
001100011000
Если основной аргумент функции dec2bin представлен числовым массивом,
то результат преобразования будет получен в виде массива строк, длина
которых выровнена по максимальному числу:
» a=[148 1023,-525 792];
» dec2bin(a) % Перевод в двоичную систему числового массива
ans =
0010010100
1000001101
1111111111
1100011000
Аналогичный перевод в строку с шестнадцатеричным представлением
аргумента выполняет функция dec2hex (пример 5.37).
! Пример 5.37. Перевод числа в шестнадцатеричную.систему ^¾¾^1¾¾¾,;><•£''"';
» dec2hex(792) % Перевод в шестнадцатеричную систему
ans =
318
» dec2hex(792,5) % Перевод в шестнадцатеричную систему с 5 цифрами
ans =
00318
» а=[148 1023,-525 792];
» dec2hex(a) % Перевод в шестнадцатеричную систему массива чисел
190
Глава 5
ans =
094
20D
3FF
318
При переводе целого десятичного числа в систему с основанием р значение
р задается вторым аргументом функции dec2base. Необязательный третий
аргумент определяет количество цифр в результате (пример 5.38).
! Пример 5.38j Перевод числа в произвольную систему сч^слейий v ■■< -_гц 4f *; р,^з
» dec2base(792,5) % Перевод в пятеричную систему
ans =
11132
» dec2base(792,5,8) % Перевод в пятеричную систему с 8 цифрами
ans =
00011132
ФуНКЦИИ bin2dec, hex2dec И base2dec Преобразуют строку С СИМВОЛЬНОЙ
записью числа в двоичной, шестиалцатеричнои или произвольной системе
счисления в машинный формат целого числа типа double (пример 5.39).
: Пример 5.39. Преобразование числа в десятичнунр систему 11¾.¾¾¾^¾^)^
» bin2dec('1100011000')
ans =
792
» hex2de.c('3l8')
ans =
792
» base2dec(,11132',5)
ans =
792
Если аргументом этих функций является массив строк, то каждая строка
рассматривается как символьный эквивалент целого положительного числа
в соответствующей системе счисления (пример 5.40).
Обработка символьных данных
191
» bin2dec(['101100';'001101'])
sns =
44
13
» whos
Name Size Bytes Class
ans 2x1 16 double array
Вещественное число в формате типа double занимает 8 байтов оперативной
памяти и может быть компактно записано с помощью 16 шестнадцатеричных
цифр* включающих знак, порядок и мантиссу числа в соответствии со
стандартом IEEE — 1 бит на знак, 11 битов на порядок в дополнительном коде и
52 бита на мантиссу. В такой записи, например, число я на IBM-совместимых
компьютерах выглядит следующим образом — 400921FB54442D18.
Для преобразования такой строки символов в число используется функция
hex2num (пример 5.41).
» format long
» hex2num('40.09211^544420181)
ans- =
3.14159265358979
Если аргумент функции hex2num содержит менее 16 символов, то он
дополняется справа нулями.
Функции mat2str и str2mat занимаются преобразованиями между
символьной записью двумерных числовых матриц и их машинным представлением
(пример 5.42).
{«Пример 5;4Z:^ ;■ "':.;-: *'- ' 4-|;i
» х=(1 2; 3 4]
х =
1 2
3 4
» y=mat2str{x)
192
' Глава 5
У =
tl 2;3 4]
■» z=str2mat('[1 2;3 4]')
г =
[1 2;3 4]
» whos
Name
X
У
z
Size
2x2
1x9
1x9
Bytes
32
18.
18
Class
double array
char array
char array
Grand total is 22 elements using 68 bytes » x=[l 2;3 4]
В целесообразность последней процедуры верится с трудом.
5.7. Форматные преобразования
(sprintf, sscanf)
Идеологию функций преобразования числовых и символьных данных по
заданному формату MATLAB заимствовал из языка С, почти полностью
сохранив набор соответствующих спецификаций. Конечно, определенную
особенность вносит то, что элементом преобразуемых данных может быть
массив. Но тогда действие соответствующего форматного указателя
распространяется на каждый элемент массива.
Преобразование списка данных (ai, а2, ...) по формату fmt с записью
результата в строку s выполняется с помощью функции sprintf:
[s,s_err] = sprintf{fmt,al,a2,...)
Кроме результата преобразования функция sprintf может выработать
сообщение об ошибке во время выполнения операции, которое заносится в
строку s_err. При нормальном завершении операции вместо сообщения об
ошибке выдается пустая строка, которую можно проигнорировать, если
обратиться к функции с единственным выходным параметром:
s = sprintf(fmt,al,a2, ...)
Однако ошибка, обнаруженная при выполнении преобразования, может
привести к получению пустой результирующей строки:
» sprintf С %ld\ pi)
ans =
3.14l593e+000
» sprintf (' %lf ,pi)
Обработка символьных данных
193
ans =
Empty string: l-by-0
Формат %lf, допустимый в С и обеспечивающий вывод вещественных чисел
с удвоенной точностью, в системе MATLAB считается недопустимым и
приводит К сообщению Об ошибке s_err=Invalid format.
Строка формата fmt задает шаблон преобразования, состоящий из
спецификаций, начинающихся с символа %, и набора литеральных символов,
переносимых без всяких изменений из строки формата в результат. Каждая
спецификация, управляющая способом преобразования, может содержать до
5 следующих компонентов:
% [флажки] [ширина] [.точность] [{b, t}]cc
Обязательными среди них являются начальный символ (%) и завершающая
буква (ее).
Флажки задаются как комбинация от одного до трех символов из набора
(-, +,"", #, о).
Символ - устанавливает левый прижим. По умолчанию преобразуемое
значение прижимается к правой границе поля заданной ширины.
Символ + устанавливает режим обязательного вывода знака числа (даже
если преобразуемые числа положительны).
Символ " " (пробел) устанавливает режим вывода знака положительного
числа пробелом (по умолчанию на знак положительного числа специальная
позиция не отводится).
Символ # влияет на вывод восьмеричных, шестнадцатеричных и
вещественных чисел. Перед восьмеричными числами выводится о, перед шестнадцате-
ричнымй числами — префикс Ох или ох. В символьную запись вещественных
чисел, преобразуемых по форматам £, е и Е, обязательно включается
десятичная точка (по умолчанию она опускается, если дробная часть равна 0). В
символьной записи вещественных чисел, преобразуемых по форматам g и G, не
удаляются лидирующие нули и всегда включается десятичная точка.
Символ о при правом прижиме чисел включает режим вывода лидирующих
нулей.
Ниже приведено несколько примеров, демонстрирующих влияние флажков
при выводе целых чисел (пример 5.43).
;.Лрймёр;.5Ш^ррматнйй вывод целых 41106¾¾¾^¾¾¾^ 1$ф-г2фр*Щ^^Ф&\
» sprintf С%-5d %+5d %05d\123,123,123)
ans =
123 +123 00123
» sprintf <'%x: %-№X\123,123)
194
Глава 5
ans =
7b 0X7B
» sprintf{'% d',123)
ans =
123
» sprintf('% d',-123)
ans =
-123
Ширина, задаваемая целым числом, определяет количество позиций
(символов), которое отводится под преобразуемое значение. Точность, также
задаваемая целым числом, определяет количество дробных цифр, сохраняемых в
преобразованном значении:
■» sprintf('%10.6f' ,.pi)
ans =
3.141593
Символ а, завершающий форматную спецификацию, определяет вид
преобразованного значения и должен согласовываться с типом преобразуемого
данного. Возможные варианты этого символа приведены в табл. 5.1.
Таблица 5.1
Спецификатор Формат результата
%с Единственный символ
%d Целое десятичное число со знаком
%е Вещественное число в форме с плавающей запятой (порядок
идентифицирует буква е)
%Е Вещественное число в форме с плавающей запятой (порядок
идентифицирует буква е)
%f Вещественное число в форме с фиксированной запятой
%д Компактная форма числа с фиксированной или плавающей запятой
SG Компактная форма числа с фиксированной или плавающей запятой
%о Целое восьмеричное число без знака
%s Строка символов
%ч Целое десятичное число без знака
%х Целое шестнадцатеричное число с малыми буквами а—f
%х Целое шестнадцатеричное число с большими буквами A—F
Обработка символьных данных
195
Спецификаторы %.d, %u, %о, %х и %х имеет смысл применять к
целочисленным значениям (хотя и представленным в оперативной памяти в формате
double). Если соответствующий элемент списка не является целым числом,
то MATLAB заменяет целочисленную спецификацию на формат
вещественного числа:
» sprintf('%d',pi}
ans =
3.141593е+000
Однако после округления спецификатор %d действует нормально:
» sprintf('%d',round(pi))
ans =
3.
Символ ь или t, предшествующий символу-спецификатору, позволяет
преобразовать в восьмеричный или шестнадцатеричный формат вещественные
числа стандарта [ЕЕЕ. Они используются в сочетании с форматными
указателями %о, %х или %х. Однако результат их применения может удивить в
связи с перестановкой байтов, характерной для IBM-совместимых
компьютеров (пример 5.44).
*7'г»ида^::^™:^т;-:*^^ " -^--.4----¾¾^^.¾
;.Пример 5.44. Форматный вывод с преобразованием,системы счисления i ■ * _ ■
» sprintf('%bx',pi)
ans =
182d4454fb210940 % Здесь переставлены байты
» format long
» hex2num(,400921EB54442D18')
ans =
3.14159265358979
» sprintf('%bx'fl) \
ans =
000000000000f03f
» hex2num('3ff0000000000000')
ans =
1
» sprintf('%tx',l)
ans =
3f800000
196
Глава 5
Все символы, включенные в состав строки fmt и не относящиеся к
форматным спецификациям, являются литералами, которые без изменения
переносятся в результирующую строку:
» sprintf(,nM=%10.8f'/pi)
ans =
пи=3.14159265
Среди литералов могут присутствовать управляющие символы и
специальные знаки, запись которых выполняется в соответствии с правилами языка
С (табл. 5.2).
Таблица 5.2
Символ
\ь
\f
\п
\г
\t
\\
V
%%
Назначение
Удаление предшествующего символа (Backspace)
Перевод страницы (Form feed)
Перевод строки (New line)
Возврат каретки (Carriage return)
Горизонтальная табуляция (Horizontal tab)
Обратная косая черта (Backslash)
Одинарная кавычка (')
Процент(%)
Обратная операция по извлечению данных из строки s, сформированной
функцией sprintf, выполняется с помощью функции sscanf:
A = sscanf(s,fmt)
Этот вариант вызова обеспечивает выборку всех данных и их обратное
преобразование из символьного представления в машинное в соответствии с
форматными указателями строки fmt. Форматные спецификации здесь те же
самые, что и при преобразовании в строку (см. табл. 5.1), хотя некоторые
детали, характерные для вывода данных (прижим, точность, префиксы
и т. п.), в обратном преобразовании не используются.
Среди дополнительных средств управления форматом выделим использование:
П флажка, задаваемого символом *, обеспечивающего пропуск очередного
данного в строке s;
П форматов %hd, %id и %ig, позволяющих преобразовать извлекаемое число
в машинный формат короткого целого (%hd), длинного целого (%id) или
вещественного числа с удвоенной точностью (%lg);.
Обработка символьных данных
197
П формата %[sis2... ], обеспечивающего извлечение только тех символов
из строки s, которые перечислены в квадратных скобках;
П формата %[~sis2... ], обеспечивающего извлечение только тех символов
из строки s, которые не перечислены в квадратных скобках.
Для программистов, работавших на языке С, будет довольно непривычно
увидеть следующее использование единственного форматного указателя
(пример 5.45).
гЛримёр-5:45.''Испол£^ I
-41.-. .г.л^.. .. . ....tl,?j» -. ...Л .'.*..№ ji..-.. «vis.Яti?ni\..;*,?.,f.r'rff.it, bir(AvAV<»i'> ДЯ1 «Vi. /**.»«-й»«тЛ; ;П £vt».'ir ¥frtf*?t,tjf ,t r№№i№t
» s = '2.7183 3.1416';
» A = sscanf(s,*%f')
A =
2.7183
3.1416
Однако ведь и при прямом преобразовании в строку для массива а
требовалась тоже только одна спецификация формата:
» sl=sprintf('%f ',А)
si =
2.718300 3.141600
Обратите внимание на использование литерального пробела в формате. Без
него оба числовых значения оказались бы "склеенными", и для их
разделения потребовались бы определенные усилия (пример 5.46).
ЬПри»4ер,5:46:.О.теутствие-разделмхе^^
» sl=sprintf('%f', А)
si =
2.7183003.141600
>i> s2=sl(l:B)
s2 =
2.718300
» s3=sl(9:end)
s3 =
3.141600
198
Глава 5
Впрочем, склейки можно было бы избежать за счет использования ширины,
точности и прижима:
» sl=sprintf{'%-8.4f' ,А)
si =
2.7183 3.1.416
Функция sscanf допускает и другие варианты вызова, обеспечивающие
извлечение только заданного количества данных или их извлечение в цикле:
A = sscanf(s,fmt,size)
[A,count,s_err,nextindex] = . sscanf(s,fmt}
5.8. Регулярные выражения и поиск
В разд. 5.4 рассматривались процедуры поиска заданного текста. При этом
разрешались две возможности. Кроме абсолютного совпадения искомого
фрагмента с заданным текстом допускалось игнорировать разницу между
большими и малыми буквами. Более широкие возможности для поиска в
текстовом документе предоставляют так называемые регулярные выражения.
В шаблоне, формируемом с помощью регулярных выражений, разрешается
задавать не только те символы, которые должны присутствовать в искомом
фрагменте. Например, если мы собираемся извлечь из текста семизначный
номер телефона, то можно составить шаблон поиска следующим образом:
"три_цифры тире две_цифрьг тире две_цифры". Или мы точно не знаем
фамилию человека — то ли "Корягин", то ли "Калягин". В этом случае может
помочь поисковый шаблон, в котором указано, что фамилия начинается с
буквы "К", после нее следуют две какие-то буквы, а окончание имеет вид
"ягин". Это позволит найти те данные, значения которых мы точно не
знаем. Нечто похожее используют программисты, когда производят поиск
файлов по некоторым шаблонам, задаваемым в фильтрах поиска. Например,
показать все файлы с расширением ерр — шаблон поиска имеет вид *.срр.
Символ * заменяет собой произвольную цепочку символов, расположенную
перед четырьмя указанными.
Шаблон поиска с применением регулярных выражений представляет собой
строку или массив ячеек строк. Наряду с заранее известными символами в
составе шаблона допускается использование следующих управляющих
конструкций:
П точка (.) — для указания позиции любого символа, включая и белый
пробел. Для указания позиции, в которой искомый текст может
содержать точку, Используется пара символов \.;
Обработка символьных данных
199
О Vw — для указания позиции, в которой может находиться буква, цифра
или подчерк, т. е. те символы, которые участвуют в конструировании
слов;
П \w — для указания позиции, в которой может находиться любой символ,
кроме буквы, цифры или символа подчеркивания;
П \s — для указания позиции, в которой может находиться белый пробел;
П \s — для указания позиции, в которой может находиться любой символ
кроме белого пробела;
П \d — для указания позиции, в которой может находиться цифра;
□ \D — для указания позиции, в которой может находиться любой символ,
кроме цифры;
П [sis2.. -skj — для указания позиции, в которой может находиться любой
из символов, перечисленных в квадратных скобках;
О .[nsis2.. .sk] — для указания позиции, в которой может находиться
любой из символов, кроме перечисленных в квадратных скобках.
Когда диапазон символов, указываемых в квадратных скобках, непрерывен,
то можно ограничиться заданием начального и конечного символов:
[abede] = [a-el
Шаблон поиска оформляется в виде строки, в которой указанные выше
управляющие символы могут чередоваться с обычными символами.
Например, шаблон вида ' w*ko\s' означает, что мы собираемся искать слово,
оканчивающееся буквами "ко", вслед за которыми следует пробел. Заданным
буквам может предшествовать любая цепочка символов, включающая буквы,
цифры и символы подчеркивания.
Обозначим через r, ri, R2 элементарные регулярные выражения,
образованные из перечисленных выше конструкций. Их можно объединять в более
сложные шаблоны поиска, выписывая друг за другом, объединяя в круглые
скобки или сопровождая дополнительными указаниями следующего вида:
П (R) * — выражение r может повторяться 0 или более раз;
П (R) + — выражение r может повторяться I или более раз;
П (R) ? — выражение r может повторяться 0 или 1 раз;
О R{n,m} — выражение r должно повторяться от пдо траз;
П R(n} — выражение r должно повторяться ровно п раз;
П R(n, ) — выражение r должно повторяться п или более раз;
П (R11R2) — искомый фрагмент может содержать тексты, удовлетворяющие
либо шаблону ri, либо шаблону кг;
200
Глава 5
D "R - искомый фрагмент должен находиться в начале строки;
П r$ — искомый фрагмент должен находиться в конце строки;
П \<r — искомый фрагмент должен находиться в начале слова;
П r\> — искомый фрагмент должен находиться в конце слова.
Для организации поиска фрагментов текста, удовлетворяющих заданному
шаблону, MATLAB предлагает три функции:
П regexp — поиск всех фрагментов в заданной строке;
П regexpi — поиск всех фрагментов в заданной строке с игнорированием
разницы между большими и малыми буквами;
П regexprep — поиск фрагментов и их замена другим контекстом.
Две первые функции допускают задание от двух до восьми аргументов:
П первый параметр (обязательный) определяет строку, в которой
организуется поиск;
D второй параметр (обязательный) представляет шаблон поиска;
П все последующие параметры необязательные. Они задаются строками
■match', 'start', 'end', "tokens', 'tokenExtents', 'names', которые
определяют перечень возвращаемых результатов поиска.
Если ни один из необязательных параметров в обращении не задан, то
функции поиска возвращают начальные индексы найденных фрагментов:
» regexp('123_abc 45б_78', *\d(3)')
ans =
1 9
Если задан единственный дополнительный параметр 'match', то функция
regexp возвращает текст найденных фрагментов:
» regexp('123_abc 456_78','\d{3)','match')
ans =
423' '456'
Необязательный параметр 'start* позволяет дополнительно получить
индекс символа, с которого начинается найденный фрагмент:
» [m s]=regexp('123_abc 45б_78','\d{3}','match','start')
т. =
423' '456'
■s =
1 9
Обработка символьных данных
201
Перестановка местами необязательных параметров приводит к аналогичной
перестановке возвращаемых результатов:
» [m sl=regexp('123_abc 4S6_78','\d{3)','start','match'}
т =
1 9
s =
423' '456'
Необязательный параметр 'end' включает в состав возвращаемых
результатов индекс последнего символа найденного фрагмента:
» [m indl ind2]=regexp('123_abc 456J78','\d(3}•,'match','start','end')
m =
423' '456'
indl =
1 9
ind2 =
3 11
Приведем пример 5.47.
[Пример 5.47. Поис^ поэлементарны ■ .f " > j
» s ='abCD_ 123#';
» [mat ind]=regexp(s,'Xs','match','start')
mat =
i i
ind =
6
» [mat indj=regexp(s,'\S','match','start')
mat =
'a' 'b' 'C 'D' '_' 4' '2' '3' '#'
ind =
12345769 10
» [mat ind]=regexp(s,'\d','match','start')
mat =
4' '2' '3'
ind =
7 8 9
202
Глава 5
» [mat ind]=regexp(s, '\D', 'match', 'start')
mat =
■a' 'b' 'C 'D' '_' ' ' '#'
ind =
1 2 3 4 5 6 10
» [mat ind]=regexpCs,'\w','match','start')
mat =
■a* 'b' 'C 'D' '_' '1' '2' '3'
ind =
1234 5. 789
» [mat ind] =regexp (s, '\W, 'match', 'start')
mat =
, . ,#.
ind =
6. 10
Тексты, в которых производится поиск, могут содержать и русские буквы
(пример 5.48).
I Пример 5.48. Использование кириллицы в;.регулярных выражениях -1 ■■> * Ч
» str='Li;apb, царевич, король, королевич';
» pat='ap|op'; S R1 или R2
» regexp(str,pat)
ans =
2 8 17 25
» раЫ='ич\>"; i
» regexp(str,patl) % R в конде слова
ans =
12 31
» pat3="4aap' ;
» regexpi(str,pat3) %R в начале строки
ans =
1
» раМ='ич$';
» regexpi(str,pat4) % R в конце строки
Обработка символьных данных
203
апз =
31
» pat2='\<цар';
» regexpi(str,pat2) % R з начале слова
ans =
1 7
Параметр ■ tokens • используется для выделения лексем — цепочек
символов, заключенных между заданными разделителями. Продемонстрируем это
на примере из файла помощи, где лексемой считается цепочка символов,
расположенных между буквами s:
» str = 'six sides of a hexagon';
» pat = 's(\w*}s'; % Шаблон для поиска
» [m s t]=regexp(str,pat,'match','start', 'tokens')
m =
% Найденный фрагмент
% Начальный индекс
% Массив янеек для лексем
% Выделенная лексема
'sides'
s =
5
t =
(lxl
» t(l)
ans =
•ide'
» whos
Name
ans
m
pat
s
str
t
ce
ul}
Size
lxl
lxl
1x7
lxl
1x22
lxl
Bytes
66
70
14
8
44
Class
cell array
cell array
char array
double array
char array
126 cell array
Мы могли бы заменить ограничитель 's' набором знаков арифметических
операций и круглыми скобками для того, чтобы выделить операнды в формуле.
Применение регулярных выражений расширяет возможности стандартных
функций поиска — мы можем осуществить поиск и выделение подстрок
текста, удовлетворяющих довольно сложным запросам. Наряду с этим
имеется возможность произвести нестандартную замену найденного фрагмента
с помощью функции regexprep.
204
Глава 5
В простейшем случае функция использует три обязательных аргумента —
строка, в которой ищется фрагмент, шаблон поиска, которому должен
удовлетворять найденный фрагмент, и текст замены:
» s='H думаю, он думает, мы думаем';
» pat='дума';
» regexprep(s,pat,'по')
ans =
Я пою, он поет, мы поем
По умолчанию процесс поиска фрагмента учитывает разницу между
большими и малыми буквами:
» 5='Я ДУМАЮ, он ДУмает, они думают';
» regexprep{s, pat,'по')
ans =
Я ДУМАЮ, он ДУмает, они поют
С помощью дополнительного параметра 'ignorecase' включается режим
игнорирования этой разницы:
» regexprep(s, pat,'по','ignorecase')
ans =
Я поЮ, он поет, они поют
Дополнительный параметр 'once' указывает, что замене подлежит только
первый найденный фрагмент:
» regexprep (s, pat, * по.', ' ignorecase', ' once')
ans =
Я поЮ, он ДУмает, они думают
Процесс замены может использовать информацию о больших и малых
буквах. При задании необязательного параметра 'preservecase' в заменяемых
фрагментах сохраняются регистры заменяемых символов:
» s='A_b_C_d_123';
» pat='[A-Z]';
» regexprep(s,pat,'qwerty','preservecase')
ans =
QWERTY_qwerty_QWERTY_qwerty_123
Аналогичная операция правильно выполняется и при замене символов
русского алфавита:
» s='Aa_B6_123' ;
» pat='[А-Я]';
Обработка символьных данных
205
» regexprep(s, pat,'эЮя','preservecase')
ans =
ЭЮЯэюя_ЭЮЯэюя_12 3
Однако если шаблон поиска расширить до нескольких букв, то результат
замены выглядит следующим образом:
» s='Aa_B6_123';
» pat='[А-Я]* * ;
» regexprep (s, pat, ' эЮя', ' preservecase ')
ans =
Эюя_Эюя_123
Мы перебрали различные комбинации регистров заменяемых и
замещающих букв, меняли длины старых и новых фрагментов, однако предсказать
результаты замен с использованием параметра 'preservecase' не удалось.
Сулите сами:
» s='AbcD_aBCd';
» pat-'[A-Z]*';
» regexprep(s,pat,'zx1,'preservecase')
ans =
zx_zx
» regexprep(s,pat,'Zx','preservecase')
ans =
Zx_Zx
» regexprep(s, pat, 'zX', 'preservecase *)
ans =
zX_zX
» regexprep(s,pat,'EFgh','preservecase')
ans =
EFgh_EFgh
» regexprep(s,pat,'efgh','preservecase')
ans =
efgh_efgh
» s='ABCD_abcd';
» regexprep(s, pat,'efgh','preservecase')
ans =
EFGH_efgh
» regexprep(s,pat,'EFgh','preservecase')
206
Глава 5
ans =
EFGH_efgh
» regexprep(s, pat,'EFGH', 'preservecase')
ans =
EFGH_efgh
» s='Abcd_aBCD';
» regexprep[s,pat,'EFGH','preservecase')
ans =
Efgh_EFGH
» regexprep(s,pat,'EFgh','preservecase')
ans =
Efgh_J5Fgh
Очень похоже на то, что алгоритм до конца не продуман.
Глава 6
Работа с файлами
Как правило, файлы представляют собой именованные области внешней
(дисковой) памяти, с которыми программы могут обмениваться
информацией. Необходимость в таких обменах возникает в разных ситуациях. Иногда
объем оперативной памяти недостаточен для хранения нужной
информации, и тогда приходится прибегать к услугам внешней памяти, записывая
туда очередную порцию накопленных данных. В другой ситуации
приложение может воспользоваться своими же данными, ранее записанными на
диск или полученными в результате работы других программ. Вообще
говоря, поставщиками или потребителями данных, с которыми наша программа
вступает в контакт, могут быть не только дисковые файлы, но и файлы-
устройства: диеплей, принтер, графопостроитель, сканер, клавиатура,
каналы связи и т. п. Данная глава посвящена работе с дисковыми файлами, хотя
обслуживание файлов-устройств происходит по аналогичной схеме.
Оценивая ключевые аспекты процесса обмена данными, можно сказать, что
работа с файлами в основном ограничивается тремя-четырьмя операциями:
П выделение ресурсов и приведение файла в состояние готовности к
обмену (именно это скрывается за термином открыть фаСш);
П чтение (ввод из файла) или запись (вывод в файл) очередной порции
данных;
П возврат выделенных ресурсов и завершение неоконченных операций
(этому соответствует термин закрыть файл).
К числу наиболее важных моментов, связанных с обменом информацией,
следует отнести формат представления данных на внешнем носителе. В
большинстве своем почти все системы программирования (и MATLAB в этом
смысле — не исключение) используют два формата данных — текстовые и
двоичные.
Текстовые или символьные данные состоят из строк,- похожих на те,
которые мы набираем при вводе с клавиатуры или видим при выводе на экране
дисплея. Для текстовых данных характерна переменная длина строки,
завершающейся невидимым признаком конца (обычно эту функцию выпбл-
208
Глава 6
няют символы типа CR — возврат каретки, LF — перевод строки). Кроме
того, числовые данные в строках представлены в естественном для человека
виде. Это означает, что при вводе символьных данных служебные
программы преобразуют числовую информацию во внутренний формат компьютера,
а при выводе работают другие сервисные программы, которые преобразуют
данные из машинного формата в приемлемый для человека вид.
Из-за переменной длины строк обмен с текстовыми наборами данных
приходится вести последовательно — строка за строкой. Ведь для того чтобы
определить, где в наборе данных находится строка с заданным номером, пришлось
бы перебирать байт за байтом все символы предшествующих строк.
Как правило, объем информации, хранящейся в символьном наборе данных,
заметно превышает длину той же информации в машинном формате.
В основном это относится к данным числового типа. Например, число
71=3.14159265358979 в символьном представлении занимает 16 байтов,
тогда как с таким же количеством значащих цифр его машинный
эквивалент требует 8 байтов.
Таким образом, текстовое представление данных имеет ряд минусов — оно
менее эффективно по объему используемой памяти, требует
дополнительных затрат на преобразование между машинным и символьным форматами,
допускает только последовательный обмен между программой и внешним
носителем. Однако главные преимущества текстовых данных заключаются в
их естественности для восприятия человеком и в независимости их
представления от компьютера и операционной системы. Последнее
обстоятельство очень важно при передаче данных между различными
вычислительными платформами.
Информация, которая хранится в двоичных наборах данных, может иметь
совершенно разную природу. Это могут быть и символьные данные с 8- или
16-разрядной кодировкой символов, и числовые данные в машинном
формате, и графические образы в одном из многочисленных форматов (PCX,
BMP, JPG, TIF и т. д.), и закодированные звуки, и многое другое. В
отличие от текстовой информации, в байтах двоичного набора может встретиться
любая двоичная комбинация, поэтому здесь отсутствует понятие управляющих
кодов, таких как CR, LF, Tab и т. п. Обмен информацией с двоичными
наборами данных не требует каких-либо преобразований. Поэтому он
выполняется быстрее и связан с меньшими объемами памяти. В отличие от
текстовых файлов, обмен данными с двоичными файлами выполняется
порциями заданной длины. Поэтому в зависимости от природы информации,
хранящейся в двоичных файлах, здесь имеется возможность прямого
доступа к нужной порции данных. Таким образом, если файл предназначен для
временного хранения информации, используемой только программой, и его
содержимое не будет переноситься на компьютеры другого типа,
предпочтение следует отдавать двоичным файлам.
Работа с файлами
209
6.1. Подготовка файла к работе
Файлы открывают с помощью функции fopen, которая в случае удачного
завершения возвращает целочисленный положительный идентификатор
файла fid (в дальнейшем мы будем называть его номером файла).
В простейшем варианте вызова указывается единственный входной
аргумент — имя открываемого файла:
f_id = fopen(,name_file');
В качестве имени открываемого файла может быть задано короткое имя, и
тогда система пытается отыскать его сначала в рабочем каталоге, а затем
производит поиск по всем каталогам, доступным пакету MATLAB. Если вы
задаете полную спецификацию, то поиск осуществляется только в указанном
каталоге. В случае неудачи возвращаемое значение равно -п.. Для получения
дополнительной информации, поясняющей причину ошибки при открытии
файла, к функции fopen можно обратиться с двумя выходными параметрами:
[f_id err_txtI = fopen('name_file');
В случае ошибки в переменную err_txt будет занесено соответствующее
сообщение. Если указанный файл обнаружен, то он открывается для чтения
как двоичный файл.
Второй необязательный входной аргумент функции fopen определяет режим
доступа к открываемому файлу. В качестве этого параметра могут выступать
один, два или три символа, заключенные в одинарные кавычки. Их
назначения описаны в табл. 6.1.
Таблица 6.1
Формат вызова Выполняемое действие
fopen (' name_f ile *, ' г') Открывается существующий двоичный файл для
чтения
fopen (' name_f ile * r ' rt') Открывается существующий текстовый файл для
чтения
fopen (' name_f ile', ' r+') Открывается существующий двоичный файл,
который можно использовать как для чтения, так и для
записи (новый файл при этом не создается)
fopen (' name_file', ' rt+') Открывается существующий текстовый файл,
который можно использовать как для чтения, так и
для записи (новый файл при этом не создается)
fopen ('name_f ile', ' w ) Открывается существующий или создается новый
двоичный файл для записи. Предыдущее
содержимое существующего файла пропадает
210
Глава 6
Таблица 6.1 (окончание)
Формат вызова
Выполняемое действие
f-open (' name file ', ' wt'
fopen ('name_file', 'w+'
fopen ('name_file', 'wt+'>
fopen ('name_file', 'a')
fopen('name_file' , 'at' )
fopen ('name_fiie', ' a+')
fopen{'name file',,at+'}
Открывается существующий или создается новый
текстовый файл для записи. Предыдущее
содержимое существующего файла пропадает
Если существующий двоичный файл был ранее
открыт, то его содержимое от текущей позиции
указателя и до конца усекается. Если файл с
таким именем не существовал, то создается новый
файл. Открытый файл можно использовать для
записи и чтения
Если существующий текстовый файл был ранее
открыт, то его содержимое от текущей позиции
указателя и до конца усекается. Если файл с
таким именем не существовал, то создается новый
файл. Открытый файл можно использовать для
записи и чтения
Открывается существующий двоичный файл для
дозаписи или создается новый файл
Открывается существующий текстовый файл для
дозаписи или создается новый файл
Открывается существующий двоичный файл для
чтения и дозаписи. Если файла с указанным
именем нет, то его создают
Открывается существующий текстовый файл для
чтения и дозаписи. Если файла с указанным
именем нет, то его создают
Иногда при открытии двоичных файлов по аналогии с C++ к символам
режима добавляют букву ь (от англ. binary — двоичный): гь, wb и т. д.
Операции обмена как с текстовыми, так и с двоичными файлами
используют указатель на начало текущей порции данных. Если файл открывают для
чтения или записи, этот указатель "смотрит" на первую строку или на
первый байт в соответствующем наборе данных. Если файл открывают для
дозаписи, то указатель перемешается в конец данных, что позволяет
присоединять новые данные в хвост к уже существующей информации. Термин
усечение (trimcaie) обычно используют для операции удаления хвостовых
данных, начиная от текущей позиции указателя.
Поясним смысл еще одной операции, связанной с выводом в файл. В связи
с тем, что скорость работы периферийных устройств, на которых
располагаются внешние данные, много ниже быстродействия процессора, операции
обмена используют специальные буферы, выделяемые системой. В этих бу-
Работа с файлами
211
ферах накапливается выводимая информация, которая после заполнения
буфера переписывается на внешнее устройство. Когда файл закрывают,
накопленная в буфере информация автоматически выталкивается в файл,
чтобы не произошло потери последних данных. Это действие в англоязычной
документации связывают с термином flash, flashing. Процедура открытия
файлов для записи или дозаписи предоставляет программисту возможность
отказаться от автоматического опустошения буферов обмена — для этой
цели вместо малых букв а и w в режиме доступа следует применять их большие
эквиваленты — а и w. Такие режимы на IBM-совместимых компьютерах не
используются.
Существуют три системных файла — стандартный ввод (stdin),
стандартный вывод (stdout) и файл, предназначенный для вывода сообщений об
ошибках (stderr). За этими файлами в MATLAB закреплены
фиксированные номера — 0, 1 и 2 соответственно. Указанные файлы открывать не надо,
они доступны всегда. В демонстрационных примерах, приводимых в данной
главе, мы часто будем использовать стандартный вывод для того, чтобы
наглядно представить данные, которые могли бы попасть в соответствующий
файл на диске.
Обращаясь к функции fopen с числовым аргументом, представляющим
номер открытого файла, мы можем получить информацию о статусе этого
файла (пример 6.1).
; Пример 6.1; Получение информации о статусе файла.^-¾½¾ ;Ss;^i? , .ч, \
» [паше access]=fopen{0)
name =
"stdin"
access =
x
» [name access]=fopen(1)
name =
"stdout"
access =
a
» [name access]=fopen(2)
name =
"stderr"
access =
a
» k=fopen ('qq','wt+')
212
Глава 6
к =
3
>> [name access]=fopen(к)
name =
qq
access =
wt+
Функция f open допускает еще один формат вызова:
v = fopen('all')
В этом случае она возвращает вектор с номерами всех файлов, открытых к
данному моменту времени (файлы с номерами 0, 1 и 2 в этот список не
включаются).
6.2. Завершение работы с файлами
Файл, работа с которым завершена, должен быть закрыт. Эта операция,
выполняемая с помощью функции fclose, преследует две цели. Во-первых,
необходимо вытолкнуть в файл вывода ту часть информации, которая
накопилась в буфере обмена. Во-вторых, нужно освободить ресурсы, выделенные
системой для работы с файлом. Функция fclose допускает два формата
вызова:
s = fclose(f_id)
a = fclose{■all')
В первом случае закрывается файл с указанным номером, во втором случае
закрываются все открытые к этому моменту файлы. Если возвращаемое
функцией значение равно -1, то операция по закрытию завершилась
неудачно. Причиной тому может быть задание номера файла, который в
данный момент не находится в открытом состоянии. При нормальном
закрытии файла функция fclose возвращает нулевое значение.
6.3. Контроль за исчерпанием данных
При выборке информации из текстового или двоичного файла, открытого
для чтения, может наступить момент, когда прочитана последняя порция
данных и в файле больше ничего нет. Контроль за тем, достиг ли указатель
файла конца данных (end-of-Ji/e), обеспечивает функция f eof:
k = feof(f id);
Работа с файлами
213
Если возвращаемое функцией значение равно о, то в файле еще находятся
непрочитанные данные. При исчерпании данных значение, возвращаемое
функцией feof, равно i.
6.4. Работа с двоичными файлами
Указатель файла "смотрит" на текущую порцию данных. При чтении эта
информация извлекается из файла, а указатель автоматически перемешается
на следующую доступную порцию, если таковая еще есть. При выводе в
файл новая информация записывается, начиная с адреса, на который
"смотрит" указатель, а по завершению обмена указатель автоматически
устанавливается на позицию, следующую за выведенной порцией. В двоичных
файлах возможно дополнительное перемещение указателя по предписанию
программы.
Текущая позиция указателя определяется как смещение в байтах
относительно начала файла. Для открытого файла с номером f_id текущее
положение указателя можно узнать, обратившись к функции fteil:
pos = ftell(f_id);
Возврат указателя в начало файла обеспечивает функция frewind. Своим
названием она обязана оператору rewind, который появился почти
полстолетия назад и использовался в Fortran для перемотки магнитной ленты в
начало. Единственным входным аргументом этой функции является номер
открытого файла — frewind (£_id).
Все остальные перемещения указателя файла реализуются с помощью
функции fseek, близкий аналог которой имеется в C++. Перемещения
указателя задаются относительно одной из трех позиций:
□ от начала файла на заданное число байтов вперед (п>0)
st = fseek(f_id,n,'bof);
ИЛИ
st = fseek (f_id, n,-1) ;
П от конца файла на заданное число байтов назад (п>о)
st = fseek{f_id, n, 'eof');
ИЛИ
st = fseek(f_id,n,1);
□ от текущей позиции указателя вперед (п>0) или назад (п<о) на заданное
число байтов
st = fseek(f id,n,'cpf');
214
Глава 6
или
st = fseek(f_id,n, 0) ,-
Величина смещения п может быть, в частности, равна о. Например,
действие fseek(f_id, 0, 'bof') эквивалентно оператору frewind(f_id>.
Нулевое значение, возвращаемое функцией fseek, свидетельствует о
нормальном завершении операции. В случае ошибки возвращаемое значение
равно -1.
6.4.1. Чтение данных из двоичного файла
Для выборки данных из двоичного файла предназначена функция fread,
допускающая несколько форматов вызова. В простейшем случае, когда ее
единственным входным аргументом является номер открытого файла,
функция возвращает содержимое этого файла и количество считанных байтов:
[array count] = fread(f_id);
При этом содержимое файла рассматривается как вектор-столбец,
элементами которого являются однобайтовые числа без знака. Однако в массив
array эти числа поступают уже преобразованными в формат double.
Проведем несложный эксперимент. С помощью редактора m-файлов
сформируем две следующие строки:
ABCD
012345
Сохраним их под именем tcst.m и обратим внимание на длину
получившегося файла. Несмотря на то, что мы набирали 10 символов, в файле их
оказалось 12, т. к. в конце первой строки редактор вставил два управляющих
символа с кодами 13 (символ CR) и 10 (символ LF). По существу, файл
test.m является текстовым, но мы попробуем открыть его как двоичный
файл и прочитаем его содержимое (пример 6.2). Комментарии в строках с
прочитанными значениями вставлены вручную.
i Пример 6.2. Чтение из текстового файла как двоичного '
». J7_id^fopen('test.m','г'); % открываем файл как двоичный для чтения
» [a k]=fread(f_id) % читаем весь файл в массив а
а = % каждый элемент массива а - число типа
double
65 % код буквы А
66 % код буквы Б
67 % код буквы С
Работа с файлами
215
68 % код буквы D
13 % код символа 'Возврат каретки'
10 % код символа 'Перевод строки'
.48 % код цифры 0
39 .% код цифры 1
50 % код цифры 2
51 % код цифры 3
52 % код цифры 4
53 % код цифры 5.
12 % количество считанных байтов
» a=char(a) % преобразование данных типа double в тип char
а = % теперь каждый элемент массива а — типа char
А % буква А
В % буква" В
С % буква С
D % буква D
% неотображаемый символ 'Возврат каретки'
5 неотображаемый символ 'Перевод строки'
% действие управляющего символа 'Перевод строки'
% цифра 0
% цифра 1
% цифра 2
% цифра 3
% цифра 4
% цифра 5
% транспонирование вектора-столбца
% вывод вектора^-строки
0
1
2
3
4
5
» а'
ans =
ABCD
012315
Второй формат вызова функции f read использует второй входной аргумент,
который задает количество считываемых символов:
[array count] = fread(f_id, г.);
Возвратим указатель файла test.m в начало и попробуем прочитать 8 байтов
(пример 6.3).
к зик кчч
216
Глава 6
К'Прймер 6.3. '^щшёз$р0Н№
» frewind(f_id)
» [a k]=fread(f_id,8)
a = % элементы массива а имеют тип double
.65
66
.67
68
13
10
48
49
к =
Количество фактически прочитанных элементов данных может не совпадать
с заказанным. Обычно это случается при выборке последней порции,
которая может оказаться короче предыдущих, если длина файла не кратна
длинам запрашиваемых порций.
Третий необязательный входной параметр в функции fread задает длину
считываемых из файла компонентов вектора и их тип. Перечень допустимых
значений этого параметра приведен в табл. 6.2. По умолчанию действует
описатель uchar, обеспечивающий побайтный доступ к содержимому файла.
Описатели другого типа рассматривают содержимое последовательно
идущих двух, четырех или восьми байтов как очередной элемент вектора-
столбца. В этом случае второй аргумент функции fread задает количество
элементов, извлекаемых из файла. Но каждый раз очередной элемент,
считанный из файла данных, преобразуется в число типа double.
Таблица 6.2
Описатель длины и типа элементов
Пояснение
•uchar'
'schar'
•intl6'
'int32'
•int64'
■uintl6'
'uint8'
'int8'
1integer*2'
' integerM '
'integer^8 '
Целое число без знака, 1 байт
Целое число со знаком, 1 байт
Целое число со знаком, 2 байта
Целое число со знаком, 4 байта
Целое число со знаком, 8 байтов
Целое число без знака, 2 байта
Работа с файлами
217
Таблица 6.2 (окончание)
Описатель длины и типа элементов Пояснение
' uint32' Целое число без знака, 4 байта
' uint 6 4 * Целое число без знака, 8 байтов
'single' | 'float32' Вещественное число, 4 байта
' double' | ' float 64' Вещественное число, 8 байтов
Вообще говоря, MATLAB позволяет рассматривать содержимое файла как
целочисленные данные с точностью до бита, если воспользоваться одним из
описателей вида:
П bitN — целое со знаком, длина ы битов (I < N < 64);
D ubitN — целое без знака, длина N битов (1 < n < 64).
Функция fread допускает наличие четвертого входного параметра, который
позволяет читать данные из файла не подряд, а с заданными пропусками.
Продемонстрируем эту возможность на примере того же файла test.m
(пример 6.4).
■ Пример 6.4. Чтение из файла с пропусками ,'■>' -й-.,- \ ^v. ■„>£' .;■'',.¾ '-'г.^ЩШ
» frewind(f_id)
» [a k]=fread(f_id,20,'uchar',3)
a =
65
13
.50
k =
3
Пусть вас не смущает, что мы заказали чтение 20 байтов. В файле их всего
12, и больше, чем там находится, все равно никто не прочитает. Мы по-
прежнему рассматриваем содержимое файла как вектор из однобайтовых
целых чисел без знака. Но после того как прочитан очередной байт, в файле
пропускаются три следующих байта. Распечатка содержимого вектора а
отчетливо демонстрирует режим чтения с пропусками.
Режим чтения с пропусками допускает еще один вариант выборки данных из
файла — сначала читается порция из п элементов, затем пропускаются m
элементов, и далее все повторяется в таком же порядке. Например, чтение
порциями из трех элементов с пропуском двух следующих может выглядеть так:
» [a k]=fread(f id,inf,'3*uchar',2)
218
Глава 6
Так как в нашем файле содержится 12 байтов, то в массив а будет считано
6 байтов — две полные порции по 3 байта, а два последние байта не будут
прочитаны (пример 6.5).
» f_id=fopen( 'test.m', 'г') ,-
» [a k]=fread{f_id,inf,'3*uchar', 2)
a =
65 % первое число
66 % второе число
67 % третье число
% два байта пропущены
10 % первое число
48 % второе число
49 % третье число
% два байта пропущены
52 % первое число
53 % второе число
m =
8
Массив, в который считываете*! очередной фрагмент или полное
содержимое файла, не обязательно должен быть представлен одномерным вектором.
Используя указание о количестве считываемых элементов из файла в виде
вектора, можно сформировать результат выборки как двумерный массив
(пример 6.6).
Ii Пример 6.6. Чтение из файла в двумерный масёив^'гЙ'7 ч -^-^.-^¾¾¾
» f_id=fopen{'test, m', 'г');
» a=fread(f_id,[3 4]) % читаем данные из файла в двумерный массив
а =
65 6.8 48 51
66 13 49 52
67 10 50 53
» whos
Name Size Bytes Class
a 3x4 96 double array
f id 1x1 8 double array
из первой порции
из первой порции
из первой порции
из второй порции
из второй порции
из второй порции
из третьей порции
из третьей порции
Работа с файлами
219
Из приведенного примера видно, что последовательно считываемые из
файла элементы данных заполняют столбцы результирующей матрицы.
Если количество считываемых элементов в обращении к f read явно не
указано, то данные читаются до конца файла. Точно такого же эффекта можно
добиться, указав в качестве размера порции бесконечную дайну inf (или
inf) — пример 6.7.
I Пример6.7.Ятени"ес^ --^^-^1¾^¾¾¾^^''■'■' ^¾¾¾¾¾
» f_id=fopen('test.m', 'г') ;
» a=fread(f_id,inf)
a =
65
66
67
68
13
10
48
49
50
51
52
53
Такой же константой можно воспользоваться и при задании числа столбцов
для матрицы-результата (пример 6.8).
Шример б.а. Чтение 'файла целиком в двумерный массив V. ^^'S-*^^ |||Щ!у
» 1: rewind (f_id)
>> a=fread{f_id, [3,Inf])
a =
65 68 48 51 '
66 13 49 52
67 10 50 53
До сих пор рассматривались режимы чтения файловых данных, которые
могли интерпретироваться как целые или вещественные числа различной
длины. Но в принимающий массив, расположенный в оперативной памяти,
220
Глава 6
они поступали уже в формате double, т. е. в большинстве случаев числовые
данные подвергались преобразованию. На Это тратилось дополнительное
машинное время, неэкономно использовалась оперативная память и
сводились на нет заявленные выше преимущества двоичных файлов. Однако
функция fread позволяет производить чтение двоичных файлов
"один-води н" без какого-либо преобразования форматов или с преобразованием в
числовой формат, отличный от double. Для этого в параметре,
определяющем тип считываемых элементов, задается конструкция "
тип1=>тип2
Левая половина этой конструкции трактуется как тип данных, находящихся
в файле, а правая — как тип элементов принимающего массива
(пример 6.9).
Гт ■;■■- 7"T'™-?;wv3r>3v^^^^ -!Ш
;: Пример 6.9. Преобразование, формат^^ ■'fSrJ.^i:,, ■.. щ
i
» frewind(f_id);
» a=fread(f_id,[3 4],'uchar=>uchar'j
a =
65 68 48 51
66 13 49 52
67 10 50 53
» whos
Name Size Bytes Class
a 3x4 12 uintS array
f__id 1x1 8 double array
Когда тип считываемых данных совпадает с типом принимающих данных,
то вместо конструкции тип1=>тип1 можно указывать более короткую строку
*тип1. В приведенном выше примере можно было бы заменить
uchar=>uchar на *uchar.
6.4.2. Запись в двоичный файл
Операция записи в двоичный файл отличается только направлением
перемещаемых данных и использует похожие аргументы с той лишь разницей,
что массив — поставщик информации — теперь является входным
параметром функции fwrite:
count = fwrite(f_id,array,'type■);
При этом в заранее открытый файл с номером fid записываются все
элементы массива array с преобразованием данных в тип, определяемый
Работа с файлами
221
третьим аргументом. В качестве f_id можно использовать номера
системных файлов stddut и stderr. Целочисленное значение, возвращаемое
функцией fwrite, определяет количество удачно записанных элементов
массива. Если значение count меньше, чем количество элементов в массиве
array, то причиной тому может быть нехватка места на диске.
Если массив array — двумерный, то запись его элементов в файл
производится по столбцам.
Проделаем несложный эксперимент (комментарий для отображаемых
данных вписан вручную) — пример 6.10.
■ПрйМёр'6,10: Запись в двййчнЙЙ $айп.$^$^ *"**£Л^^€^ :?^&
» al='ABCD'; % строка из четырех символов
» а2='012345'; % строка из шести символов
» k=fopen('abc.m','w'); % открыли двоичный файл для вывода
» cl=fwrite(k,al,'uchar') % вывели в файл строку al
cl =
4 $ количество записанных элементов
» c2=fwrite(k,a2,'uchar') % вывели в файл строку а2
с2 =
6 % количество записанных элементов
» fclose(k); % закрыли выводной файл
» k=fopen('abc.m','г'); % переоткрыли файл для звода
» [аЗ c3]=fread(k,inf,'*uchar') % прочитали все данные
аЗ =
65 % код буквы А
66 % код буквы В
67 % код буквы С
68 % код буквы D
48 % код цифры 0
49 % код цифры 1
50 % код цифры 2
51 % код цифры 3
52 % код цифры 4
53 % код цифры 5
сЗ =
10 % количество считанных элементов
» whbs
222
Глава 6
Name
al
a2
a3
cl
c2
c3
к
Size
1x4
1x6
10x1
lxl
lxl
lxl
lxl
Bytes
8
12
10
8
8
8
В
Class
char array
char array
uint8 array
double array
double array
double .array
double array
Обратите внимание на то, что при записи в двоичный файл никаких
дополнительных управляющих кодов типа CR, LF не пишется. Мы можем
прочитать данные в их первозданном формате, если указать соответствие типов
(пример 6.11).
[■ Пример fcitj^HMg^ lZ$±u-&..;Atd&'^ll\--<- WU
» frewind(k)
» a4=fread.(k, inf, "uchar=>char') ' % чтение и транспонирование
.a4 =
ABCD012345
Конечно, операция по преобразованию данных из однобайтового числового
представления в однобайтовый символьный формат ни с какими затратами
машинного времени не связана. Но мы могли бы и при записи в файл не
изменять тип передаваемых данных (пример 6.12).
: Пример 6.12. Запись и чтение в двоичный файл в одинаковом 'форматё'Щййк^?^!
» k=fopen ('abc.m','w');
» cl=fwrite{k,al,'char');
» c2=fwrite(k,a2,'char') ;
» fclose(k);
» k=fopen('abc.m','r');
>> a4=fread(k,inf,'*char')'
a4 =
ABCD012345
Четвертый входной аргумент функции fwrite позволяет записывать
элементы указанного массива не подряд, а со вставкой перед каждым элементом
заданного количества нулевых данных (пример 6.13).
Работа с файлами
223
■» al='ABCD';
» k=fopen('abc.m','w');
» cl=fwrite(k,al,'uchar',2) % запись с разрядкой
cl =
4 % количество переданных элементов массива
» fclose(к);
» k=fорел('abc.т','г');
» a4=fread{к,inf,'uchar')
а4 =
О % первый элемент разрядки
О % второй элемент разрядки
65 % первый элемент массива al
О
О
66 % второй элемент массива al
О
О
67 % третий элемент массива ,al
О
О
68 % четвертый элемент массива al
6.5. Работа с текстовыми файлами
Содержимым текстового файла являются строки — цепочки символов,
завершающиеся парой управляющих кодов CR (шестнадцатеричный код od) и
LF (шестнадцатеричный код or). Такие разделители строк вписывает любой
текстовый редактор, когда мы завершаем набор строки нажатием клавиши
<Enler>. Признак конца строки может вписать и наша программа, если
формат записываемой строки (см. функцию fprintf) заканчивается
управляющим кодом '\п. Для демонстрации процедур чтения строк и символов
создадим с помощью текстового редактора файл text.txt, содержащий две
строки:
ABCD
012345
Убедитесь в том, что длина файла 12 байтов и после кода буквы "С"
(шестнадцатеричный код 43) расположена пара байтов odoa.
224
Глава 6
6.5.1. Последовательное чтение строк
из текстового файла
Чтение очередной строки из текстового файла осуществляется с помощью
функции fgetl. При этом информация из файла читается от текущей
позиции указателя до тех пор, пока не встретится признак конца строки или не
будут исчерпаны данные. Функция имеет единственный входной аргумент —
номер открытого текстового файла — и возвращает прочитанную строку.
Если данные в файле исчерпаны, а мы обращаемся к функции fgetl, то она
возвращает -1 (пример 6.14).
^Пример 6.14, Последователь^ ■- .,- " . .;&ЩР/-- :i
» k=fopen ('text.txt','rt'); % открываем текстовый файл
» sl=fgetl(k) % читаем первую строку
si =
ABCD
» s2=fgetl{k) % читаем вторую строку
s2 =
012345
» s3=fgetl(k) % читаем несуществующие данные
S3 =
-1
Управляющие байты в состав считываемых строк не включаются.
6.5.2. Последовательное чтение
нескольких символов из файла
Один или несколько символов из текстового файла читаются с помощью
функции fgets, у которой могут быть один или два входных аргумента —
номер открытого текстового файла и количество считываемых символов.
Чтение данных из файла начинается с текущей позиции указателя и
продолжается до тех пор, пока не выполнится одно из условий:
□ прочитано указанное количество символов;
□ встретился признак конца строки;
П данные в файле исчерпаны.
Если второй аргумент не указан, то его можно считать равным
бесконечности, и тогда операция будет прервана либо по исчерпанию текущей строки,
Работа с файлами
225
либо по достижению конца файла. При попытке прочитать данные после их
исчерпания функция fgets возвращает -1. Приводимый пример 6.15
демонстрирует все возможные варианты.
[Пример; 6i'i5vn.6ci(iMB;!tWHoe:4^
» k=fopen ('text.txt','rt'); % открываем текстовый файл
» sl=fgets(k) % читаем первую строку
si =
■AECD
» s2=fgets{k,3) % читаем три- следующих символа
s2 =
012 ~
» s3=fgets(к,5) % читаем пять следующих символов,
s3 = % а в файле их осталось всего три
345
» s4=fgets(к,1) % чтение после исчерпания данных
s4 =
-1
6.5.3. Форматирование выводимой строки
Даже в том случае, когда строка, записываемая в файл, представляет собой
цепочку символов, она обязана подвергнуться преобразованию
(форматированию) по двум следующим причинам:
П в оперативной памяти каждый символ представлен двумя байтами, а в
файле — одним;
□ для того чтобы отделить одну строку от другой, вслед за последним
символом на диск должна быть записана пара управляющих кодов.
На самом деле символьная информация обычно перемежается с числовыми
данными, которые должны быть тем или иным способом преобразованы из
машинного формата в соответствующие поля строки. Таким
конвертированием данных из их внутреннего представления в символьное заведуют
форматные указатели, задаваемые в качестве одного из параметров функции
fprintf (пример 6.16).
|Л ример6. J6. Форматная запись в текстовыйфайл■■'■ '-П?~^г: -t--- .•■£.<*:■• -^1-^
» f_id=fopen('text.txt','wt'); % открыли текстовый файл
» cl=fprintf(f_id,'%s\n','ABCD') % вывели в файл строку
226
Глава 6
cl =
5
» fclose(f_id);
Форматные указатели всегда начинаются с символа %. В приведенном выше
примере такой указатель один — %s, и он означает, что перед записью на
диск необходимо преобразовать строку abcd, занимающую в оперативной
памяти 8 байтов. Управляющая комбинация \п\ следующая за форматным
указателем, записывается в файл как признак конца строки. Может вызвать
некоторое недоумение значение, возвращаемое функцией fprintf (рис. 6.1).
Рис. 6.1. Просмотр содержимого файла text.txt
С одной стороны, информативных байтов записано четыре. К ним
добавляется признак конца строки. Несмотря на то, что он на диске представлен
двумя байтами (0D и ор.), функция fprintf рассматривает их как один
управляющий элемент данных (в англоязычной документации ему
соответствует символ newiine — новая строка).
Первый входной аргумент функции fprintf задает номер открытого файла.
Им, в частности, может быть число 1, и тогда данные передаются в файл
стандартного вывода, т. е. в командное окно:
» fprintf(1,'%s\n','ABCD');
ABCD
To же самое происходит и при отсутствии первого аргумента:
» fprintfС%s\n','ABCD');
ABCD
Второй входной аргумент функции fprintf представлен строкой,
содержащей форматные указатели и так называемые литеральные константы. К
последним относятся все символы, не принадлежащие к форматным
указателям. Литеральные константы включаются в выводимую строку без каких-
либо преобразований. В частности, к литеральным константам в
приводившемся выше примере относится признак конца строки. Количество
указателей в строке форматов может не соответствовать количеству преобразуемых
данных. И этим MATLAB кардинально отличается от других систем про-
Работа с файлами
227
граммирования. Если длина списка форматных указателей меньше, чем
количество преобразуемых данных, то список циклически повторяется:
» fprintfC%4d\l,2,3,4)
12 3 4
В приведенном выше примере форматный указатель %.4d повторился четыре
раза. Если количество указателей, формата превышает длину выводимого
списка, то лишние форматные указатели игнорируются:
» fprintf('%d %f %e\l,2)
I 2.000000
Данные, подлежащие преобразованию перед записью в файл, задаются
третьим и последующими входными аргументами функции
fprintf."Например, если мы хотим записать в очередную строку текстового файла два
целых и одно вещественное значения переменных ii, i2: и гз, то это может
выглядеть так, как представлено в примере 6.17.
; Пример 6f17. Преобразование данных при форматной записи -
» il=125;
» i2=2003;
» r3=2.3456;
» fprintf('%5d %d %8.3f\n',il,i2,r3>;
125 2003 2.346
Значение переменной il преобразуется в формат целого числа (об этом
свидетельствует буква d в первом форматном указателе), и для его записи в
выводной строке отводится 5 позиций. Между первым и вторым форматными
указателями находится один пробел, который считается литеральной
константой, разделяющей первое и второе число. Значение переменной ±2
преобразуется по формату %d и занимает в выводной строке 4 позиции. После
второго числа вставляется еще один литеральный пробел, расположенный
между вторым и третьим указателями формата. Следующие 8 позиций
отведены для результата преобразования вещественного числа (об этом
свидетельствует буква f в третьем форматном указателе), у которого сохраняются
3 значащие цифры в дробной части. Обратите внимание на то, что результат
форматного преобразования третьего числа округлен в соответствии с
общепринятыми правилами.
Форматные указатели, используемые в функции fprintf, MATLAB
позаимствовал у языка C++ и слегка модифицировал их. Одна из наиболее
существенных модификаций, на наш взгляд, заключается в том, что элементом вы-
228
Глава 6
водного списка может быть матрица. И тогда список форматных указателей
определяет преобразование каждого элемента очередного столбца матрицы.
Указатель формата начинается с символа %, вслед за которым могут быть
расположены три необязательные компонента — флажки, ширина (w) и
точность (.п). Завершается указатель одним из символов, характеризующих
тип преобразования данных и приведенных в табл. 6.3.
Таблица 6.3
Символ Способ преобразования перед записью в текстовый файл
формата
d Преобразование целочисленного значения в десятичное число
со знаком
i Преобразование целочисленного значения в десятичное число
со знаком
о Преобразование целочисленного значения в восьмеричное число
без знака
и Преобразование целочисленного значения в десятичное число
без знака
* Преобразование целочисленного значения в шестнадцатеричное
число без знака с использованием малых букв а, Ь, с,..., f
в качестве цифр
х Преобразование целочисленного значения в шестнадцатеричное
число без знака с использованием больших букв А, в, с,..., F в
качестве цифр
f Преобразование числового значения в вещественное число
с фиксированной запятой
е Преобразование числового значения в вещественное число
с плавающей запятой, признак порядка — буква е
Е Преобразование числового значения в вещественное число
с плавающей запятой, признак порядка — буква е
g Преобразование числового значения в вещественное число с
фиксированной или плавающей запятой в зависимости от того, какой
формат числа занимает меньше места (незначащие нули в дробной
части не выводятся)
G Преобразование числового значения в вещественное число с
фиксированной или плавающей запятой в зависимости от того, какой
формат числа занимает меньше места (незначащие нули в дробной
части не выводятся)
s Преобразование текстового значения в строку символов
с Преобразование единственного символа
Работа с файлами
229
В качестве флажков, следующих непосредственно после символа %, могут
использоваться следующие символы:
□ для вывода очередного символьного или числового значения,
начиная с левой границы текущего поля (левый прижим). По умолчанию
выводимое значение прижимается к правой границе текущего поля;
□ + — для обязательного включения знака числа (обычно этот знак у
положительных чисел опускается);
П пробел — для вывода пробела вместо знака положительного числа
(обычно такой пробел игнорируется);
□ # — для формирования префиксов у восьмеричных и шестнадцатеричных
чисел (восьмеричное число начинается с о, шестнадцатеричное — с пары
символов Ох или ох).
Ширина w, задаваемая целым числом, определяет количество позиций в
текущем поле строки, в которых должна разместиться преобразуемая
величина. Вообще говоря, ширине может предшествовать о, и тогда старшие
незначащие позиции чисел заполняются не пробелами, а нулями.
Продемонстрируем в примере 6.18 результат влияния флажков при заданной
ширине первого и единственного поля выводимой строки (комментарии в
выводимых строках проставлены вручную).
» а=16;
» Ь=-16;
» fprintfC%5d\n%5d',a,b)
16 % число прижато к правой границе поля
-16 % число прижато к правой границе поля
» f print f C%+5d\n%5d',a,b)
+16 % знак + у положительного числа
-16
» fprintf(,%-5d\n%-5d',a/b>
16 % число прижато к левой границе поля, знак + не выводится
-16 % число прижато к левой границе поля
» fprintf('%- 5d\n%-5d",a,b)
16 % прижим к левой границе, пробел вместо знака +■
-16 % прижим к левой границе
» fprintf (ЧЬхХпЗй.Бх'^а) ;
10
0x10 %■ префикс Ох у шестнадцатеричного числа
230
Глава 6
» fprintf (' %5X\n%#5X', a., a) ;
10
0X10 % префикс OX у шестнаццатеричного числа
» fprintf{'%5o\n%#5o',a,a);
20
020 % префикс — цифра 0 у восьмеричного числа
:» fprintf('%05d',a)
.00016 % дополнение числа незначащими нулями
Обратите внимание на то, что использование целочисленных форматов (%d,
%i, %u, %х, %х, %о) предполагает, что преобразуемое значение действительно
является целым (пример 6.19).
( Замечание ^
Приведенный выше текст в точности соответствует содержимому Command
Window (Окно команд) среды MATLAB 6.5. Однако в среде MATLAB 7 после
вывода данных по функции fprintf символы новой команды (») не
переводятся в начало следующей строки. На результат вычислений и на
продолжение работы это влияния не оказывает, но должного порядка на экране не
наблюдается.
f Пример 6.19^ИспЬльзование различных форматов веществённь1х чисел3 f" '■' i
» z=1.8;
» fprintf('%d',z>
1.800000e+000 % вместо формата Sd использован формат %е
» fprintf('%x',z>
1.800000е+000 % вместе формата %х использован формат %е
» fprijitf {' %u', z)
1.800000e+000 % вместо формата %u использован формат %е
» fprintf<'%f',z)
1.80D000 % незначащие нули в дробной части выводятся
» fprintfС%е',я)
1.800000е+000 % незначащие нули в дробной части выводятся
» fprintf{'%Е',г)
1.800000Е+000 % незначащие нули в дробной части выводятся
» fprintf('%g',z)
1.8 % незначащие нули в дробной части не выводятся
Работа с файлами
231
Если вы действительно, хотите использовать один из целочисленных
форматов для преобразования вещественного значения, то перед выводом в файл
такие величины нужно округлить с помощью одной из функций: fix, round,
floor ИЛИ ceil.
Однако MATLAB позволяет рассматривать вещественное число типа double
как 8 подряд идущих байтов и записывать их содержимое в текстовый файл
в виде последовательности из 16 шестнадцатеричных цифр. Для этой цели к
одному из целочисленных форматов %х, %х, %о, %и добавляется символ ь
(пример 6.20).
г: у™ ^■^■^■■■■-"^■чгсч:.^""'"*^^^
i Пример> 6.20. Вывод вещественногочисла■«Мвста^йэте^й^цбй^дё4^^','^
» fprintf(,%bx\n%bx,,l,-l)
3ff0000000000000
bff0000000000000
Еще одну возможность подобного рода предоставляет добавление символа t
к одному из указанных форматов. В этом случае вещественное значение
представляется как четырехбайтовое число типа float, и оно
"преобразуется" в цепочку из 8 шестнадцатеричных цифр (пример 6.21).
I Пример 6.21. Вывод числа типа-^ЙгсЫГ вЧи&йн^цатё^йчнШйй^Зй";. "'—" 1
» fprintf['%.tx\n.%tx', 1,-1)
3f300000
bf800000
Естественно, что каких-либо дополнительных затрат машинного времени на
такие "преобразования" не требуется. Тем не менее на некоторых
вычислительных платформах после чтения данных из файла, возможно, придется
менять местами старшие и младшие байты слов.
Точность п, следующая за шириной и отделяемая от нее точкой, обычно
определяет количество значащих цифр у вещественного числа в дробной
части. Однако по правилам языка C++ точность может быть использована и
в сочетании с форматными преобразованиями целых чисел, и даже строк.
В первом случае преобразуемое число должно содержать в своей
символьной записи не менее чем п цифр. Если их меньше, то старшие позиции
числа дополняются недостающим количеством нулей. При преобразовании
строки по формату %lo.5s в файл попадут не более 5 первых символов,
прижатых к правой границе поля, содержащего 10 позиций.
232 Глава 6
Руководства по языку C++ содержат еще несколько менее значительных
правил, определяющих влияние тех или иных сочетаний управляющих
символов на способ преобразования выводимых данных. Однако они
используются достаточно редко, а в случае необходимости вы можете самостоятельно
заглянуть в соответствующую документацию по языку C++.
(У Замечание ^
Если в списке данных, выводимых в текстовый файл, встречаются
комплексные переменные или выражения, то в обработку включаются значения только
вещественных частей (пример 6.22).
'Пример 6.22. Преобразование комплексных чисел при форматной записи": „ «&_ I
&-файл ,¾ - у -т$ф- - г -.,¾¾■" ■ ■ ;sr: ^.. жъ ^?г*$®т?Ш \
ь;.,..£. „-.- ..:Ш, .-;..-.зг:;г.„;..,.--..,.,. :...... „:. «...й от,.ы. „<и:.;„ .....:^ ■ :. •..,.}
» a=l+2*i
а =
1.0000 + 2.000'0i
» b=3+4*j
b =
3.0000 + 4.0000i
» fprintf ('%4.2f\n%4.2f, a, b)
1.00
3.00
Функция fprintf возвращает количество байтов, которое ей удалось
записать в указанный файл (с учетом ранее сделанного замечания о том, что
признак конца строки рассматривается как один двухбайтовый символ
newiine). Обычно этим значением функции fprintf редко кто не пользуется.
Единственная ситуация, в которой возвращаемое значение может помочь,
связана с поиском ошибки в строке форматных указателей. Иногда
MATLAB не выдает никаких сообщений, но и не выполняет запись
соответствующего значения выводного списка в файл (пример 6.23).
|Примёрф23г6шибкй:в-ф\>рЪ -. ; -^''.?|£^ч^ЙЙ:^
>> n=fprintf('%d %bd',1,-1)
1 n = % формат %bd не обслуживается, но и не критикуется
2
» n=fprintf (' %d %d\ 1,-1)
1 -In =
4
Работа с файлами
233
Продемонстрируем действие форматных указателей в ситуациях, когда
элементом выводного списка является вектор или матрица (пример 6.24).
» х=0:0.2:1 % вектор из 6 компонентов
х =
Q 0.2000 0.4000 0.6000 0.8000 1.0000
» fprintf('%g ',х) % вывод компонентов вектора в одной строке
0 0.2 0.4 0.6 0.8 1
» у=[х; sin(x)] % массив размерности 2x6
У =
0 0.2000 0.4000 0.6000 0.В000 1.0000
0 0.19В7 0.3894 0.5646 0.7174 0.8415
» fprintf{'%4.1f %8.4f\n',y) % вывод массива в виде 6 строк
0.0 0.0000
0.2 0.1987
0.4 0.3894
0.6 0.5646
0.8 0.7174
1.0 0.8415
Среди литеральных констанг в командной строке кроме уже
упоминавшегося признака конца строки ('\п') могут использоваться и другие управляющие
символы, известные под названием Esc-последователъноапи. Их перечень
приведен в табл. 6.4.
Таблица 6.4
Символ Описание
\Ь Удаление предыдущего символа (Backspace)
\£ Перевод страницы (Form feed)
\п Новая строка (New line)
\г Возврат каретки (Carriage return)
\t Горизонтальная табуляция (Horizontal tab)
Некоторые символы форматной строки задействованы как управляющие:
П с символа % начинается форматный указатель;
П одиночная кавычка открывает и закрывает строку форматов;
П обратная косая черта использована в Esc-последовательностях.
234
Глава 6
Для того чтобы включать такие символы в состав литеральных констант и
не путать их с управляющими комбинациями, в форматной строке
действуют следующие соглашения:
П %% — воспринимается как символ процента;
□ \\ -^ воспринимается как обратная косая черта;
П ' ' — воспринимается как одиночная кавычка;
0 \" — воспринимается как двойная кавычка.
( Замечание ^
В том случае, когда в текстовый файл с помощью функции fprintf
записывается единственная строка, строка форматных указателей может быть опущена
(пример 6.25).
1 Пример 6.25. Запись в текстовый файл без форматнь|х,указателей ' j;*''_■'-. *^''Ф|
» m-fprintf ('ABCDEFGH IJKLMN1 ) ;
ABCDEFGH IJKLMN
» m
m =
15
6.5.4. Чтение данных из текстового файла
Выборка данных из текстового файла может быть произведена с помощью
функции fscanf, обращение к которой в общем виде выглядит следующим
образом:
[a n]=fscanf(f_id,'format',т) ;
Здесь:
Па — принимающий массив, в элементы которого заносятся считываемые
данные;
П п — количество фактически считанных значений;
П f_id — номер открытого файла;
П format — список форматных указателей, в соответствии с которыми
осуществляется преобразование считываемых данных;
П m — количество запрашиваемых данных.
Обязательными параметрами в этом обращении являются массив а,
идентификатор файла fid и хотя бы один форматный указатель в списке format.
Отсутствие количества запрашиваемых значений или константа inf в каче-
Работа с файлами
235
стве третьего параметра воспринимаются как задание прочитать данные до
конца файла. Если количество запрашиваемых значений задано числом т, то
считываемые данные размешаются в векторе-столбце размерности mxi.
Однако, указав количество запрашиваемых данных в виде вектора [р q], мы
можем прочитать данные из файла в матрицу размерности pXq.
Продемонстрируем описанные возможности на следующем примере —
сгенерируем магический квадрат размером 5x5, запишем его элементы как
целые числа в текстовый файл a.txt, а затем попробуем разными способами
прочитать эту информацию (пример 6.26).
\ Пример .6.26. Запись и чтение
» k=fopen{'a.txt','wt');
» a=raagic{5)
a =
Ле из. текстового файла -&? * ---¾.¾~" •.-:■: :\+ ~ ■' •
% открыли файл лля вьшода
% сформировали магический квадрат
17
23
4
10
11
24
5
6
12
18
1
7
13
19
25
8
14
20
21
2
15
16
22
3
9
» n=fprintf (к, 'Ы ' ,а)
п =
66
» fclose(к);
» k=fopen('a.txt', 'rt') ;
» [b n]=fscanf (к,'%d\ [5 5]
b =
17
23
4
10
11
24
5
6
12
18
1
7
13
19
25
8
14
20
21
2
% записали массив а в файл
% количество Сайтов, записанных в файл
% закрыли файл
% открыли файл для чтения
) % читаем матрицу 5x5
15
16
22
3
9
25
» f rewind Ik) ;
» [с n]=fscanf (k, '%d.\5)
с =
17
23
%■ количество считанных значений
% вернули указатель файла в начало
% прочитали 5 значений (1-й столбец)
236
Глава 6
10
11
5
» whos
Name
a
b
с
к
n
Size
5x5
5x5
5x1
lxl
lxl
Bytes
200
200
40
В
8
Class
double
double
double
double
double
array
array
array
array
array
Обратите внимание на разницу в возвращаемых количествах между
функциями fprintf и fscanf. Первая из них считает количество байтов,
записываемых в файл, а вторая возвращает количество элементов данных,
считанных из файла. При выводе в файл кроме указателя %d в форматной
строке присутствует пробел, разделяющий числовые данные. Если вы
посчитаете количество цифр в элементах магического квадрата и добавите к
ним 25 пробелов (по одному пробелу после каждого числа), то получится
66 байтов.
Форматные указатели, задаваемые в строке формата у функции fscanf,
почти те же, что и у функции fprintf (см. табл. 6.3). Но если точность при
выводе имеет определенный смысл, то на ввод она не оказывает влияние. При
считывании вещественных данных из текстового файла указатели типа %f,
%е и %д выполняют одинаковые функции, преобразуя считанное значение в
машинный формат типа double. Форматные указатели типа %d, %i выбирают
из очередного поля текстового файла целочисленные данные, однако в
элементы принимающего массива результат преобразования заносится в
формате double.
Если форматный указатель начинается с комбинации %*, то
соответствующее значение, считанное из файла, в принимающий массив не передается.
Это дает возможность пропускать ненужные данные. В примере 6.27
показано считывание данных из файла с магическим квадратом и пропуском
каждого второго числа.
•, Пример 6.27<;Чтение И3 текстового файла с пропусками - *■- "{•- ■ ,-.:'
» frewind(k);
» [d n]=fscanf(k,'%d %*d')
Работа с файлами
237
d =
17
4
11
5
12
1
13
25
14
21
15
22
9
г. =
13
Форматные указатели типа %s на выводе и на вводе действуют по-разному.
Строка данных, записываемая в файл, например, может содержать пробелы.
Однако если мы читаем единичный элемент по формату %s, то чтение
прерывается на первом же пробеле. Если мы запрашиваем чтение более чем
одного элемента, то белые пробелы, встречающиеся в текстовой строке,
игнорируются (пример 6.28).
|;Пр;Имёр.&2в,:рбра!5а1^про^
» k=fopen ('a.txt','wt');
» fprintf(k,"%s','ABCD 012345') % записали строку с пробелом
ans =
11 % количество записанных байтов
» tclose(k);
» k=fopen ('a.txt','rt');
» [a n]=fscanf(k,'%s',l) % прочитали 1 элемент до первого пробела
а =
ABCD
п =
1
» frewind(к)у
» [a n]=fscanf(k,'%s',2) % прочитали 2 .элемента
238
Глава 6
а —
ABCD012345 % пробел проигнорирован
п =
2
» k=fopen('a.txt','wt'); * открыли файл
» fprintf (k,'%s\n%s','ABCD','0123.45'); % записали 2 строки
>> fclose(k);
» k=fopen ('a.ty±','rt');
» [a nj=fscanf(k,'%s') % читаем все данные
a -
ABCD012345 % признак конца 1-й строки проигнорирован
л =
2 %. прочитаны 2 элемента "
6.6. Форматные преобразования
в оперативной памяти
Все, что выше было сказано о работе функций fprinf и fscanf, можно
повторить для функций sprintf и sscanf. Если в первом случае в качестве
сторон, обменивающихся информацией, выступали массив, расположенный
в оперативной памяти, и файл, находящийся на диске, то во втором случае
вместо файла выступает строка, расположенная, как и массив, в
оперативной памяти:
[str errtxt] = sprintf('format',al,a2,...); % запись в строку str
[a n] = sscanf(str,'format',m); % чтение из строки str
Достаточно подробно работа этих функций рассматривалась в разд. 5.7.
6.7. Анализ ошибок
в файловых операциях
Обмен с файлом может завершиться ошибкой. Получить соответствующее
сообщение и узнать номер ошибки поможет функция ferror:
msg_ecr = (Terror (f_ict) ;
|msg_err num_err] = ferror(f_id);
Если последняя операция обмена с указанным файлом завершилась
нормально, то в символьную переменную msgerr записывается пустая строка,
а в качестве номера ошибки в переменную num_err заносится о. Если же
Работа с файлами
239
обнаружена нештатная ситуация, то числовой код ошибки будет отличен от
о. Для продолжения работы с данным файлом необходимо сбросить признак
аварийной ситуации:
[msg_err num__err] = ferror(f_id, 'clear1);
6.8. Альтернативный доступ
к текстовым файлам
Функция textread (пример 6.29), которая позволяет читать данные из
текстового файла, отличается от функции fscanf в первую очередь тем, что
файл не нужно открывать. Обращение к файлу производится не по номеру
открытого заранее файла, а по его имени. Конечно, такой способ менее
удобен, т. к. переключение на другой файл данных связано с внесением
большего количества исправлений.
Вторая особенность функции textread заключается в том, что при чтении
из текстового файла, заполненного только числовой информацией, можно
не задавать строку форматных преобразований.
Наконец, функция textread обладает большей гибкостью, т. к. с помощью
дополнительной пары аргументов типа "параметр — значение" позволяет
пропускать строки комментариев, управлять выбором
символов-разделителей, регулировать размеры буфера обмена и др.
В простейшем случае у функции textread может быть задан единственный
аргумент.
г.,.....г..„..,у,Ы„.---у-:;,ъ\^^^^^^^ ,„,,..,„,...,...,..,... ,.......;
I Пример, 6.29. Чтение из текстового файла с по^ taxtread
» K=fopen('a.txt','wt'); % открыли текстовый файл
» fprintf(k,'%d ',1,2,3,4,5); % записали 5 чисел
» f close (k) ;
» a=textread('a.txt')
a =
1. 2 3 4 5
( Замечание )
В среде MATLAB 7 этот пример выполняется неправильно — вслед за пятым
числом извлекается несуществующий 0. Скорее всего это ошибка системы.
Для того чтобы читать не все данные, среди входных аргументов должны
находиться форматная строка и количество запрашиваемых чисел
(пример 6.30).
240
Глава 6
i Пример 6.30. Формйтнр? чтение из текстового фаила.с помощью функции . ■ \ ;■
i.ii;.........-...-.-.-.'. 1...V..1. .C;.^v:i..:;.^..v;rh;-.^V..-.:..:..rt^^^ ..Ы............. -.н
» b=textread(,a.txt',' %d\2)
b =
1
2
Если задан формат, но не указано количество запрашиваемых чисел, то из
файла извлекаются все данные (пример 6.31).
h Пример;6.31 ДФорматйое .чтение' тёКртовр}ф\файла> целиком fe^fW**41
» b=textread('a.txt','%d'>
b =
1
2
3
4
5
Данные можно прочитать не только в массив, но и разбросать их по
отдельным переменным, но при этом каждой выходной переменной должен
соответствовать свой форматный указатель (пример 6.32).
^Примере. . ч" текрт вогоЛаедСв-л^^
» [bl Ь2 b3 b4 bSHtextreadCa.txt','%d %d. %d %d %d')
bl =
1
b2 =
2
ЪЗ =
3
b4 =
4
b5 =
5
Работа с файлами
241
Приписав символ * к любому из перечисленных выше форматных указателей,
мы можем пропустить соответствующее числовое значение (пример 6.33).
» [Ы ЬЗ b5]=textread('a.txt','%d %*d %d %*d %d'>
Ы =
1
ЬЗ =
3
Ь5 =
5.
Форматная строка может быть пуста, но при этом из текстового файла
можно прочитать только числовые данные (пример 6.34).
: Пример 6,34.: Нтёнйёйэ текстового файла с пустой форматной строкой ^,¾¾ :.4¾
» b=textread('a.txt', " )
b =
12 3 4 5
( Замечание )
В среде MATLAB 7 этот пример выполняется неправильно — вслед за пятым
числом извлекается несуществующий 0. Скорее всего это ошибка системы.
Форматные указатели, используемые в функции textread, немного
отличаются от тех, которые приводились в табл. 6.3. Их специфика отражена в
табл. 6.5.
Таблица 6.5
Формат Выполняемое преобразование
■%п Целое или вещественное число преобразуется из символьного
формата в формат double
%d Целое число со знаком преобразуется из символьного формата в
формат double
%u Целое число без знака преобразуется из символьного формата в
формат double
%f Вещественное число преобразуется из символьного формата в
формат double
242
Глава 6
Таблица 6.5 (окончание)
Формат Выполняемое преобразование
%s Строка, завершающаяся белым пробелом, преобразуется в
элемент массива ячеек
%q Строка, возможно, заключенная в двойные кавычки, преобразуется
в элемент массива ячеек
%с Символ или белый пробел преобразуется в символьный массив
% [sls2... ] Строка из символов, входящих в заданный набор, преобразуется в
элемент массива ячеек. Чтение прерывается при выборе символа,
не входящего в заданный набор
% (Лз1з2 . . . ] Строка из символов, не входящих в заданный набор, преобразуется
в элемент массива ячеек. Чтение прерывается при выборе символа,
входящего в заданный набор
В форматных указателях после символа % может быть задано целое число,
ограничивающее количество преобразуемых символов текстового файла,
если до этого не будет обнаружен настоящий символ-разделитель. В
качестве символа-разделителя по умолчанию используется белый пробел.
В качестве последних параметров функции textread могут задаваться пары
типа "свойство — значение", имеющие целью по желанию пользователя
подменить тот или иной управляющий символ или изменить значение
какой-либо системной характеристики. Возможные сочетания таких пар
приведены в табл. 6.6.
Таблица 6.6
Свойство Пояснение, возможные значения
'buf size' Максимальная длина строки в байтах (по умолчанию — 4096)
'commentstyle' Комментарий при выборке из текстового файла можно
проигнорировать. Допустимые значения свойства:
• 'mat lab': начало комментария в гл-файлах — символ %;
• 'shell': начало комментария — символ #;
• 'с': комментарий в С-программах—/* комментарий "'/;
• 'с++': начало комментария в программах на C++ — символ / /
'delimiter' Символ-разделитель элементов в считываемой строке
'emptyvalue' Способ передачи пропущенного значения
'endofline' Признак конца строки
Работа с файлами
243
Таблица 6.6 (окончание)
Свойство Пояснение, возможные значения
'expchars' Символ десятичного порядка (по умолчанию — еЕсЮ')
'headerlines' Количество пропускаемых строк в заголовке файла
'whitespace' Белые пробелы (по умолчанию — '\b\t')
В файлах помощи по функции textread приводится несколько полезных
примеров, иллюстрирующих особенности выборки данных из текстового
файла и использования дополнительных параметров "свойство — значение".
Прокомментируем эти слегка модифицированные примеры.
Пусть в текстовом файле с именем datal.dat должны находиться три строки-
записи, содержащие по пять полей со следующей информацией:
Sally Typel 12.34 45 Yes
Joe Type2 23.54 60 No
Bill Typel 34.90 12 No
Сформируем эти значения с помощью функции fprintf (пример 6.35).
; Пример Q.35. Формирование текстового файла • -
» k=fopen ('da tal.dat', 'wt');
» fprintf {k,'%s\n\'Sally Typel 12.34 45 Yes');
» fprintf(k,'%s\n','Joe Type2 23.54 60 No');
» fprintf(k,'%s\n','Bill Typel 34.90 12 No');
» fclose (k) ;
А теперь попробуем извлечь информацию из этих полей в соответствующие
массивы. Разделителями данных в нашем случае являются белые пробелы, в
число которых входят настоящие пробелы между значениями полей и
символы перехода на новую строку. Как только список форматных указателей
исчерпывается, он повторяется заново, а считываемые данные пополняют
следующие элементы наших массивов:
» [names,types,х,у,answer5 = textread('datal.dat','%s%s.%f%d%s')
names —
'Sally'
'Joe'
•Bill'
types ==
'Typel'
244
Глава 6
'Туре2'
■Typel'
х =
12.3400
23.5400
34.9000
У =
45
60
12
answer" =
'Yes'
'No'
'No'
» whos.
Name
answer
names
types
X
У
Size
3x1
3x1
3x1
3x1
3x1
Bytes
194
204
210
24
24
Class
cell array
cell array
cell array
double array
double array
Обратите внимание на то, что содержимое символьных полей, считываемых
по формату %s, поступает в массивы ячеек, а содержимое числовых полей —
В МаССИВЫ ТИПа double.
Теперь попробуем прочитать из содержимого того же файла только
значения первого поля, пропуская все остальные данные каждой строки до
признака newline (пример 6.36).
=. .Пример-6,3!Б:-ВыбррОчНр^
» [names]=textreadСdatal.dat','%5%*[Л\п]')
names =
'Sally'
'Joe'
'Bill'
Конечно, процедуру пропуска значений четырех оставшихся полей можно
было бы оформить и с помощью следующей строки форматных указателей —
%s%*s%*f%M%*s. Однако здесь продемонстрирован сравнительно редко ис-
Работа с файлами
245
пользуемый формат, который в данном примере звучит как "пропускать все
символы кроме символа newiine ('\п')"- Обратите внимание на то, что
форматный указатель %s пропускает все белые пробелы, в т. ч. и символы
перехода на новую строку.
Заменим в предыдущем примере формат %s на указатель %с (пример 6.37).
!гПример 6.37. Выборочное чтение символов из текстового файла 1^(¾¾¾¾¾¾¾¾
» [names]=textread('datal.dat','%c%*["\n]')
names =
Б
J
В
» whos
Name Size Bytes Class
names 3x1 6 char array
После выборки первого символа строки ее остаток был проигнорирован до
появления символа newiine, затем список форматов повторился и из
следующей строки был извлечен еще один символ. И все это повторилось еще
один раз (пример 6.38). В отличие от формата %s, по которому результаты
преобразования имели тип cell array, результат преобразования по
формату %с Имеет ТИП char array.
| Пример 6.38. Выборочное чтение из файла в переменные равных типов; ^ф0^;\
» [names,-type's,у, answer] = textread( 'datal .dat', '%9c%5s%*f%2d%3s')
names =
Sally
Joe
Bill
types =
'Typel'
•TypeZ"
'Typel'
У =
45
60
12
246
Глава 6
answer =
'Yes'
'Ко'
'No'
» whos
Name
answer
names
types
У
Siz«
3x1
3x9
3x1
3x1
Bytes Class
194 cell array
54 char array
210 cell array
24 double array
Интересен результат преобразования при чтении данных по формату,
представленному в примере 6.39.
[Пример 6.39. Чтение(Текстового феШа'по заданному формату ■
» [names,typenum,x,у,answer]=textread('datal.dat','%sType%d%f%d%s')
names =
•Sally'
'Joe'
'Bill'
typ.eiium =
1
2
1
x =
12.3400
23.5400
34.9000
У =
45
60
12
answer' =
•Yes'
'No'
'No'
Работа с файлами
247
whos
Name
answer
names
typenum
X
У
Size
3x1
3x1
3x1
3x1
3x1
tes
194
204
24
24
24
Class
cell array
cell array
double array
double array
double array
Включение литеральной константы туре в список форматных указателей
привело к тому, что аналогичные символы из считываемой строки были
извлечены в воздух. Зато следующий за ними символ был воспринят как целое
число и результат его преобразования по указателю %d был сохранен в
элементах вектора typenum В формате double.
Содержимое текстового файла в естественном виде по строкам можно
прочитать так, как показано в примере 6.40.
■текстового гЬайла' УУ^Щ..ff^-^AW «В*-4?^ ?-
Пример 6.40. Построчное чтение текстового файла
» file = textreadCdatal.dat','%s','delimiter','\n','whitespace','')
file =
Typel 12.34 45 Yes'
Type2 23.54 60 No'
Typel 34.90 12 No'
1 Sally
'Joe
'Bill
» whos
"Name
file
Size Bytes Class
3x1 338 cell array
Без подмены стандартных разделителей и белых пробелов результат чтения
был бы совершенно другим (пример 6.41).
| Пример 6.41, Ошибки при отсутствии обработки разделителей « - '""■■<■ -■;' ..
» file = textreadCdatal.dat', '%s')
file =
'Sally'
'Typel'
42.34'
'45'
'Yes'
'Joe'
« Зак. 899
248
Глава 6
'Туре2'
'23.54'
'60'
•No"
•Bill'
•Typel'
'34.90'
42'
'No'
» whos
Name Size Bytes Class
file 15x1 1010 cell array
При чтении числовых данных, разделенных запятыми, среди которых могут
оказаться "пустые" поля (две подряд идущие запятые), можно воспользоваться
свойствами delimiter и emptyvalue. Сформируем в текстовом файле с
именем data2.dat следующие строки:
1,2,3,4
5,6,7,8
9,10,11,12
При чтении по пустой форматной строке числа, разделенные запятыми,
заполняют строку результирующей матрицы. Но как только встречается
символ newiine, происходит переход к следующей строке результирующей
матрицы (пример 6.42).
| Дример^^ЧтМ^
» data = textreadCdata2.dat', ",'delimiter',',')
data =
12 3 4
5 6 7 8
9 10 11 12
Однако стоит нам задать какой-либо форматный указатель, как
возвращаемые значения заполняют вектор-столбец (пример 6.43).
^Пример 6.43, ЧтенКедекстовых данных, с разделителем; g;-: *-\*-ж *■?■*w*«5u -^-
» [data]=textread('data2.dat','%n','delimiter', ', ')
data =
1
Работа с файлами
249
2
3
4
5
6
7
8
9
10
11
12
Варьируя количество выходных аргументов и пропуская часть строки,
можно, например, прочитать только два первых столбца матрицы, хранящейся в
текстовом файле (пример 6.44).
I Призер 6.44.4}фнй£р;ад(»л"^ к. ,; ■ j
» [coll, со12] = textreadfdata2.dat','%n%n%*[Л\п]','delimiter',',')
coll =
1
5
9
col2 =
2
6
10
Сформируем третий текстовый файл с именем data3.dat, в котором заданы
некоторые пустые поля:
1,,3,4
5,6,,8
9,10,11,,
Воспользуемся свойством emptyvalue, которое позволяет заменить
отсутствующие данные указанным значением (пример 6.45).
= Пример 6.45. Чтенй^текстового файла С^стыми^РШМи^^^^^^^
i -...:.-..-...:.. .-..;..л.-.'.-.:.:.. ?... ;-.^...:.л...:;:.-:;..-:'.::..'.':.-. ;:::7.::..\.ъ;-.:.:*л.-::к:.л.-^
» data = textread('data3.dat','','delimiter',',','emptyvalue',KaN)
data =
1 NaN 3 4
250
Глава 6
5 6 NaN 6
9 10 11 NaN
( Замечание ^
В среде MATLAB 7 этот пример выполняется неправильно — в результате
появляется лишний пятый столбец, содержащий только элементы ЫаЫ. Мы
сохранили правильную выдачу, полученную в среде MATLAB 6.5. Скорее всего это
ошибка системы.
Обратите внимание на пропущенное значение в третьей строке файла
data3.dat — оно расположено между двумя запятыми. Между ними может
быть несколько пробелов, которые не оказывают никакого влияния на
результат преобразования. Но стоит нам удалить последнюю запятую, как
изменяется результат преобразования последнего элемента матрицы
(пример 6.46).
Шример 6Д6л;Р|щй6оч>1>8;тра«сг9вка последнего данного-„ :Щ^^ШШЖ ГЛШ
1,,3,4
5,6,,8
9,10,11,
» data = textread('data3.dat','','delimiter',',','emptyvalue', NaN)
data =
1 NaN 3 4
5 6 NaN R
■9 10 11 0
( Замечание ^
В среде MATLAB 7 и этот пример выполняется неправильно — вместо
последнего нулевого элемента появляется NaN. Скорее всего это ошибка системы.
6.9. Числовые файлы с разделителями
MATLAB предлагает еще одну разновидность текстовых файлов,
содержащих последовательность чисел, отделяемых друг от друга символами-
разделителями. Создаются такие файлы с помощью функции dimwrite:
dlmwrite (' f ile_name', a., dim) ;
В этом случае создается файл с именем filename, и в него записываются
элементы числового массива в символьном представлении. Вслед за каждым
числовым значением в файл записывается символ dim. Если записываемый
Работа с файлами
251
массив двумерный, то его элементы выводятся в файл по строкам
(пример 6.47).
\ Пример 6.47. Запись в числовой файл с р.аддвлйтепями:.^/^Ш^^ЙШ^4^^%^
I .....:..:.....:......... ...:v.*...-.'..i;;v.,.:,...',.:. .;;;:..■ ■...л".:...*;.:;.-..;.;;.;;*..^^";^^ .;
» a = magic(4)
а =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
» dLmwrite('dim.txt', а, ';')
Замечание
Данные в dim-файл записываются только один раз. Любая последующая
запись в файл с тем же именем уничтожает предыдущие данные.
Из созданного таким образом текстового файла, строки которого
завершаются символом LF (шестналцатеричный код оа), числовые данные читаются
с помощью функции dimread (пример 6.48), допускающей три формата
обращения:
b = dimread('file_name', dim);
b = dimread('file_read', dim, n,m);
b = dimread('file_naree',dlm, [nl ml n2 m2]);
В первом варианте из файла считываются все числовые данные, каждая
строка которых образует строку в выходном массиве. Во втором случае из
файла читается только фрагмент расположенной там матрицы. Левый
верхний угол этого фрагмента задается номером строки п и номером столбца m
(отсчет индексов ведется от о, а не от 1, как это принято во всех матричных
операциях MATLAB). В третьем формате вызова задается не только верхний
левый угол фрагмента, но и индексы правого нижнего угла.
г Пример 6.48; Чтение, из числового файла ср^зделитея^ми;ш«гЛй^^кК&»м^
» b=dlmread('dim.txt',';')
b =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
2S2
Глава 6
» c=dlmread(■dim.txt',';',2,1)
с =
7 б 12
14 15 1
» d=dlmread('dlm.txt\';',[0 1 2 3])
d =
2 3 13
11 10 8
7 6 12
При записи массива в файл с помощью функции dimwrite тоже имеется
возможность задания двух дополнительных индексов. Но речь идет не о
выводе части массива, а о месте расположения записываемых данных в файле
(пример 6.49).
» dimwrite{'dim.txt', a,';',2,1)
» d=dlmread('dim.txt■,';')
d =
0
0
16
5
9
4
0
0
2
11
7
14
0
0
3
10
6
15
0
0
13
'8
12
1
Попытка задать отрицательные дополнительные индексы не расценивается
как ошибка, но они автоматически заменяются нулевыми значениями
(пример 6.50).
: Пример 6,50, реакция системьгна"ошие!0нно^,задан^9йсум]е,нто8 fee ^. v г % щ
» dimwriteС dim. txt",a,',',-2,-1)
» b=dlmread( 'dlm.txf,', *)
b- =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Работа с файлами
253
А для того; чтобы записать часть массива, можно воспользоваться обычным
для MATLAB способом выделения нужного фрагмента (пример 6.51). Не
забывайте только, что в этом случае граничные значения индексов ведут
отсчет от 1.
• Пример6.51/Записьнаети'массивавчисловоифаил ^#^Зп&*#дЗД^ ч-&<£
» dlmwriteCdlm.txt'jafaM,2:3) , \ ')
» b=dlmread('dim.txt',',')
b =
11 10
7 6
14 15
Если в dim-файл записываются вектор-строка или вектор-столбец, то
числовые данные в файле имеют такую же организацию, как и исходные данные
(пример 6.52).
пример 6.52. еохранен|йеррганиза]цИ
» а=[1 2 3 4 5 6];
» dlmwrite('dlm.txt', а, ', ')
» b=dlmread(■dim.txt',',')
b =
12 3 4 5 6
» c=[l;2;3;4;5;6];
» dlmwrite('dlm.txt',c,',')
» d=dlmread('dim.txt',',')
d =
1
2
3
.4
5
6
Глава 7
Иерархия графических объектов
и их свойства
Для более точного понимания материала настоящей главы нам потребуются
некоторые термины, присущие объектно-ориентированному подходу (ООП)
в современных системах программирования.
Понятие класс обычно связывают с некоторым шаблоном, по образцу и
подобию которого строятся объекты — фрагменты программы, объединяющие
в себе данные и функции обработки этих данных. Объявление класса
эквивалентно объявлению структуры данных и описанию методов (функций) их
обработки. Когда создаются несколько объектов, порожденных данным
классом, то каждый объект получает личную оперативную память для
хранения своих данных. А функции их обработки при этом не дублируются.
Набор методов класса обслуживает данные любого объекта этого же класса
подобно тому, как стандартные функции получают разные аргументы и для
каждого из них выдают соответствующие результаты. Данные в каждом
объекте, порожденном одним и тем же классом, имеют одинаковые имена и,
чтобы различать, с какими аргументами должен проработать вызываемый
метод, он должен получить не только набор соответствующих параметров,
но и узнать, какой объект должен быть обслужен. В большинстве
универсальных алгоритмических языков вызов методов класса по форме
отличается от вызова обычных подпрограмм и функций (табл. 7.1).
Таблица 7.1
Язык Вызов Вызов метода Пояснение
программи- функции
рования
VisualBasic z = f(x,y> г = Obj.F(a,b) obj — имя объекта
pOb j — указатель на
объект
F — имя метода
256
Глава 7
Таблица 7.1 (окончание)
Язык
программирования
C++ Builder
Delphi
Вызов
функции
z = f(х,у);
z := fix,у)
Вызов метода
z = pObj->F[a,b);
z = Obj.F(a,b);
z := Obj.F(a,b);
Пояснение
Может показаться, что объектно-ориентированный подход существенно
усложняет жизнь программиста. Однако первое впечатление обманчиво.
Поясним это на простом примере. Пусть существует несколько классов,
каждый из которых связан соответственно с обработкой точек, отрезков
прямых и окружностей. Предположим, в каждом классе определен свой метод
отображения соответствующей графической фигуры на экране дисплея.
А называются эти методы, представленные, естественно, разными
программами, все одинаково — show. Насколько прозрачнее выглядит обращение к
отображению точки рцх.у), отрезка ы (xl,yi,x2,y2j и окружности
oi(xO,yO,R) по сравнению с традиционными вызовами соответствующих
функций:
putpixel(х, у); PI. Show;
line(xl,yl,x2,y2); Ll.Show;
circle <х0,уО,R); 01. Show;
На самом деле, сообщая методу имя объекта, мы неявно передаем и сведения
об этом объекте, которые хранятся в соответствующих информационных
полях. Класс позволяет защитить нужные данные от внешнего воздействия,
проконтролировать правильность их задания, поскольку к определенной
информации доступ возможен только через методы типа set (установить
новое значение) и get (опросить текущее значение). Такой подход,
несмотря на дополнительные накладные расходы, позволяет предотвращать многие
ошибки и разрабатывать достаточно хорошо защищенные программы.
Для создания объекта с именем nam_obji, построенного в соответствии с
шаблоном класса nam_cis, в языке C++ прибегают к специальным
функциям — конструкторам, имена которых совпадают с именем класса:
nam_cls nam__obj 1;
nam_cls nam_obj1(al,a2);
nam_cls nam__objl (nam_obj2) ;
В первом случае конструктор создает объект, присваивая каким-то его
данным значения по умолчанию, предусмотренные шаблоном класса. Во втором
Иерархия графических объектов и их свойства
257
случае конструктору передаются параметры (al,a2), которые используются
для начальной инициализации некоторых данных объекта. В третьем случае
вновь создаваемый объект получает начальные значения, которые были
использованы при создании уже существующего объекта nam_obj2.
Конструкторы обладают двумя полезными свойствами. Во-первых, они могут
проконтролировать правильность выделения ресурсов (в первую очередь, оперативной
памяти), необходимых для нормального функционирования объекта. Во-
вторых, они не допустят инициализации параметров объекта
непредусмотренными значениями. Именно поэтому прямой доступ к жизненно важным
данным объекта запрещен, и для установки новых значений или опроса текущих
значений обычно прибегают к функциям-посредникам, которые в состоянии
проконтролировать правильность той или иной операции.
Еще одна важная процедура, называемая деструктором, используется в
ООП для автоматического уничтожения объекта после выхода из блока
программы, в которой объект был объявлен. Деструкторы создаются и, как
правило, вызываются автоматически, освобождая программиста от заботы
по возврату занятых ресурсов. В C++ имена деструкторов тоже совпадают с
именем класса, однако им предшествует символ ~ (-nam_cis).
Еще один термин, который появился немного позже и активно
используется в системах визуального программирования, представляет наиболее
характерные свойства объекта (properties по терминологии C++). Большинство
из них определяет внешний вид объекта и/или управляет его
функционированием во время выполнения программы. К свойствам, присущим многим
объектам, относятся их габариты (ширина, высота), местоположение на
экране или внутри некоторой области, цвет, характеристики используемого
шрифта (имя шрифта, высота символов, наклон, утолщение контура,
подчеркивания), видимость объекта, его активность или пассивность и др.
Некоторые из таких свойств могут изменяться на стадии проектирования
программы, и пользователь способен визуально оценить принимаемые им
решения. Другие свойства оказываются доступными только на стадии
выполнения программы, причем некоторые из них можно только опросить
(доступны только для чтения). Для работы со свойствами объектов, в
универсальных системах программирования используются составные имена:
Labell->Caption="CKopocTb"; //так это выглядит в C++
Label1.Caption:='Скорость'; (так это выглядит в Delphi)
В приведенном примере свойству Caption (заголовок) объекта с именем
Labeli (метка) присваивается указанное символьное значение.
Объектно-ориентированное программирование никогда бы не состоялось,
если бы в нем не была предусмотрена процедура порождения новых классов
из уже существующих с наследованием данных, методов и разграничением
способа доступа к ним. На основе существующего класса а (базовый класс)
мы можем определить класс в (производный класс), который получит в на-
258
Глава 7
следство все или часть методов и данных базового класса. Производный
класс способен переопределить часть методов, доставшихся по наследству,
добавить новые данные и методы. Класс в может, в свою очередь, стать
"родителем" для следующего класса с, и таким образом легко построить
генеалогическое дерево некоторой программной системы. Язык C++
допускает порождение нового класса из двух или более базовых классов
(множественное наследование).
Для разграничения прав доступа к методам и данным в ООП введены такие
понятия, как общедоступные (public), защищенные (protected) и личные
(private) компоненты. К первой категории данных и методов могут
обращаться любые внешние функции. Данные и методы второй категории могут
быть переданы по наследству производному классу, но от других внешних
функций они защищены. Наконец, личные данные доступны только в том
классе, где они определены.
В системах визуального программирования появился еще один тип данных,
которые можно было бы назвать сверхдоступпыми (published). Он относится
к свойствам объекта, которые можно изменять на стадии конструирования
программы.
Изложенные выше соображения были приведены только для того, чтобы
подчеркнуть разницу между общепринятой терминологией и подходами к
реализации идей объектно-ориентированного программирования и
воплощением близких по содержанию, но все-таки иных по форме понятий в
системе MATLAB. Возможно, что причина расхождений лежит в истории
создания системы, которая сначала была реализована на Fortran — языке, в
котором до поры до времени никакого намека на
объектно-ориентированный подход и не было.
Тем не менее термины класс и иерархия классов, наследование и
переопределение функций, объекты и их свойства, события и реакция на них лежат в
основе таких разделов MATLAB, как структуры данных, графика и организация
диалогового взаимодействия с пользователем. На рис. 7.1 приведена схема
классов, отражающая структуру и иерархию компонентов графического
интерфейса пользователя (Graphic User Interface, GUI).
Сразу же договоримся о переводе термина handle, лежащего в основе всех
манипуляций с объектами. В системе MATLAB им пользуются для
идентификации различных объектов — открываемых файлов, графических окон,
координатных осей, линий графика, источников света, текстовых меток,
компонентов диалогового взаимодействия (кнопки, меню, окна ввода/
вывода). Значение того или иного handle можно отобразить как число, но
его величина для пользователя никакого смысла не несет. Исключение
составляет handle единственного объекта, порожденного классом Root. Его
значение равно о, и именно его приходится указывать при опросе или
установке каких-либо свойств данного объекта. Во всех остальных случаях роль
Иерархия графических объектов и их свойства
259
handle станет выполнять какая-либо переменная, значение которой будет
присвоено функцией, создающей тот или иной объект. В дальнейшем мы
будем называть этот системный идентификатор указателем или ссылкой на
объект.
Root
Figure
Axes
Uicontrol
Uimenu
Button Group
Uicontextmenu
Panel
Image
Line
Light
Rectangle
Patch
Text
Surface
Рис. 7.1. Иерархия классов GUI
В каждый конкретный момент выполнения программы выделяют три
объекта — активное окно (текущая фигура), только что созданный или
активизированный графический объект (текущий объект) и текущий график,
владельцем которого считаются координатные оси. Независимо от способа
создания этих объектов можно обратиться к одной из системных функций:
gcf (от англ. get handle of the current figure), geo (от англ. get handle of the
current object) и gca (от англ. get handle of the current axes) для получения
значения соответствующего указателя. Полученным значением можно
пользоваться при обращении к тому или иному методу обработки текущего окна,
объекта или графика.
Любой графический объект обладает определенным набором свойств,
каждое из которых имеет индивидуальное имя. Для опроса текущего или
установки нового значения того или иного свойства предназначены функции
get И set:
v = get (h, ' Свойство')
set(h,'Свойство',Новое_значение)
Первая из них возвращает значение указанного свойства, которым обладает
графический объект с указателем h. Вторая изменяет текущее значение ука-
260
Глава 7
занного свойства. Обе функции допускают различные варианты обращения.
В качестве первого аргумента может выступать массив указателей, и тогда
соответствующая операция распространяется на группу объектов. Результат,
возвращаемый функцией get, в этом случае представлен массивом ячеек,
длина которого совпадает с длиной вектора h. В каждую ячейку результата
заносится значение указанного свойства для соответствующего объекта.
Аргумент 'свойство' тоже может быть представлен не только скалярным
значением, но и массивом ячеек, значение каждой из которых определяет имя
соответствующего свойства.
К функции get можно обратиться и с единственным аргументом — get(h).
В этом случае она возвращает значения всех свойств указанного объекта в
виде пар
имя = значение
Количество таких свойств довольно велико, так, например, у объекта типа
Axes их порядка 100. И большинством из них пользователь так или иначе
может управлять. Поэтому важно знать, как влияет то или иное свойство на
поведение соответствующего объекта.
Функция set тоже допускает различные варианты обращения, основная
идея которых заключается в задании множества пар "имя — значение":
set(h,'Свойство^!.',3начение_1,*Свойство_2',Значение_2,...)
set(h,struct)
set(h,cell_name,cell_value)
В первом случае имена свойств и соответствующие им значения
перечисляются в виде списка переменной длины. Во втором случае аналогичные пары
задаются как значения нолей структуры struct. В третьем случае группа
имен задается ячейками массива ceii_name, а соответствующий им набор
значений — ячейками массива ceii_value.
7.1. Объект Root
Корнем генеалогического дерева является класс Root, символизирующий
экран дисплея. Единственным объектом этого класса выступает наше
приложение, которое система создает автоматически. Полный перечень его
свойств и набор соответствующих им значений можно получить,
обратившись к функции get с нулевым указателем (пример 7.1).
^Пример 7.1, Своие^рэ объекта Roofc -,-*&?\т^*<£^Щх*ШШ$£-. :¾¾¾¾^¾¾ j
» get(O)
CallbackObject = []
Иерархия графических объектов и их свойства
261
CoinmandWindowSize = [81 18]
CurrentFigure = [1]
Diary = off
DiaryFile = diary
Echo = off
FixedWidthFontName = Courier
Format = short
FormatSpacing = compact
Language = russian
MonitorPositions = [0 0 1024 768]
More = off
PointerLocation = [376 361]
PointerWindow = [0]
RecursionLimit = [500]
ScreenDepth = [32]
ScreenPixelsPerlnch = [116]
ScreenSize = [1 1 1024 768]
ShowHiddenHandles = off
Units = pixels
BeingDeleted = off
ButtonDownFcn =
Children = []
Clipping = on
CreateFen =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = []
Selected = off
SelectionHighlight = on
Tag =
Type = root
UIContextMenu = []
UserData = []
Visible = on
Познакомимся более подробно с каждым из свойств объекта Root, тем
более, что многие из них будут повторяться и в других объектах.
262
Глава 7
Термин Callback довольно часто встречается в документации в сочетании
СО словами Object (объект) И Function (функция, сокращенно— Fen). Он
немного непривычен для программистов, работавших в визуальных средах,
но достаточно понятен по смыслу. Речь идет об объекте, который в данный
момент явился инициатором некоторого события (caiibackobject), и
функции-обработчике данного события (calibackFunction). Префикс
callback, символизирующий "потусторонний вызов", просто означает, что
действия, связанные с возникшим событием и его обработкой,
инициируются не выполняющейся программой, а поведением пользователя и средой,
управляющей прохождением задач. Значением свойства Caiibackobject
является указатель на активизированный таким образом объект, если тот в
данный момент существует.
Свойство commandwindowSize определяет текущие размеры (ширину и
высоту) командного окна в текущих единицах измерения длин (см. значение
свойства units).
Свойство CurrentFigure задает номер текущего графического окна (i в
приведенном выше примере). В качестве такового может выступать только что
созданное графическое окно либо активизированное пользователем или
программой в результате выполнения одной из команд:
D figure (п) % — окно с указателем h выдвинуто на передний план;
□ set (0, 'CurrentFigure' ,h) % — активизировано окно с указателем h.
Два следующих свойства — Diary и DiaryFile — связаны с ведением
протокольного файла, в который могут быть записаны все шаги, фиксирующие
ваши операции во время сеанса, т. е. то, что дублируется в окне History
Command (История команд). Запись Diary=off означает, что запись в
протокольный файл отключена.
Свойство Echo, принимающее значение on (включено) или off
(выключено), связано с возможностью повторения текста выполняемых команд
m-файла в командном окне. Во время отладки программы включение такого
эха может оказаться полезным.
Свойство FixedwidthFontName определяет имя моноширинного (ширина
всех символов одинакова) шрифта, который используется в командном
окне. В противоположность этому, Windows располагает большим количеством
пропорциональных шрифтов, в которых существуют узкие (например — 1, i)
и широкие символы (например — w, щ). Их применение привело бы к
плавающей ширине колонок в выводимых таблицах.
Свойства Format и Formatspacing задают формат вывода числовых данных,
наличие или отсутствие дополнительных пустых строк. Выбор их значений
подробно обсуждался в гл. 2.
Иерархия графических объектов и их свойства
263
Свойство Language отражает текущий язык, установленный в операционной
системе.
Свойство MonitorPositions определяет координаты левого верхнего угла
монитора (0, 0) и разрешение в пикселах, установленное в данный момент
(1024x768).
При выводе данных, объем которых превышает размеры экрана, полезно
установить режим постраничного вывода (моге=оп), который
приостанавливает работу программы после заполнения области вывода. Для продолжения
работы достаточно нажать любую клавишу. Такая возможность была
предусмотрена еще в операционной системе MS-DOS.
Свойство Pointer-Location фиксирует текущие координаты (х, у) курсора
мыши в графическом окне, указатель которого хранится в свойстве
pointerwindow. В нашем примере этот указатель равен 0 (указатель на
объект Root), т. к. ни одного графического окна еще не было создано.
В свойстве RecursionLimit задается глубина рекурсии, т. е. максимальное
количество вложенных обращений к m-функциям. По достижению
указанного лимита выполнение программы будет прервано.
В свойстве ScreenDepth хранится количество битов, отводимых для
хранения компонентов цвета одного пиксела.
Свойство screenPixeisPerinch определяет количество пикселов,
приходящихся на 1 дюйм. Им можно воспользоваться при масштабировании
изображения на экране с другим разрешением.
Текущие координаты левого верхнего и правого нижнего углов объекта Root
в пикселах фиксируются в векторе screensize (в нашем примере
установлено разрешение 1024x768, и объект занимает весь экран). При измерении
длин в пикселах левый верхний угол имеет координаты (1, 1), во всех
остальных единицах измерения ему соответствует точка с нулевыми
координатами. Обратите внимание на положение начала координат в нижнем левом
углу, что характерно для всех математических учебников в отличие от
экранной системы координат, к которой привыкли программисты.
Свойство showHiddenHandies определяет, надо ли показывать объекты, чьи
указатели помечены как скрытые. Это напоминает возможности таких
оболочек, как Norton Commander или ДИСКо Командир по отображению имен
файлов с атрибутом hidden (скрытый).
В свойстве units хранится установленная система измерения длин.
Допустимый набор значений представляют следующие константы:
П normalized — при этом левым нижним углом поля вывода считается
точка с координатами (0, 0), правым верхним — точка с координатами
(1.0, 1.0). Приведением программных значений координат к
фактическому размеру окна занимается система. Это позволяет менять размеры
графического окна с одновременной адаптацией поля графика;
264
Глава 7
D pixels — все размеры задаются в пикселах, и пересчет программных
координат в пикселы выполняется программой пользователя;
□ inches — все размеры задаются в дюймах (1 дюйм = 2,54 см) и не
меняются при изменении габаритов графического окна;
□ centimeters — все размеры задаются в сантиметрах и не меняются при
изменении габаритов графического окна;
D points — все размеры задаются в пунктах (1 пункт = 1/72 дюйма =
= 0,3528 мм) и не меняются при изменении габаритов графического
окна;
D characters — размеры измеряются в "буквах". За ширину "буквы"
принимается ширина буквы "х" шрифта, установленного в операционной системе
по умолчанию, а за высоту— расстояние между базовыми линиями двух
смежных строк текста. Выбор такой единицы измерения длины позволяет
создавать приложения, имеющие одинаковый внешний вид на
компьютерах, управляемых различными операционными системами.
По умолчанию для объекта Root измерения производятся в пикселах.
Однако при построении графиков функций наиболее удобным является режим
normalized, который и установлен для объектов типа Figure по умолчанию.
Задание координат в единицах типа "сантиметры", "дюймы" или "пункты"
полезно при выводе на принтер документов, где должны быть соблюдены
абсолютные размеры.
Довольно многие свойства "описаны в классе Root только для того, чтобы
быть переданными по наследству порожденным классам. Очень немногие из
них имеют смысл для самого объекта Root. Однако мы объясняем их
назначение с единственной целью — не повторять соответствующий материал в
последующих разделах.
Свойства BusyAction (действие в случае занятости) и interruptibie
(возможность прерывания) определяют режим обработки текущего события в
момент возникновения нового события. Для объекта, вызвавшего текущее
событие, СВОЙСТВО Interruptibie Может быть разрешено (lnterruptible=on, по
умолчанию) или запрещено (interruptibie=off). В первом случае
обработка текущего события прерывается, обрабатывается вновь поступившее
событие, а затем продолжается обработка прерванного события. Во втором
случае существуют две возможности:
D обработка текущего события прекращается (если BusyAction=cancel) и
начинается обработка вновь поступившего события;
D вновь поступившее событие устанавливается в очередь и ждет
завершения обработки текущего события (если BusyAction=queue).
Иерархия графических объектов и их свойства
265
Свойства ButtonDownFcn, CreateFcn И DeleteFcn хранят указатели на
функции, соответственно обрабатывающие события "Щелчок мышью на
объекте", "Создание объекта1' и "Удаление объекта".
Местоположение объекта в иерархии существующих объектов определяется
свойствами Parent (родитель) и children (потомки). Первое из них
представлено указателем на породивший объект, чьи данные и методы наследует
текущий объект. В качестве значения второго свойства выступает вектор
указателей на объекты, порожденные данным и не помеченные как
невидимые. Естественно, что у объекта Root родитель отсутствует, а его дочерними
объектами являются все видимые графические окна, созданные к
настоящему моменту.
Свойства Selected и SelectionHighiight принимают значения on ИЛИ off в
зависимости от того, выделен ли данный объект и отмечен ли он повышенной
яркостью. Для разных объектов такое выделение может быть представлено
разными способами. Например, выделенный график функции помечается
черными маркерами вдоль кривой, .выделение строки списка достигается
путем инвертирования цвета, у выделенного окна изменяется цвет заголовка
и т. п.
Если графические построения выходят за пределы отведенной области, то
они, как правило, отсекаются (ciipping=on). Но в некоторых ситуациях
бывает полезно увидеть отсекаемую часть изображения, и тогда режим
отсечения можно запретить (clipping-of f).
Свойство Туре (тип) определяет принадлежность объекта тому или иному
классу. Если класс Root представлен единственным объектом с типом
Type=root, то другие классы могут быть представлены разными объектами с
общим типом. Например, все графические окна имеют тип figure.
Обратите внимание на свойство Tag (дословно — ярлык, этикетка, бирка),
значением которого может быть любая строка, присваиваемая пользователем. Для
того чтобы различать между собой объекты одного класса, их свойствам Tag
можно присвоить разные ярлыки. Конечно, это далеко не единственный
способ идентификации объектов, в частности, каждый объект имеет
уникальный указатель. При создании графических объектов в среде GUIDE
(Graphical User Interface Development Environment) свойству Tag значения
присваиваются автоматически, например — editl, edit2 и т. д. Началом
такого имени служит тип объекта, а дописываемый числовой индикатор
определяет порядковый номер объекта данного типа.
Свойство visible, которое может принимать одно из двух значений: on или
off, определяет видимость объекта на экране. Если какой-то объект
объявлен невидимым, то его указатель может попасть в список указателей
свойства childern, если родительское свойство showHiddenHandies разрешает это
сделать.
266
Глава 7
Свойство HitTest управляет режимом выбора текущего объекта по щелчку
мыши. Если его значение отключено (HitTest=off), то щелчок мыши при- ,
ВОДИТ К Сбросу Значения свойства CurrentObject (CurrentObject=[]).
Почти к любому графическому объекту может быть добавлено контекстное
меню, появляющееся при нажатии правой кнопки мыши в тот момент,
когда курсор находится над данным объектом. Указатель на такое меню
хранится В свойстве UIContextMenu.
Значением свойства userData может быть любая матрица с данными,
которая ассоциирована с объектом. Для корневого объекта такие данные
великого смысла не имеют. Однако пользователю предоставляется возможность
установить какие-то значения этого свойства с помощью функции set,
изменить их в процессе выполнения программы и опросить текущие значения
с помощью функции get.
7.2. Объект Figure
Графические окна являются объектами, порождаемыми по шаблону класса
Figure. Об этом свидетельствует свойство Туре, которое для любого
графического окна принимает значение figure. Существует несколько способов
создания графических окон. Во-первых, можно прибегнуть к услугам
функции figure:
» h_Fig = figure;
» h_Fig = figure ('Свойство_1',Значение_1,...
*Свойство_2',Значение_2,...);
В первом случае создается новое графическое окно, которому система
присваивает значения свойств по умолчанию. Во втором случае вновь
создаваемому объекту присваиваются значения указанных свойств, а неупомянутые
свойства устанавливаются системой по умолчанию. В обоих случаях
функция figure возвращает указатель на созданный объект, который становится
текущим, заслоняя собой остальные окна, находящиеся на экране.
Однако мы воспользуемся другим способом — построим график синусоиды
и отобразим все свойства текущего окна (пример 7.2).
кл.Г..,.......".-; йв,,.й ,..;i..&s^:i«(«&ftSiiWffi, *nrf«» ^s^^s^MSSi^^ig^^i^si&.4mmimss^
» х=6:0.2:6.28;
» y=sin(x);
» plot (х, у)
» h_Fig=g.cf ;
» getfh Fig) % Отображение всех свойств текущего окна
Иерархия графических объектов и их свойства
267
Alphamap =1 [1 by 64) double array]
BackingStore = on
CloseRequestFcn = closereq
Color = [0.8 0.8 0.8]
Colormap = [ (64 by 3) double array]
CurrentAxes = [101.001]
CurrentCharacter =
CurrentObject = []
CurrentPoint = [0 0]
DockControls = on
DoubleBuffer = on
FileName =
FixedColors = [ (10 by 3) double array]
IntegerHandle — on
InvertHardcopy = on
KeyPressFcn =
MenuBar = figure
MinColormap = [64]
Name =
NextPlot = add
NumberTitle = on
PaperUnits = centimeters
PaperOrientation = portrait
PaperPosition = [0.634517 6.34517 20.3046 15.2284]
PaperPositionMode = manual
PaperSize = [20.984 29.6774]
PaperType = A4
Pointer = arrow
PoihterShapeCData = [ (16 by 16) double array]
PointerShapeHotSpot = [1 1]
Position = [120 90 560 420]
Renderer = painters
RendererMode = auto
Resize = on
ResizeFcn =
SelectionType = normal
ShareColors = on
'ToolBar = auto
Units = pixels
268
Глава 7
WindowButtonDownFcn =
WindowButtonMotionFcn =
WindowButtonUpFcn =
WindowStyle = normal
WVisual = [ (1 by 77) char array]
WVisualMode = auto
BeingDeleted = off
ButtonDownFcn =
Children = [101.001]
Clipping = on
CreateFcn =
DeleteFcn =
BusyA'ction = queue
HandJeVisibility = on
HitTest = on
Interruptible = on
Parent = [6]
Selected = off
SelectionHighlight = on
Tag =
Type = figure
UICbntextMenu = []
UserData = []
Visible = on
Специфика графического окна, характеризующаяся наличием главного
меню и области, в которой могут быть расположены различные графические
объекты нижних уровней (оси, компоненты для организации интерфейса с
пользователем и др.), привела к появлению довольно большого числа новых
свойств, которых не было у родителя — объекта Root. Тем не менее порядка
20 свойств, содержащихся в предыдущем разделе, унаследовано
графическим окном, и к повторному их описанию мы возвращаться не будем.
Положение вновь создаваемого графического окна на экране определяется
его свойством Position, в качестве значений которого выступает четырех-
элементный вектор [left bottom width height]. Смещения left и bottom
задают положение нижнего левого угла, а два следующих компонента —
ширину и высоту окна в пикселах.
Графическое окно может быть обычным (windowstyie=normai) или
модальным (windowStyie=modai). В первом случае его можно переместить,
изменить размеры или закрыть. Во втором случае окно ждет только
определенного события со стороны пользователя (ввода данных, нажатия кнопки
Иерархия графических объектов и их свойства
269
и т. п.). Без этого события окно не может быть уничтожено, и работа
программы, соответственно, не может быть продолжена.
Окну присвоен стандартный заголовок Figure 1. Дополнительный заголовок
графического окна в виде строки хранится в свойстве Name. По умолчанию
это свойство представлено пустой строкой, и в заголовках окон мы видим
надписи типа Figure 1, Figure 2, и т. д. Если свойству Name присвоить какое-
либо значение, например,
h_Fig.Name = 'Оптимизация f(x)'
то заголовком окна будет строка вида:
Figure 1 : Оптимизация f (х)
Можно отказаться от стандартной нумерации окон (Figure 1, Figure 2 и т. д.),
если присвоить свойству NumberTitie значение off.
Свойство Мептдваг управляет отображением стандартного главного меню
графического окна. В режиме MenuBar=figure это меню создается и
отображается, в режиме мегшваг=гюпе — не создается и не отображается.
Независимо от значения этого свойства мы можем выполнить команду uimenu,
чтобы создать нестандартное меню графического окна.
Свойство Backingstore, принимающее значение on или off, управляет
"использованием специального буфера, расположенного1 в оперативной памяти
и применяемого для запоминания копии окна во время работы программы.
Если часть окна перекрывается на экране, то его содержимое может быть
быстро восстановлено путем копирования буфера в видеопамять.
Когда пользователь пытается закрыть графическое окно (это можно сделать
разными способами — нажать кнопку с крестиком в заголовке окна,
выбрать в меню команду Close (Закрыть) или выйти из системы MATLAB),
возникает событие "Запрос на закрытие". На это событие может
отреагировать специальный обработчик, предусмотренный программистом, или
системная программа, если пользователя усфаивают действия системы по
умолчанию. А сводятся системные действия к тому, что все скрытые
указатели из режима off переводятся в режим on, и все созданные объекты
удаляются. Соответствующая системная функция имеет имя closereq, которое
ПО умолчанию присвоено СВОЙСТВУ CloseRequestFcn.
Один из вариантов пользовательского обработчика указанного события
приведен в документации и его слегка переработанный текст представлен в
примере 7.3.
% my_closereq
selection = questdlg('Закрыть указанное окно?',...
'Close Request Function','Yes',?№>','Yes');
ч
270
Глава 7
switch selection,
case 'Yes' delete(gcf)
case 'No' return
end
Теперь остается заменить системный обработчик для окна с указателем
h_Fig на наш:
set(h_Fig,'CloseRequestFcn','my_closereq')
Значение свойства color определяет цвет фона в графическом окне с
помощью вектора из трех чисел, задающих интенсивность каждой из трех
RGB-составляющих. По умолчанию у всех окон цвет фона серый, и ему
соответствует комбинация [0.8 0.8 0.8].
Свойство coiormap представлено матрицей из m строк (по умолчанию m=64,
максимальное значение для Windows — 256). В каждой строке этой матрицы
задано 3 вещественных числа, соответствующих интенсивности RGB-coc-
тавлющих. Таким образом, матрица задает набор допустимых цветовых
оттенков (coiormap — дословно, карта цветов), в которые могут быть
окрашены различные объекты в окне. Использовать однобайтовый индекс строки
гораздо экономичнее, чем указывать три соответствующих вещественных
числа. Минимальное количество строк в массиве Coiormap определяется
значением свойства MinCoiormap. Матрица фиксированных цветов
FixedCoiors, также представленная матрицей размерности /ихЗ,
предназначена для запоминания нестандартных цветов, не попавших в свойство
Coiormap. В этой дополнительной матрице могут храниться нестандартные
цвета меток, линий, текстов и визуальных компонентов.
В графическом окне функция plot автоматически создала объект типа Axes,
присвоив ему указатель — вещественное число ю.1.001 (см. значение
свойства CurrentAxes). Поэтому у фигуры появился первый потомок
(chiidren=[ioi.OOi]). В свою очередь, родителем фигуры является объект
Root (parent=[0]). Так как мы еще не сохраняли текущее графическое окно
в файле с расширением fig, то значение свойства FileName пока не
определено.
Одним из важнейших свойств любой графической системы является
текущая точка, координаты которой [х,у] хранятся в векторе CurrentPoint.
В момент создания графического окна эта точка устанавливается в начало
координат, расположенное в левом нижнем углу фигуры. Затем система
отслеживает перемещения курсора мыши по графическому окну и изменяет
координаты текущей точки перед тем, как обратиться к одной из функций
обработки следующих событий: "Нажатие кнопки мыши", "Отпускание
кнопки мыши" и "Перемещение мыши". В каждом из обработчиков
указанных событий мы можем обратиться к свойству CurrentPoint, чтобы опреде-
Иерархия графических объектов и их свойства
271
лить текущее положение курсора мыши. Если ни один из перечисленных
обработчиков события не предусмотрен, изменение координат текущей
точки происходит в момент щелчка кнопкой мыши на территории
графического окна.
Свойство NextPiot управляет способом отображения нового графика в уже
существующем окне. По умолчанию NextPiot=add, что сохраняет ранее
установленные значения всех свойств. Если установить свойство NextPiot=
=repiace, то у окна восстанавливаются значения всех свойств по
умолчанию, кроме свойства Position, и удаляются все порожденные объекты
(children). Третья возможность (№xtPiot=repiacechiidren) сохраняет все
свойства текущего окна, но удаляет порожденные объекты.
Довольно широкие возможности по конфигурации указателя мыши в
зависимости от выполняемой операции предоставляют свойства Pointer и
PointerShapeCData. Первое из них может принимать одно из 17
стандартных значений: crosshair, arrow, watch, topi, topr, botl, botr, circle,
cross, fleur, left, right, top, bottom, fullcrosshair, ibeam, custom.
Полужирным шрифтом выделено значение по умолчанию, которому
соответствует стандартная стрелка. Последнее значение (custom — по выбору)
разрешает пользователю сформировать шаблон своего курсора в виде массива
размером 16x16, представляющего значение свойства PointershapeCData.
Значениями элементов такого массива могут быть: 1 — для обозначения
черных точек, 2 — для обозначения белых точек, Ыак — для обозначения
прозрачных точек.
В примере 7.4 приведен фрагмент создания образа курсора в виде квадрата с
прозрачной серединой, заимствованный из книги [3J и слегка
подправленный.
г^'^г"^'"1^'"'"....rr~;^"™T""~:w"-s*»v, , "?% v^K"""7""'^x £""у"—----,^
» MP = ones (16,16') ; % матрица 16x16 из единиц
» MP(2:15,2:15)=NaN; % заполнение прозрачных "точек"
» set(gcf,'Pointer','custom')
» set(gcf,'PointerShapeCData',MP)
» set(gcf,'PointerShapeHotSpot',[1 1])
Для нестандартного пользовательского курсора бывает полезно определить
характерную точку в шаблоне, которая соответствует указываемой позиции
на экране. По умолчанию таковой считается левый верхний угол шаблона,
который в локальной системе координат курсора имеет координаты (1, 1).
Эта система координат не совпадает с обычными координатами MATLAB,
она ближе к экранной системе координат. Целеуказывающая точка нестан-
272
Глава 7
дартного шаблона задается в виде двухэлементного вектора [ i j ],
присваиваемого СВОЙСТВУ PointerShapeHotSpot.
Возможность изменять размеры графического окна с помощью мыши
зависит от значения свойства Resize, по умолчанию равного on, что позволяет
деформировать или перемешать окно. При Resize=off такие манипуляции
запрещены. Изменение размеров окна или его перемещение вызывают
автоматическую перестройку графика с возможным изменением маркировки
координатных осей. Однако в поле графического окна могут находиться и
другие компоненты — кнопки, списки, окна ввода и др. Для их перерисовки
может понадобиться специальный обработчик события Resize — функция,
указатель на которую помещен в свойство ResizeFcn. Обработчики
подобного рода будут рассмотрены в гл. 9.
Несколько свойств графического окна связано с получением твердой копии.
При выводе на принтер или плоттер фоновый цвет может оказаться
неприемлемым, т. к. созданный график лучше бы смотрелся на белом фоне (при
этом можно было бы сэкономить и на расходе тонера). Если свойству
invertHardcopy присвоено значение on, то MATLAB на время печати
выполнит такую замену. В случае invertKardcopy=off принтер постарается
тем или иным способом соблюсти цветовую гамму графического окна
(цветной — цветом, черно-белый — полутонами). Свойства, начинающиеся
со слова Paper, управляют параметрами страницы, на которой
воспроизводится копия графического окна (табл. 7.2).
Таблица 7.2
Имя свойства Назначение
PaperUnits Установка единиц измерения (по умолчанию —
centimeters)
PaperOrientation Ориентация листа бумаги, по умолчанию — портретная
(portrait). Альтернативное расположение — альбомная
(landscape)
РарегТуре Формат листа бумаги (по умолчанию — А4)
Paper size Размер листа бумаги [width height] (по умолчанию —
[210 297])
PaperPosition Четырехкомпонентный вектор [xl yl х2 у2], задающий
положение прямоугольной области на листе, в которой
должно быть воспроизведено графическое окно. Началом
координат считается левый нижний угол листа. Точка
(xl, yl) определяет положение левого нижнего угла
прямоугольника, точка (х2, у2) — правого верхнего
Иерархия графических объектов и их свойства 273
Таблица 7.2 (окончание)
Имя свойства Назначение
PaperPositionMode Способ размещения графического окна на листе. При
PaperPositionMode=iranual положение рисунка задается
вектором PaperPosition. При PaperPositionMode=auto
система пытается отобразить окно в такой позиции, в какой
оно находится на экране (WYSIWYG — то, что вы видите, то
и получится)
При различных перемещениях отображаемых объектов по экрану приходится
каждый раз выполнять довольно большой объем вычислительной работы —
пересчитывать координаты характерных точек графического объекта,
освещенность и отражательную способность его граней и т. п. Этот процесс
называют визуализацией векторного изображения или рендерингом. Чем
эффективнее алгоритм решения такой задачи, тем более реалистично выглядит
отображаемый объект и тем быстрее перемещается по экрану. MATLAB
предлагает пользователю три варианта для выбора алгоритма рендеринга.
Значение Renderer=painters соответствует оригинальному алгоритму
разработчиков пакета, и он достаточно эффективно обрабатывает простые или
небольшие графические объекты. Значение Renderer=zbuffer позволяет
подключить известный алгоритм Z-буфера, в котором удаление невидимых
деталей осуществляется за счет анализа расстояний отображаемых точек до
поверхности экрана. Наиболее мощный и самый эффективный набор
алгоритмов отображения предлагает библиотека методов OpenGL, которая на
большинстве современных компьютеров поддерживается и аппаратными
средствами. Если вы с помощью команды opengl info убедитесь в такой
поддержке на своем компьютере, то самый лучший результат будет получен
при Renderer=OpenGL. Выбор метода рендеринга в зависимости от
сложности отображаемого объекта по умолчанию выполняет система, т. к. свойству
RendererMode присвоено значение auto.
Использование мыши для выделения какого-либо интерфейсного элемента
допускает различные действия со стороны пользователя — щелчки (обычно
левой кнопкой мыши), двойные щелчки (время между двумя
последовательными щелчками не превышает некоторого лимита времени,
установленного в системе), щелчки в сочетании с нажатой клавишей <Shift>, <Alt>
или <Ctrl>. Каждое из таких событий может быть ассоциировано с разными
программными откликами, например, двойной щелчок по имени файла
должен привести к его открыванию, щелчок по графическому объекту
может перевести его в режим перемещения или изменения размера и т. п.
Свойство seiectionType хранит информацию о способе, который был из-
274
Глава 7
бран пользователем при последней операции с мышью. Его значениями
могут быть следующие величины:
D normal, что соответствует обычному щелчку левой кнопкой;
□ extend, что соответствует щелчку левой кнопкой с одновременно
нажатой клавишей <Shift> или одновременному щелчку обеими кнопками;
□ ait, что соответствует щелчку правой кнопкой или сочетанию клавиши
<CtrI> с щелчком левой Кнопкой;
□ open, что соответствует двойному щелчку любой кнопкой мыши.
В момент, когда указатель мыши находится в области графического окна,
пользователь может быть инициатором следующих событий:
□ "Нажатие кнопки мыши" — обработчик этого события определяется
строкой, заданной в качестве значения свойства windowButtonDownFcn;
□ "Отпускание кнопки мыши" — обработчик этого события определяется
строкой, заданной в качестве значения свойства windowButtonUpFcn;
П "Перемещение мыши" — обработчик этого события определяется
строкой, заданной в качестве значения свойства windowButtonMotionFcn;
□ "Нажатие клавиши на клавиатуре" — обработчик этого события
определяется строкой, заданной в качестве значения свойства KeyPressDown.
Строки, представляющие значения этих свойств, задают имена
обработчиков соответствующих событий. В роли таких обработчиков могут выступать
либо заранее подготовленные m-файлы, либо строки, содержащие
выражения, которые MATLAB может исполнить.
Если обработчику KeyPressFcn передается управление, то символ,
соответствующий нажатой клавише, можно извлечь из свойства currentcharacter-.
Программа обработки этого события может также обратиться к свойству
pointerwindow объекта Root, чтобы узнать, в каком графическом окне в этот
момент находился курсор мыши.
Вектор-строка Aiphamap имеет отношение к отображению трехмерных
объектов в графическом окне. Он содержит набор числовых значений в
диапазоне [0, 1], которые могут быть приписаны к RGB-компонентам
каждого пиксела для определения степени его прозрачности. Палитра RGBA
позволяет отображать объекты, сквозь которые просвечивают другие
объекты заднего плана.
7.3. Объект Axes
Объект axes, представляющий график функции в графическом окне, является
наиболее сложным, ибо содержит довольно много составляющих — собствен-
Иерархий графических объектов и их свойства
275
но оси с их подписями и разметкой, линии графиков с их маркировкой и
соответствующими подписями, легенды, возможность увидеть объект из разных
позиций наблюдателя и многое другое. В примере 7.5 приведен список всех
свойств текущих осей, на которых был построен график синусоиды.
» get(gca)
ActivePositionProperty = outerposition
ALim = [0 1]
ALimMode = auto
AmbientLightColor = [1 1 1]
Box = on
CameraPosition = [3.5 0 17.3205]
CameraPositionMode = auto
CameraTarget = [3-.5 0 0]
CameraTargetMode = auto
CameraUpVector = [0 1 0]
CameraUpVectorMode = auto
CameraViewAngle = [6.60661]
CameraViewAngleMode = auto
CLim = [0 1]
CLimMode = auto
Color = [1 1 1]
CurrentPoint = I (2 by 3) double array]
ColorOrder = [ (7 by 3) double array]
DataAspectRatio = [3.5 1 1]
DataAspectRatioMode = auto
DrawMode = normal
FontAngle = normal
FontName = Helvetica
FontSize = [10]
FontUnits = points
FontWeight = normal
GridLineStyle = :
Layer = bottom
LineStyleOrder = -
LineWidth = [0.5]
276
Глава 7
MinorGridLineStyle = :
NextPlot = replace
OuterPosition = [0 0 1 1]
PlotBoxAspeetRatio = [1 1 1]
PlotBoxAspectRatioMode = auto
Projection = orthographic
Position = [0.13 0.13 0.775 0.815]
TickLength = [0.01 0.025]
TickDir = in
TickDirMode =■ auto
Tightlnset = [0.047619 0.0396825 0.00892857 0.0176571]
Title = [102.001]
Units = normalised
View = [0 90]
XColor = [0 0 0]
XDir = normal
XGrid = off
XLabel = [103]
XAxisLocacion = bottom
XLim = [0 7]
XLimMode = auto
XMinorGrid = off
XMinorTick = off
XScale = linear
XTick = [ (1 by 8) double array]
XTickLabel =
0
1
2
3
4
5
6
7
XTickLabelMode = auto
XTickMode = auto
YColor = [0 0 0]
YDir = normal
Иерархия графических объектов и их свойства 277
YGrid. = off
YLabel = [104]
YAxisLocation = left
YLim = [-1 1]
YLimMode = auto
YMinorGrid = off
YMinorTick = off
YScale = linear
YTick = [ (1 by 11) double array]
YTickLabel = [ (11 by 4) char array]
YTickLabelMode = auto
YTickMode = auto
ZColor = [0 0 0]
ZDir = normal
ZGrid = off
ZLabel = [105]
ZLim = [-11]
ZLimMode = auto
ZMinorGrid = off
ZMinorTick = off
ZScale = linear
ZTick = [-10 1]
ZTickLabel =
ZTickLabelMode = auto
ZTickMode = auto
BeingDeleted = off
ButxonDownFcn =
Children = [3.00098]
Clipping = on
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [1]
Selected = off
SelectionHighlight = on
278 Глава 7
Tag =
Type = axes
UICoiitextMenu = []
UserData = []
Visible = on
Свойство осей position позволяет нам определить положение осей в
графическом окне. Например, оператор
h_Ax ^ axes{'Position",[х у w h]};
создает объект типа Axes с указанной позицией и возвращает указатель на
созданный объект. Координаты (х, у) задают позицию левого нижнего угла
прямоугольного поля графика. Ширина w и высота h определяют размеры
прямоугольника. Эти величины задаются в единицах, соответствующих
значению свойства Units. По умолчанию для осей MATLAB использует
Units=normaiized, когда точка (о, о) соответствует левому нижнему углу, а
точка (1.0,1.0)— верхнему правому углу графического окна. В пределах
одного графического окна могут быть объявлены несколько осей
(пример 7.6).
: .--.--; ■■■■■:■ ..г..ТГг- v-.^^^.^.y.y........... ..,.v.,..,v.^..^-..t....,....,...,...,.,„.. .,.,„..,..,..,.....,.......„„ ;
I Пример 7.6. Неркрль«о;.оре|^й;Од||ом р^б.^^^^^^^у- -:, .,.-, _,.. ■> "- - ■
» axes ('position',[.1 .1 .8 .6])
» mesh(peaks(40) ) ;
» axes('position',[.1 .8 .8 .1])
» pcolorl [1:10,-1:10]) ;
Результат построения этих двух совершенно разнородных графиков
приведен на рис. 7.2.
Стиль линий, которыми рисуются оси графика, и их толщины регулируются
свойствами Linestyieorder и Linewldth. Возможные значения этих свойств
подробно обсуждались в гл. 2. Пример графика с утолщенными осями
(Linewidth=4) приведен на рис. 7.3.
Около 40 свойств управляют параметрами координатных осей.
Комментарии к этим свойствам, повторяющимся по каждой из трех осей,
приведены в табл. 7.3.
Иерархия графических объектов и их свойства
279
Рис. 7.2. Совмещение двух объектов типа Axes в одном окне
1
D.5
0
-DJ5
[ У
/
' /
/
1
f
1
1
] 1
~\
\
2 3
\
-4
/
/
/
5 6
•?
?:'*■ ■
U
!
.Г -
>3
■;i
Рис. 7.3. График с утолщенными осями
Таблица 7.3
Свойство
XColor
XDir
XGrid
XLabel
Значение
[rx gx bx]
normal 1 reverse
on | off
[px]
Пояснение
RGB-компоненты цвета оси x
Направление оси х
Наличие или отсутствие сетки,
перпендикулярной к оси X
Указатель на подпись под осью х
ЮЗак 899.
280
Глава 7
Таблица 7.3 (окончание)
Свойство
Значение
Пояснение
XAxisLocation
XLim
XLimMode
XMinorGrid
XMinorTick
XScale
XTick
XTickLabel
bottom I top
[xmin xmax]
auto I manual
on | off
on I off
linear | log
Массив чисел ixnx
Массив строк nxxl
XTickLabelMode auto | manual
XTickMode auto I manual
Положение оси x
Пределы изменения по оси х
Режим выбора пределов изменения
Наличие или отсутствие мелкой сетки,
перпендикулярной к оси х
Наличие или отсутствие мелких
штрихов по оси х
Масштаб по оси х
Координаты меток по оси х
Значения меток по оси х
Режим формирования меток
Режим нанесения меток
Еще несколько свойств принимают участие в оформлении поля графика:
□ Title — заголовок графика;
О Projection — задание проекции (orthographic ИЛИ perspective);
П GridLineStyle — стиль построения крупной координатной сетки;
О MinorGridLinestyle — стиль построения мелкой координатной сетки;
D TickLength — двухкомпонентныи вектор, задающий длины штрихов для
2D- и ЗО-графиков;
П TickDir — направление штрихов на осях (in — внутрь, out — наружу);
П TickDirMode — реЖИМ НЭНесеНИЯ ШТРИХОВ (auto ИЛИ manual).
В поле графика находится довольно много текстовых характеристик —
маркировка осей и штрихов, подпись графика. Поэтому объект Axes обладает
рядом свойств, управляющих параметрами используемого шрифта:
П FontName — имя шрифта;
□ Fontunits — единицы измерения высоты символов;
О Fontsize — высота символов;
D FontWeight — ПрИЗНЭК уТОЛЩеНИЯ КОНТура (light — ТОНКИЙ, normal —
нормальный, demi — полужирный, bold — жирный);
О FoncAngle — наклон шрифта (normal — Прямой, italic — Курсив,
oblique — НЭКЛОННЫЙ).
Иерархия графических объектов и их свойства
281
Свойства, названия которых включают сочетание AspectRatio, позволяют
отказаться от автоматического масштабирования и переключиться в ручной
режим управления шагами вдоль каждой из координатных осей. Для этих
целей гораздо удобнее воспользоваться функцией axis:
axis normal;
axis square;
axis equal;
Результаты такого управления приведены на рис. 7.4—7.6.
Группа свойств, названия которых начинаются со слова Camera, управляет
параметрами точки зрения. В точке с координатами CameraPosition
находится камера, наблюдающая за графическими объектами, размещенными на
поле Axes. Оптическая ось камеры нацелена на точку с координатами
CameraTarget. Угол обзора объектива камеры определяется значением
параметра CameraViewAngle. Наконец, компоненты вектора CameraUpVector
определяют поворот камеры вокруг оптической оси. Сцена, которую мы
наблюдаем на экране, представляет собой изображение, запечатленное
камерой. Каждый из перечисленных выше параметров либо выбирается
системой автоматически, либо назначается пользователем. Варианты выбора
определяются значениями СВОЙСТВ CameraPositionMode, CameraTargetMode,
CameraViewAngleMode И CameraUpVectorMode.
-> Figure 1
File- Ecjlt View Insert Tools Desktop Window, He(p.
dc*e-@if¥l^■«о®|'«;i Dm\«3 D "
,. .0.5'
f'''p-Ж.
Q
■ -0.5
1.Л- .
■V: '
" ' '''" ' -:"'
/ \
/ \
\
\
\
\
У ......1-'.-.; ■ .2',..;- -3- „.' 4
V~
/
/
. 1 . J-
^-*• ».f
- *- '
/
- 6 Y V ■:
НПИ
'" /"■ *
.-7-,^--.- -
- ■ r,% ,
■%■"!
Рис. 7.4. Автоматический выбор шагов по обеим осям
282
Глава 7
»> Figure 1
File Edit View InserM[ools Desktop Window Help
ЯПП
\ ,
/
*
Рис. 7.5. График в квадратной области
-> Figure 1
File Edit
View- insert Tools Desktop Window Help _ ..:
НПО
I-:-...
d.b* q в IfFJ.ei ^ ■*■> ® i«! D В1 в о
i;.5
.! s* 1
1 \ 0.5
:0
" ^5.
"-1
-1.5
(
^-
У N
\
\
) 1.2 3 4
-
/
У '
5 6
1 Л J
i
:4=4)
L ."
Рис. 7.6. График с равными шагами по обеим осям
Иерархия графических объектов и их свойства 283
7.4. Объект Line
Объекты типа Line создаются почти всеми функциями построения плоских
И пространственных кривых (plot, semilogx, semilogy, loglog, plotyy,
plots), которые возвращают указатель на появляющуюся кривую. Еще один
способ создания таких объектов предлагает функция line, допускающая
несколько вариантов обращения:
h_Lin = line(X,Y); % построение плоской кривой
h__Lin = line(X,Y,Z); % построение пространственной кривой
h_Lin = line(X,Y,Z,'свойство!',значение!,...
'свойство2',значение2,...);
h_Liri = line ('свойство1', значение1, .. .
'свойство2',значение2,...);
Для плоских кривых вектор х представляет собой набор значений
независимой переменной, а вектор у — набор соответствующих значений функции
>■(*). Таким образом, каждая точка плоской кривой задается парой
координат (Xj, yj). В случае пространственной кривой каждая ее точка представлена
тройкой координат (х/, yh ц). Построение кривой происходит в области
текущего объекта типа Axes, где каждая пара соседних точек соединяется
отрезком прямой.
Выведем список свойств линии после построения графика синусоиды
(пример 7.7).
! Пример 7.7. Свойства объекта liine ""■ ';<0 Ш^Щ'^фШгШ0Ш0^Шй. "Ч^Ш
» x=0:0.1:2*pi;
>> y=sin(x);
» h_lin=plot(x,y);
>> get(h_lin)
Color: [0 0 1]
EraseMode: 'normal'
LineStyle: '-'
LineWidth: 0.5000
Marker: 'none'
MarkerSize: 6
MarkerEdgeColor: 'auto'
MarkerFaceColor: 'none'
XData: [1x63 double]
YData: [1x63 double]
.ZData: [1x0 double]
284
Глава 7
BeingDeleted:
ButtonDownFcn:
Children:
Clipping:
CreateFcn:
DeleteFcn:
BusyAction:
HaridleVisibility:
HitTest:
Interruptible:
Selected:
SelectionHighlight:
Tag:
Type:
UIContextMenu:
UserData:
Visible:
Parent:
DisplayName:
XDataMode:
XDataSource:
YDataSource:
ZDataSource:
'off
[]
[Oxl double]
■on'
[]
[]
'queue'
'on'
■on'
•on'
•off
'on'
T 1
•line'
[]
[]
'on'
151.0079
1 1
1 manual■
f i
T 1
1 1
По сравнению с предыдущими графическими объектами линия обладает
совсем незначительным количеством свойств. Большинство из них вполне
подробно были описаны в гл. 2. Поэтому мы достаточно бегло будем
останавливаться на уже знакомых свойствах.
Синусоида построена синим цветом (color=[0 о 1]). Этот цвет был выбран
из последовательности цветов, заложенных в свойстве coiororder объекта
Axes. При построении следующего графика в поле тех же осей из списка
Coiororder будет выбран следующий цвет, и так до тех пор. пока не
окажется исчерпанным весь список. Потом цикл повторится с самого начала.
Свойство EraseMode управляет режимом взаимодействия цвета пикселов
создаваемой линии с цветом пикселов поля графика. Значение по
умолчанию — normal — приводит к тому, что пикселы кривой вытесняют пикселы
области рисования. Так строится нормальная кривая. Другими возможными
значениями свойства EraseMode являются попе (кривая не рисуется,
воспроизводятся только маркеры), background (кривая прорисовывается цветом
фона) и хог (цвета новых и старых пикселов взаимодействуют по операции
Иерархия графических объектов и их свойства
285
"исключающее ИЛИ"). Повторное рисование кривой по себе же в режиме
хог приводит к ее стиранию. При этом проявляется цвет пикселов области
рисования, в который они были окрашены до предыдущего рисования.
График синусоиды построен сплошной линией (Linestyle=-). Когда
график строится с помощью функции iine(x,Y,z) без указания стиля линии,
то он выбирается автоматически из списка стилей, указанных в свойстве
LinestyieOrder текущего объекта Axes (-, —, :, .:, none). Каждая новая
линия строится своим стилем — по очередному значению в списке
LineStyleOrder.
Толщиной линии управляет значение свойства Linewidth, которое задается
в пунктах (1 пункт = 1/72 дюйма = 0,3528 мм).
Свойство Marker включает (символы, определяющие вид маркера,
приведены в табл. 2.8) или отключает (попе) режим маркировки кривой. Размером
маркеров управляет значение свойства MarkerSize, задаваемое в пунктах.
Контуры маркера и его внутренняя область могут быть закрашены в цвета,
определяемые значениями СВОЙСТВ MarkerEdgeColor И MarkerFaceColor.
Значениями свойств XData, YData и ZData являются координаты точек кривой.
Перечень оставшихся свойств'1 уже обсуждался в предыдущих разделах.
Вместо них мы прокомментируем пример построения линии с тенью.
Идея примера заключается в построении двух слегка смещенных друг
относительно друга графиков. Причем теневой график имеет несколько большую
толщину линии. Приведенный в примере 7.8 фрагмент без изменений
заимствован из файлов помощи.
• Пример 7-8. Построение линиИ'С тенью ..¾ *%•№£*•?£:■,•. -.-' - %■*:&■ - ч
г...илг.;..^!.л;к.лй..Л'...л.л. л'.л^17^.-..л:..Ъ:.3>л»^.я^.Х-,лл:.-. ;л.'.Л:....&..1/.л. л й. .7¾ .:-:. л. . -." .< «,.*.>£. .*-.-.«
» t = 0:pi/20:2*pi;
» h_Linl = plot(t,sin(t),'k');
» h_Lin2 = line(t+.06,sin(t),'LineWidth',4,'Color',[.8 .8 .8]);
» set(gca,'Children',[h_Linl h_Lin2])
Первая команда формирует массив аргументов t, который используется во
второй команде для построения обычной синусоиды черным цветом.
Третья команда использует смещенный аргумент t+о.Об и строит в этих
точках утолщенную синусоиду серого цвета. Затем построенная тень
заслоняет большую часть первой синусоиды, и наблюдаемая картина производит
грустное впечатление (рис. 7.7). Зато четвертая команда осуществляет
перестройку дочерних линий, выводя на передний план основную синусоиду
(рис. 7.8).
286
Глава 7
Немного подумав, мы достигли такого же результата, изменив порядок
построения кривых и сэкономив на этом одну команду:
» t = 0:pi/20:2*pi;
» h_Lin2 = plot(t+.06,sin(t),'LineWidth',4,'Color',[.8 .8 .8]);
» h Linl = line(t,sin(t),'Color',[0 0 0]);
■■ ^ '-:
1
0.8
0.6
0,4
■i™
л.; 0
- -0.2
-0.4
-0.6
-0.S
-'<
Ir"
" /
/
•/
-
-
-
-
] 1
1
2
\
V
\
V
:o
\
3
,
4
./
/
/
/
/
/
5 6
I
-
-
-
-
-
-
7
Рис. 7.7. Неудачное расположение основного графика и его тени
Рис. 7.8. Результат перемещения основной синусоиды
на передний план
Иерархия графических объектов и их свойства
287
7.5. Объект Rectangle
Объект типа Rectangle используется для отображения прямоугольников,
прямоугольников с закругленными краями и эллипсов. Создаются такие
объекты на поверхности текущих осей с помощью функции rectangle,
возвращающей указатель на построенный прямоугольник:
h_Rect = rectangle;
h_Rect = rectangle ('Position', [к,y,w,h])
h_Rect = rectangle ('Position',[x, y,w,h],'Curvature', [rx,ry])
h_Rect = rectangle ('Свойство_1',Значение_1,...
'Свойство_2',Значение_2,...);
Вызов функции без параметров эквивалентен следующему обращению:
h_Rect = rectangle('Position",[0,0,1,1],'Curvature', [0,0]);
Свойство Position определяет координаты левого нижнего угла (х, у),
ширину w и высоту h прямоугольника. Нулевые значения свойства Curvature
(кривизна) соответствуют построению прямоугольника. Максимальные
значения составляющих rx, гу равны 1, и при них прямоугольник
превращается в эллипс.
Построим пару прямоугольников, чтобы познакомиться с другими
свойствами этих объектов (пример 7.9).
^Пример 7.9. Протроение'^рймругольнйиов- ^^-¾^^¾¾^¾¾¾^.^¾^^^¾
» h_Rectl=rectangle('Position', {50, 50,300, 230]) ;
» rectangle('Position',[70,70,200,150]);
» get(h_Rectl)
Curvature - [0 0]
EraseMode = normal
FaceColor = none
EdgeColor = [0 0 0]
LineStyle = -
LineWidth = [0.5]
Position = [50 50 300 200]
BeingDeleted = off
ButtonDownFcn =
Children = []
Clipping = on
CreateFcn =
DeleteFcn =
288
Глава 7
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [102.006]
Selected = off
SelectionHighlight = oh
Tag =
Type = rectangle
UIContextMenu = []
UserData = []
Visible = on
Их внешний вид показан на рис. 7.9. Первый прямоугольник имеет большие
размеры, и его контуры напоминают границы поля графика.
■■ 250
:- 2ро
150
100
■%
,■.,- =
0 100
150
200
250
300
'., ..
з<
-
"1
50
Рис. 7.9. Вложенные прямоугольники
В примере 7.10 приведен фрагмент программы, которая воспроизводит
4 квадрата с разными параметрами кривизны (рис. 7.10).
™........,...,..r.,.,.t....„,...v.,™„„., ..^.^„,?„.^...ф.....„ ,„..„„„,.;
Г: Пример Х1.0; ПбстрАещё.^
» xlim( [0, 0. 7]) % пределы изменения по оси х
» ylim([0,0.7]) % пределы изменения по оси у
Иерархий графических объектов и их свойства 289
» daspect([1,1,1J) % одинаковые шаги по осям
» rectangle С Position',[0.1,0.1,0.5,0.5],'Curvature',[0.1,0.1])
» rectangle('Position',[0.1,0.1,0.5,0.5],'Curvature',[0.5,0.5])
» rectangle('Position',[0.1,0.1,0.5,0.5],'Curvature',[0.75,0.75])
» rectangle('Position',[0.1,0.1,0.5,0.5],'Curvature',[1,1])
Рис. 7.10. Квадраты
с разными радиусами закругления
Контуры прямоугольника могут быть построены линиями любого
допустимого типа, хотя в районе закругления стиль линии строго не соблюдается
(рис. 7.И). В примере 7.11 использован любопытный прием — значение
свойства кривизны задано не вектором, а скалярной величиной. Однако в этом
случае кривизна по обеим осям считается одинаковой.
^"П|$Ш£§Щ'||^^ й:углами , ;^ ,$ч ^-^^2^Щ
» rectangle('Position',[0.5,0.5,3,1], ... •
' Curvature' ,0.4,' LineWidth', 2, • LineStyle',' — ')
» xlim([0,4])
» ylim([0,2])
» daspect([1,1,1])
290
Глава 7
Значение свойства Edgecoior задает цвет контура. С помощью свойства
FaceCoior можно закрасить внутренность графического объекта
(пример 7.12, рис. 7.12).
2
15
1
0.5
г'
-
-
J?K
гШН>
г
1
\
ч
i#%~*U, V
I
1
/
„У
О 0.5 . 1 1.5
2.5
3.5
Рис. 7.11. Прямоугольник со штриховым контуром
.;ПрИмёр;7.12.;[1Ь<^^ .-"?•■■ "-^Ш"
» rectangle('Position', [1,2,5,10],'Curvature',[1,1], ...
'FaceCoior', 'г')
12 Г
10.
Л
У 1-
V-t * '
зйИчЯ
■Л
1
.-* ■
ft"
1
ч
2
..-^-
э
Л0 ■
,.1|
--...>(!; 1Ь_.
1.
■:
Г-'.
:: -■ S
♦
i,
Т1
v ■;
6-:
Рис. 7.12. Закрашенный эллипс
Иерархия графических объектов и их свойства
291
7.6. Объект Text
Функция text предназначена для формирования надписей (объектов Text) в
поле текущего объекта Axes. В простейшем случае обращение к ней
напоминает вызов процедуры outtextxy в графическом пакете Borland Graphics
Interface:
» h_Txt=text(0.5,0.5,'Hello, World!');
Два первых аргумента в этом обращении представлены координатами точки
привязки текста. Третий аргумент определяет воспроизводимый текст.
Результат этого обращения представлен на рис. 7.13.
1
ав
D.6
D.4
0,2
0
-
1. °-2
D.4
Hello. Worldl
.'..0.6
0.8 ..
1
Рис. 7.13. Текст в центре поля осей
Положение надписи относительно точки привязки регулируется значениями
двух СВОЙСТВ Объекта — Horizontal Alignment (горизонтальный ПрИЖИМ) И
verticaiAiignment (вертикальный прижим). Допустимым значением первого
свойства является одна из строк — left (к левой границе), center (по
центру), right (к правой границе). По умолчанию действует левый прижим.
Если вокруг надписи построить габаритный прямоугольник, то его
положение относительно координаты х точки привязки в зависимости от значения
левого прижима показано на рис. 7.14. Координаты левого нижнего угла
габаритного прямоугольника, его ширина и высота составляют вектор
значений свойства Extent.
Допустимым значением вертикального прижима является одна из строк —
middle (по центру), baseline (на линии строки), top (по верхней границе),
bottom (по нижней границе), cap (под линией строки). Положение
габаритного прямоугольника относительно координаты у точки привязки в
зависимости от вертикального прижима показано на рис. 7.15. По умолчанию
действует прижим по центру.
I
292
Глава 7
Left
Center
Right
Рис. 7.14. Влияние горизонтального прижима
-МккНе-
Ragplirw
Bottom
"Cap"
Top
Рис. 7.15. Влияние вертикального прижима
Если надпись должна сопровождать изображение трехмерного объекта, то
координаты точки привязки содержат еще одну переменную z:
» h_Txt=text(х,у,z,'подпись');
Кроме координат точки привязки и текста надписи среди параметров
функции text могут присутствовать пары "свойство — значение", определяющие
те или иные характеристики объекта Text. В примере 7.13 приведен полный
список свойств объекта, представленного на рис. 7.13.
» get(h_Txt)
BackgroundColor = none-
Color = [0 0 0]
EdgeColor = none
EraseMode = normal
Editing = off
Extent = [0.493151 0.444444 0.260274 0.1]
FontAngle = normal
. FontName = Helvetica
FontSize = [10]
FontUnits = points
FpntWeight = normal
Иерархия графических объектов и их свойства
293
HorizontalAlignment = left
LineStyle = -
LineWidth = [0.5]
Margin = [2]
Position = [0.5 0.5 0]
Rotation = [0]
String = Hello, World!
Units = data
Interpreter = tex
VerticalAlignment = middle
BeingDeleted = off
ButtonDownFcn =
Children = []
Clipping = off
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [102.007]
Selected = off
SelectionHighlight = on
Tag =
Type = text
UIContextMenu = []
UserData = []
Visible = on
Координаты (x, y, z) и воспроизводимый текст могут быть представлены
массивами одинаковой размерности. Это означает, что функция text
создаст несколько объектов, каждый из которых будет иметь свою точку
привязки (xj., у±, zj.). Компоненты надписей при этом могут быть заданы
разными способами — либо в виде массива ячеек, каждый элемент которого
предсгавлен строкой, либо в виде массива строк одинаковой длины, либо в
виде вектора-строки, в котором надписи разделены символом |. Обращение
вида:
text(х,у,z, 'string')
294 Глава 7
эквивалентно вызову функции text со следующим набором свойств:
text('XData',x, 'YData',y, 'ZData',z, 'string', 'текст')
Наряду с обычными символами отображаемая строка может содержать
специальные комбинации, принятые в редакторе ТеХ и позволяющие
воспроизводить обозначения, характерные для математических формул (табл. 7.4).
Таблица 7.4
Строка ТеХ
\alpha
\beta
\gamma
\delta
\epsilon
\zeta
\eta
\theta
Wartheta
\iota
\kappa
\lambda
\mu
\nu
\xi
\pi
\rho
\sigma
\varsigma
\tau
\equiv
Mm
\otimes
1 Символ
! a
IP
1 Y
! s
1 E
! с
\r\\
\ e
1 ■&
i i
! к
! *
j n
1 V
u
■ rc
1 p
! о
! ?
1 T
[ =
! 3
I ®
Строка ТеХ
\upsilon
\phi
\chi
\psi
\omega
\Gamma
Delta
\Theta
\Lambda
\Xi
\Pi
\Sigma
\Upsilon
\Phi
\Psi
\Omega
\forall
\exists
\ni
\cong
\approx
\Re
\oplus
1 Символ
! u
i *
[x
! v
i to
i г
1 A
; в
! л
1 E
! П
! 2
! Y
| Ф
1 ^
j £1
i v
| 3
j э
j =
I =
! я
! ©
Строка ТеХ
\sim
\leq
\infty
\clubsuit
\diamondsuit
\heartsuit
\spadesuit
Meftrightarrow
Meftarrow
\uparrow
\rightarrow
\downarrow
\circ
\pm
\geq
\propto
\partial
\bullet
\div
\neq
\aleph
\wp
\oslash
j Символ
| -
! <
: 0°
i *
I ♦
! *
; A
1 <->
i <—
! т
! —>
| 1
| о
! +
1 >
• oc
!й
\ •
1 +
1 /
1 N
! p
1 0
Иерархия графических объектов и их свойства
295
Таблица 7.4 (окончание)
Строка ТеХ I Символ
\сар I п
\supset 1 з
\int | J
\rfloor j J
\ffloor I L
\perp ! 1
Wedge j л
\rceil j 1
Wee ! v
Mangle j <
Строка ТеХ ! Символ
\cup | u
\subseteq j с
\in j iE
\lceil | Г
\cdot
\neg 1 -,
\times 1 x
\surd j V
\varpi 1 w
\rangle 1 )
Строка ТеХ ; Символ
\supseteq ] з
\subset j с
\o ! 0
\nabla j V
\ldots j ...
\prime j '
\0 j 0
\tnid I |
\copyright j ©
Используя соглашения ТеХ (пример 7.14), можно дублировать значения
таких свойств объекта Text, как имя шрифта (FontName), высоту символов
(FontSize), угол наклона СИМВОЛОВ (FontAngle):
П \fontname{HMH_mpM$Ta};
D \fontsizelвысота символов} в единицах, установленных в свойстве
FontUnits;
□ \bf — жирный шрифт (bold);
П \гга — Прямой шрифт (normal);
□ \it — наклонный шрифт (italic).
\ Пример 7.14. Использование-йотации ТёК^^Щ0Ш^$^т"^^^:^;:.уШ^:\
» х = 0:pi/20:2*pi;
» plot (х, sin (х) )
» text(pi,0,' Ueftarrow sin(\pi)','FontSize',18)
Результат работы этого фрагмента приведен на рис. 7.16.
Еще один пример воспроизведения формулы функции комплексного
переменного приведен на рис. 7.17. Запись самой формулы по правилам ТеХ
имеет вид, представленный в примере 7.15.
296
Глава 7
,~, Р.5
0
-0.5
1[
/
/
) 1
\
\
N
2 Э
- Sin(7l) /
\/ '
4 5 6"
г
Рис. 7.16. Подпись графика в точке (л, 0)
1
D.B
0.6
0.4
0.2
0
(
е?"1 = cos(ax) + i sin(Kn)
i i i
] 0.2 0.4 0.6"
,
0.8
Т;-
*£
1
Рис. 7.17. Пример вывода формулы
I Пример 7.15. Воспроизведение формулы в рисункеЛ-Ч1^|ф|%ч^§^833^!^^,^''-'^р
text(0.2,0.8,'e'MiNomegaXtau} = cos(\omega\tau) + i sin(\omega\tau)')
Разрешением или запретом на использование такого рода записей управляет
свойство interpreter, которое может принимать одно из двух значений: tex
или попе. По умолчанию нотация ТеХ разрешена.
Свойство Position для объекта типа Text немного отличается от
аналогичного свойства других [рафических объектов. Компонентами его вектора
являются только координаты точки привязки (х, у, г). Габариты подписи,
точнее окаймляюшего ее прямоугольника, задаются значением компонентов
свойства Extent.
Любая подпись может быть повернута на заданный угол, если ее свойству
Rotation присвоено значение этого угла в градусах (пример 7.16).
Иерархия графических объектов и их свойства
297
ШШШШШШШШШШШШВШШт
» text(.1,.1,'Hello, World!','Rotation',45)
Результат поворота представлен на рис. 7.18.
' ? 1
. о.е
ь
й* -
■; 0.2
■
*Л
•
г
) 0.'2 ■
■i
0.4
0.6
-;-~Л 'А
0.8"
&
1
1 .-J
Рис. 7.18. Поворот текста на 45е
С помощью свойства Editing можно разрешить режим редактирования
текста, отображенного в поле осей. В момент появления подписи, для которой
разрешен режим редактирования (Editing=on), в ее начале мигает
текстовый курсор, и пользователь может выполнить обычную для текстов правку,
например, заменить слово Hello на слово привет (рис. 7.19). По умолчанию
режим редактирования запрещен:
» text{.1,.5,'Hello, Wcrld!','Editing','on')'
1
0.8
0.6
■•0.4
0!2
°t
ШИ World!
i ■у 0.2 ■ "■
0.A :
■ 0.6
0.B
1
Рис. 7.19. Редактирование текста
298
Глава 7
Включив свойство selected (по умолчанию selected=off), мы сразу
получим выделенный текст (рис. 7.20):
» text(.1,.5,"Hello, World!','Selected1,'on')
Эффект такого же выделения может быть достигнут и с помощью кнопок на
панели инструментов управления графиком. Однако основный смысл этого
свойства — другой. С его помощью программа обработки некоторого
события может узнать, выделил ли пользователь тот или иной текст в
графическом окне.
-> Figure 1
File Edit
View Insert Tools Desktop Window Help
d с» a m I k 1Q. a. & ® | -#; d в | и □
1
0.8
0.6
0.4
0.2
0
(
- _, ■__
*Hello.World!"
ш ■ ■
3 , 0.2 0.4 0.6 0.8 ' A
HDD
ii
is"
1 .
Рис. 7.20. Программное выделение текста
7.7. Объект Image
Графический объект типа image предназначен для воспроизведения
растровых изображений, которые либо считываются из графических файлов, либо
специальным образом формируются в оперативной памяти. Растровые
изображения состоят из окрашенных прямоугольных элементов, заполняющих
в поле осей графического окна область размером mxn элементов. В частном
случае роль таких прямоугольных элементов изображения могут играть
пикселы экрана. Данные о кодах цветности каждого элемента изображения
составляют матрицу, которая представляет свойство cData объекта image.
MATLAB предоставляет возможность работы с изображениями трех типов.
Иерархия графических объектов и их свойства
299
Первый из них составляют так называемые RGB-объекты, описываемые в
формате truecoior. Для них матрица CData имеет размерность тхпхз и
каждому элементу изображения с координатами (i, j) в матрице цветности
соответствует тройка вещественных числовых значений в диапазоне от о до 1,
определяющая интенсивность составляющих компонентов:
□ элемент с индексами (i, j, l) — интенсивность красного цвета;
П элемент с индексами (i, j, 2) — интенсивность зеленого цвета;
О элемент с индексами (i, j, з) — интенсивность синего цвета.
В форматах графических файлов, используемых в среде Windows, аналогичные
RGB-компоненты пикселов хранятся как 8- или 16-битные целые числа.
Второй тип графических изображений составляют так называемые
индексированные (indexed) объекты, у которых матрица CData имеет размерность
mXn и каждый ее элемент представляет собой целое число в диапазоне от о
до 255 или от о до 65 535. Это число рассматривается как индекс в массиве
палитры (coiormap), который ассоциирован с текущим графическим окном.
Массив палитры, в свою очередь, состоит из числовых троек в диапазоне [о, i|,
характеризующих интенсивность RGB-компонентов. К такому косвенному
способу представления цвета пикселов прибегают при кодировании
растровых изображений в формате BMP, когда на каждый пиксел отводится 1, 4, 8
или 16 битов. Индексированный подход позволяет более экономно
закодировать изображение при относительно небольшом количестве используемых
цветовых оттенков.
К третьему типу относятся полутоновые монохромные изображения, в
которых элемент двухмерной матрицы CData определяет интенсивность цвета в
так называемой серой шкале (grayscale). Этот масштабный коэффициент в
массиве CData также приведен к диапазону [о, i], хотя в графических
файлах Windows для хранения оттенков серого используются 8- или 16-битные
целые числа.
Таким образом, если массив cmta — трехмерный, то соответствующее
графическое изображение представлено в формате truecoior. А для того чтобы
отличать индексированные изображения от полутоновых, у объекта image
предусмотрено свойство CDataMapping. По умолчанию его значением
является строка direct, соответствующая типу изображения coiormap. Вторым
значением свойства CDataMapping является строка scaled, соответствующая
изображению в серых тонах.
Чтобы подчеркнуть разницу между пикселами и элементами изображения,
создадим индексированный объект типа image размерности 3x4
(пример 7.17).
300
Глава 7
12 3 4
.5678
9 10 11 12
» h = image(X); % формирование изображения размерности 3x4
» colormap(colorcube(12)) % формирование цветовой палитры
Функция coiorcube(n) по некоторому закону формирует п цветовых троек,
которые используются в качестве цветовой палитры для индексных
изображений нашего приложения. Результат выполнения указанного фрагмента
приведен на рис. 7.21.
1
0.5
1
.. ^. % ,-
Г i '
'г»
2-Я
&
2.5 **?
3
3i5
J
'.■№,
1 1.5
if
&«*
2
mr -
И'
'*;
с
as.',:
4t.
4l№
4S.T"
P
25 3
•1
j.
:'i
*»*
'"' г
.■;
i
4
3.5
4
:
' : _.
«"'"
Рис. 7.21. Индексированное изображение размером 3x4
Познакомимся с наиболее важными свойствами созданного объекта
(пример 7.18).
Иерархия графических объектов и их свойства
301
» get(h)
AlphaData = [1]
AlphaDataMapping = none
CData = [ (3 by 3) double array]
CDataMapping = direct
EraseMode = normal
XData = [1 4]
YData = [1 3]
BeingDeleted = off
ButtonDownFcn =
Children = []
Clipping = on
Create.Fcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [101.001]
Selected = off
SelectionHighlight = on
Tag =
Type = image
UICpntextMenu = []
UserData = []
Visible = on
Свойства AlphaData и AiphaDataMapping, связанные с прозрачностью
элементов изображения, в нашем примере не используются.
Значения упоминавшегося выше свойства CData в нашем случае совладают
с элементами массива х, использованного при создании объекта:
» get(h,'CData')
ans
=
1
5
9
2
6
10
3
7
11
4
8
12
302
Глава 7
Свойство CDataMapping свидетельствует о том, что наше изображение
строится на базе индексированных данных (CDataMapping=direct).
Режим Eras.eMode=normal означает, что при выводе изображения
предшествующее содержимое поля осей стирается. Если мы с помощью функции set
изменим значение свойства CData, то перед выводом нового изображения
прежнее изображение будет уничтожено. В том случае, когда планируется
вывод последовательных кадров анимированного изображения, режим стирания
приводит к дополнительным затратам времени и вместо плавного перехода от
кадра к кадру вызывает дергание на экране. Для более плавного отображения
динамических кадров предпочтительнее установить EraseMode=none.
Значения свойств XData и YData определяют диапазоны изменения индексов
по осям х и у. Для объекта размерности mXn значениями этих свойств по
умолчанию являются интервалы XData=[i п] и YData=[i m]. Если по
каким-то соображениям значения индексов необходимо сместить, то это
можно сделать так, как представлено в примере 7.19.
г_.^...„...:™.................:...„
[Пример 7.19. Смёще;нйе;Координат;изобрЩ^
» image(X,'XData', [-1 2],'YData',[2 4]);
» colormaptcolorcube(12))
Само изображение при этом не изменится, поменяется только оцифровка
координатных осей (рис. 7.22).
1.5
2
2:5
■а*
.э.6-""
\к.
А
л, **
'$*
,
1
. ■ i;. . -а.. .
-1
.
.feji,. i
-0.6
'h
D ■'
:.4
.i-
-0.5 '
.:■■
1
"V
..';■ .•■■<. ~
- 'l '"-1S
2
r-
:
2.5
Рис. 7.22. Смещение координат изображения
Иерархия графических объектов и их свойства
303
Вообще говоря, созданный нами графический объект действительно состоит
из 12 цветных точек, расположенных в 3 ряда. Однако при его отображении
произошло масштабирование под фактические размеры области осей, и
каждая точка превратилась в большой цветной прямоугольник.
Как правило, программы отображают рисунки, считываемые из графических
файлов. Познакомимся более подробно с технологией чтения и визуализации
изображения на примере летательного аппарата НАСА, которое хранится в
каталоге MALAB7\tooIbox\aeroblks\aerodemos под именем aeroblk_HL20pic.jpg.
Чтобы не возиться с таким длинным именем, скопируем его в рабочий
каталог \work под именем aero.jpg. Во-первых, получим информацию об этом
рисунке с помощью функции imfinfo (пример 7.20).
чПрймёр .20. Свойства фай а с изображением "..'... , "'.. L'\vW'
» imfinfo ('aero.jpg')
ans =
Filename: 'aero.jpg'
FileModDate: '28-Mar-2002 21:40:54'
FileSize: 17774
■Format: 'jpg'
FormatVefsion: ''
Width: 319
Height: 396
BitDepth: 24
ColorType: 'truecolor'
FormatSignature: '*
Comment: {}
Из полученной информации следует, что размер рисунка в пикселах —
319x396, и на код цветности каждого пиксела отведено 24 бита (по 8 битов
на каждую цветовую составляющую, и это соответствует формату
truecolor). Прочитаем содержимое указанного файла в массив а и создадим
на его базе графический объект типа image:
» A=imread('aero, jpg');
>>. h_rmg=±mage (A.) ;
Созданное изображение вписывается в размеры графического окна, которые
по умолчанию MATLAB устанавливает при отсутствии дополнительных
указаний. Из рис. 7.23 видно, что пропорции рисунка по осям хну
подверглись искажению.
304
Глава 7
Рис. 7.23. Изображение с нарушенными пропорциями
Для приведения в соответствие шагов по осям х и у достаточно выполнить
команду:
» axis image
Результат не замедлит сказаться. Действие команды axis image
эквивалентно установке свойства DataAspectRatio ДЛЯ объекта Axes В [1 1 1]. По
маркировке осей (рис. 7.24) видно, что шаги по осям стали одинаковыми.
Теперь не мешает привести размеры графического окна в соответствие с
пропорциями изображения:
» A=imread('aero.jpg');
>> [m n k]=size(A)
m =
396
n =
319
k =
3
Иерархия графических объектов и их свойства
305
» figure('Units',"pixels','Position',[100 100 n m])
» Image(A);
•> Figure 1
File ^^b^o&O^yi^m,^ ___^_
DSHanl^^^SiC'Dgl
-■-'"- -,- . ■■■'-.■ ■" -.--:
■%■■ 1 ..*•„-,**.. >«#-** ~J*
,£-:.£ iTS-ЧГ ^-1-1-- -'
^1&У*/&,-1& „ '. ■ ■■
T*" "; 5Q- '\ "
r-v Ю0 к
JW«4- '
..¾^ . '" • *• ~Ъ
"f^ W 150 ' ^¾ ■!
,-Л»- ,--200 ■.... ^
; ■
v- ^
^**N"V ■ "
,.#:k Set -«Г ■ --
J" 350^
.,.^ 'W4*
.., #¢.¾^.¾¾^
saostf - N> 5=^
.¾¾1 ,ii Л :'■ 50 ■ 100
4* f. %:
rap
"ii-.
M
Щ
$
?■
150
,.-.\"
Г--ь' ".*■ * :
*• ™ f .
/
'""-/
:- л i
--- "4.
л "'J.
. v
.4 %. "
Ж
W *
V
T
■ Jb,- ■
c; %
",-.%-4
- ?..-*■* ' ■
200 250 300
■ . a.
ВПП
--■■ . Л. . ,
■:■. " ,-' ■■-■ :.-..
1 " 4?;V
я s ■ >*,
'*\*$
" .•-r^v.f l
■' ■ i - й;>-
«^'^Г
Щ,
jKff.*
к-'
^:
~
Рис. 7.24. Изображение с восстановленными пропорциями
Результат работы этого фрагмента приведен на рис. 7.25.
И, наконец, последний штрих — расширение плошали осей на всю рабочую
область графического окна:
» set(дса,'Position',[0 0 1 1])
Последнее изображение, заполняющее поверхность графического окна,
приведено на рис. 7.26.
А теперь познакомимся более подробно с функциями, используемыми при
создании и визуализации изображений.
Функция imread применяется для считывания матрицы цветности
изображения из графических файлов разных форматов. Пример чтения
изображения типа truecolor мы уже продемонстрировали. Однако возможен и
несколько иной вариант чтения RGB-изображений:
» А = imread('aero','jpg')
306
Глава 7
•> Figure 2 НПО
File Edi Viev inset Tool Deskfc Wlndo Helf -»■
___ __. _.. ^.-^ ^ _ „ _^„__
,-^¾¾¾¾¾¾¾¾^^
50
S^
100. '.
200
250 ''
,,¾
300
350
к
_ :,.., .^
v. '
£■
■: '
,t ™
(Я
t
-Двгг^"'!
ч»*£
lit*
- tk
4-
V
1 ¥~
100
200
300
Рис. 7.25. Размер окна приведен
к размерам рисунка
»Л Figure 2
ИПП
Fife Edl Vlev Ipsa Ipol Desktc Wlndo Helf *
D &UB\ k |«.ein®i«J!D "
^.: ..-...-
.■■ ■* 1
|t «-V:
u,.
' - - A
a
* e-
i
1 *V
Рис. 7.26. Последний штрих
При считывании индексированного изображения функция imread
возвращает два параметра — массив индексов (х) и ассоциированную палитру
цветов (шар):
» [X,map]=imread{'name','fmt');
Второй аргумент в этом обращении задает расширение графического файла,
если оно в явном виде не указано в имени файла ('name"). Считанный таким
образом индексированный рисунок воспроизводится в поле осей
следующим образом:
» image(X);
» coiormap(map)
Функция coiormap (map) приписывает цветовую палитру текущему
графическому окну. Матрица тар может иметь сколько угодно строк, но в каждой из
них должны находиться только три вещественных числа из диапазона [о, \\.
Они воспринимаются как значения RGB-компонентов цвета,
соответствующие индексу строки матрицы reap. Обращение к функции coiormap без
параметров возвращает значения текущей палитры фафического окна. По
умолчанию каждое фафическое окно снабжается палитрой, унаследованной
от корневого объекта Root. Она содержит 64 строки с числовыми компонен-
Иерархия графических объектов и их свойства
307
тами, приведенными в табл. 7.5. Из этой таблицы становится понятно,
почему изображение, приведенное на рис. 7.21, до смены палитры появляется
в синих тонах. Первые 12 цветовых оттенков палитры по умолчанию
содержат преимущественно градации синего.
Таблица 7.5
№
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
R
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0,0625
; G
! о
! о
! о
I 0
| 0
I °
] 0
| о
I 0,0625
! 0,1250
| 0,1875
| 0,2500
| 0,3125
I 0,3750
! 0,4375
| 0,5000
| 0,5625
| 0,6250
| 0,6875
| 0,7500
| 0,8125
| 0,8750
| 0,9375
| 1,0000
| 1,0000
! В
| 0,5625
] 0,6250
I 0,6875
! 0,7500
| 0,8125
| 0,8750
| 0,9375
| 1,0000
| 1,0000
| 1,0000
! 1,0000
; 1,0000
! 1,оооо
I 1,0000
! 1,оооо
| 1,0000
| 1,0000
! 1,0000
; 1,0000
! 1,оооо
| 1,0000
I 1,0000
j 1,0000
! 1,0000
| 0,9375
№
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
! R
| 0.1250
) 0,1875
! 0,2500
| 0,3125
| 0,3750
I 0.4375
) 0,5000
| 0,5625
| 0.6250
| 0,6875
| 0,7500
| 0,8125
| 0,8750
I 0,9375
| 1,0000
| 1,0000
| 1,0000
| 1,0000
! 1,0000
I 1,0000
| 1,0000
| 1,0000
| 1,0000
| 1,0000
I 1,0000
! G
| 1,0000
| 1,0000
I 1,0000
| 1,0000
| 1,0000
I 1,0000
| 1,0000
I 1,0000
! 1,0000
| 1,0000
| 1,0000
| 1,0000
j 1,0000
| 1,0000
| 1,0000
I 0,9375
| 0,8750
| 0,8125
| 0,7500
! 0,6875
| 0,6250
| 0,5625
I 0,5000
j 0,4375
| 0,3750
\ в
| 0,8750
I 0,8125
| 0,7500
I 0,6875
| 0,6250
| 0,5625
I 0,5000
j 0,4375
! 0,3750
| 0,3125
| 0,2500
| 0,1875
! 0,1250
| 0,0625
j 0
| 0
! о
! о
! о
! °
| 0
I °
| 0
I °
! о
308
Глава 7
Таблица 7.5 (окончание)
№ ! R | G | В
51 I 1,0000 | 0,3125 | 0
52 | 1,0000 | 0,2500 | 0
53 | 1,0000 | 0,1875 | 0
54 | 1,0000 | 0,1250 j 0
55 j 1,0000 | 0,0625 ; 0
56 I 1,0000 | 0 | 0
57 | 0,9375 ; 0 ; 0
№ | R | G ! В
58 j 0,8750 ! 0 | 0
59 j 0,8125 | 0 JO
60 j 0,7500 ; 0 | 0
61 j 0,6875 JO ;0
62 j 0,6250 JO JO
63 ; 0,5625 | 0 ; 0
64 j 0,5000 JO JO
Аргументами функции image кроме матрицы цветности могут быть два
двухэлементных вектора х и у, которые подменяют диапазоны маркировки осей
изображения:
» image {х, у, С)
Нечто подобное мы уже демонстрировали в самом первом примере этого
раздела:
» image{X,'XData',[-1 2],'YData',[2 4]);
Таким же образом могут быть изменены и любые другие свойства при
создании объекта типа image:
» h_Img=image('свойство1',значение1,'свойстве^',значение2,...);
Список форматов графических файлов, содержимое которых может быть
извлечено с помощью функции imread, приведен в табл. 7.6. На самом деле
за каждым из этих форматов скрывается довольно много вариантов,
отличающихся глубиной палитры (т. е. количеством битов на код цветности
пиксела), использованием того или иного метода сжатия данных,
количеством изображений, закодированных в одном файле. Поэтому функция imread
допускает несколько частных форматов обращения для конкретных
графических файлов. Узнать об этих деталях вы сможете, обратившись за
справкой ПО функции imread.
Таблица 7.6
Формат Тип графического файла
' bmp' Windows Bitmap (BMP)
' cur' Windows Cursor resources (CUR)
' gif' Graphics Interchange Format (GIF)
' hdf' Hierarchical Data Format (HDF)
Иерархия графических объектов и их свойства
309
Таблица 7.6 (окончание)
Формат Тип графического файла
' ico' Windows Icon resources (ICO)
'jpg' I 'jpeg' Joint Photographic Experts Group (JPEG)
' pbm' Portable Bitmap (PBM)
' pcx' Windows Paintbrush (PCX)
' pgm' Portable Graymap (PGM)
' png' Portable Network Graphics (PNG)
' pnm' Portable Anymap (PNM) — обобщенное расширение одного
из форматов: Portable Bitmap (PBM), Portable Graymap (PGM)
и Portable Pixel Map (PPM)
' ppm' Portable Pixmap (PPM)
' ras' Sun Raster (RAS)
•tif | 'tiff Tagged Image File Format (TIFF)
' xwd ■ X Windows Dump (XWD)
В "прозрачности" пикселов изображения и связанных с ней свойствах
AlphaData и AlphaDataMapping нам поможет разобраться примитивная схема
считывания и визуализации значков. Для файлов с расширением ico
функция imread возвращает 3 аргумента:
[X,map,Alpha] =dmread( 'matlab.ico') ;
Как правило, значки представлены небольшими растровыми рисунками
размером 32x32 пиксела. Значки, расположенные на вашем рабочем столе,
далеко не всегда имеют форму квадрата. Это означает, что часть пикселов
рисунка обязана быть "прозрачной", из-под них должны просвечивать
пикселы того фона, на который накладывается изображение значка. Массив
Alpha, возвращаемый функцией imread, имеет такую же размерность, как и
индексный массив х, и состоит он из нулей и единиц. Единица,
расположенная в позиции (i, j) изображения значка, означает, что
соответствующий пиксел должен быть прозрачным. В примере считывания фирменного
значка MATLAB возвращаемые массивы имеют размерности, приведенные в
примере 7.21.
|Пример.:7.21. Изображение.с прозрачными областями^г^Х>^Ш'ь^^^л^с1^^
» size(X)
ans = .% размерность массива индексов
32 32
310
Глава 7
» size(map)
ans = % размерность палитры
256 3
» size(Alpha)
ans = % размерность матрицы "прозрачности"
32 32
Обратите внимание на тип возвращаемых данных:
» whos
Name Size Bytes Class
Alpha 32x32 1024 logical array
X 32x32 1024 uintS array
map 256x3 6144 double array
Из внешнего вида фирменного знака MATLAB следует, что левый верхний
пиксел квадрата, занятого рисунком, должен быть прозрачным. Об этом же
свидетельствует и значение элемента Alpha (i, i):
» Alpha(1,1)
ans =
1
Однако индекс этого пиксела и соответствующая тройка в палитре цветов
указывают на то, что эта точка — черная.
» Х(1,1)
ans =
0
>> mapd,:)
ans =
0 0 0
Поэтому, если построить объект типа image без каких-то дополнительных
ухищрений, то все пикселы изображения, не принадлежащие узору значка,
окажутся черными:
» h_Img=image (X); col.ormap (map)
Результат лобового подхода представлен на рис. 7.27.
А теперь попробуем модифицировать процесс создания объекта типа image
следующим образом. Во-первых, добавим к считанной палитре новую
строку с компонентами белого цвета:
» mapl = [map; 1 1 1];
Иерархия графических объектов и их свойства
311
Рис. 7.27. Отображение значка без учета признаков прозрачности
Во-вторых, создадим копию индексного массива, пока заполненную
ссылками на строку белого цвета:
>> XI = ones(size(X))*(length(mapl) - 1);
Теперь перепишем все индексы всех непрозрачных пикселов из массива х в
массив xi:
» XI(Alpha = 0} = X(Alpha = 0);
Наконец, построим объект типа image по сформированным данным, не
забыв предварительно преобразовать массив xi из типа double к типу uinte:
» image(uintS(XI)); GQlormdp(mapl)
Окончательный результат, представленный на рис. 7.28, свидетельствует о
том. что все прозрачные пикселы значка теперь окрашены в белый цвет.
С помощью немного более сложных манипуляций можно было бы вместо
белых точек проявлять цвет точек графического окна, на которые
накладываются прозрачные пикселы значка.
В самом общем случае матрица прозрачности AlphaData имеет такую же
размерносгь, как и матрица CData. Ее элементами могут быть либо
вещественные числа типа double, либо целые числа типа uinte. В зависимости от
значения свойства AlphaDataMapping элементы матрицы AlphaData
расшифровываются одним из трех способов:
П как коэффициенты прозрачности соответствующих пикселов
изображения (AlphaDataMapping=none);
11 Зак. 85S
312
Глава 7
П как индексы в текущем массиве Alphamap, приписанном графическому
окну (AlphaDataMapping=direct);
П как масштабирующие множители, с помощью которых вычисляются
коэффициенты прозрачности в диапазоне от минимального до
максимального значений, заданных СВОЙСТВОМ ALim (AlphaDataMapping=scaled).
-Г
е
10
15
20
25
30
•■
_ г
5
-ш-
:>
■у-
ч
1Г-" —
,?■
10 15.
1-й.
'
,7- 1 *' ■■'
Ч
ш.
■Г
.. 20 25 .-
■! .¾¾%
_
.-.J'
30
Рис. 7.28. Изменение цвета прозрачных пикселов
Функция imwrite, осуществляющая запись объекта типа image в графический
файл, может оказаться полезной для преобразования одного графического
формата в другой. Подобно функции imread, эта функция тоже допускает
несколько форматов обращения, из которых мы приведем только два:
imwrite(А,'пате','fmt') % запись изображения типа colormap
imwrite (X,map, 'name',' frht') % запись индексированного изображения
7.8. Поиск объектов
Обращение к функциям get и set для опроса или установки значений
отдельных свойств объектов требует знания указателя на соответствуюший
объект. Функции, создающие тот или иной графический объект, как
правило, возвращают значение указателя на созданный объект. Но что делать,
если мы забыли сохранить возвращаемое значение?
Иерархия графических объектов и их свойства
313
Для текущего графического окна (объекта типа Figure), текущего поля
графика (объекта типа Axes) и объекта, выбранного в данный момент
пользователем (объекта, генерирующего событие callback), можно воспользоваться
системными функциями gcf, gca и gcbo соответственно. Но если нужный
графический объект не принадлежит ни к одной из перечисленных
категорий, то восстановлению его указателя поможет функция findobj. Для
обращения к ней достаточно знать значение какого-либо свойства, характерного
для искомой фигуры.
Иногда перед обращением к функции findobj полезно узнать перечень
объектов, среди которых имеет смысл производить поиск. Для формирования
списка указателей объектов, порожденных графическим объектом с
известным указателем h_obj, следует обратиться к функции findaii (пример 7.22).
; Пример 7:22; Получение сНиека указателей на ■в^.объекгы^^-^'щк^ u \ ":& ^
» х=0:0.1:2*pi;
» plot(х,sin(х))
» h_All=findall{gca)
h_All =
101.0020
3.0016
По количеству возвращенных значений можно догадаться, что в текущем
поле графика созданы два графических объекта. Но что скрывается за
каждым из возвращенных значений, тем более, что указателями являются
вещественные числа, точные значения которых неизвестны? Попробуем
опросить тип каждого из объектов (пример 7.23).
|«nj>^R7>23;-9^^C-TMn^О^^в »*-^¾^^¾^¾^ -W; ^¾¾¾
>> get(h_All(l>,"Type')
ans =
axes
» get(h_All(2),'Type')
ans =
line
Теиерь-то мы можем воспользоваться функцией findobj:
» hl=findobj'( 'Type', 'axes')
hi =
101.0020
314
Глава 7
» h2=findobj('Type','line')
h2 =
3.0016
А поскольку значения указателей попали в переменные hi и п2, то можно в
полной мере воспользоваться услугами функций get или set.
Вообще, в приведенном выше примере мы могли бы сузить область поиска
и ограничиться единственным обращением к функции findobj:
» hl=findobj(gca,'Type','axes')
hi -
101.0020
Обращение к функции с единственным аргументом — указателем на
графический объект — выдает вектор указателей на все дочерние объекты:
» findobj(gca)
ans =
101.0020
3.0016
Если в области поиска находится несколько объектов с заданным значением
указанного свойства, то функция findobj возвращает вектор
соответствующих указателей. Однако если функция не находит ни одного объекта с
заданным свойством, то выдается сообщение об ошибке и возвращается
пустой вектор.
Глава 8
Проектирование интерфейса
Все Windows-приложения делятся на две категории — консольные и оконные.
Консольные приложения, которые могут быть созданы в большинстве
современных систем программирования (Visual C++, Borland C++ Builder
(ВСВ), Delphi и др.), напоминают программы, функционирующие под
управлением MS-DOS. В их распоряжении вся оперативная память и экран,
режим работы которого максимально приближен к текстовому. Ввод данных
консольного приложения может быть организован либо их чтением из
файла, либо путем их набора на клавиатуре.
В отличие от этого, оконные Windows-приложения включают одно или
несколько окон, одновременно расположенных на экране, которые могут
перемещаться, изменять свои размеры, пропадать и возникать вновь. Для
ввода и вывода данных оконные приложения предлагают своеобразные
"форточки" — редактируемые поля ввода/вывода символьной информации,
выделенные в окнах прямоугольные области для отображения фафической
информации. В окопных приложениях используется большой набор
типовых компонентов, обеспечивающих диалоговое взаимодействие с
пользователем — разнообразные кнопки, списки, индикаторы состояния различных
процессов, полосы прокрутки, рамки и т. п.
Система MATLAB тоже позволяет создавать оконные
Windows-приложения, в которых широко представлены средства управления отображением
2D- и ЗО-объектов. Наряду с этим, MATLAB предлагает довольно
скромный ассортимент компонентов, ориентированных на проектирование
графического интерфейса. Тем не менее все эти компоненты оформлены в
соответствии со стандартами Windows. Набор их свойств покрывает
основные функциональные возможности аналогичных компонентов,
предлагаемых современными системами визуального программирования.
Полный перечень интерфейсных компонентов MATLAB приведен в табл. 8.1.
Роль общепринятых форм — стандартных окон Windows. — в приложениях
MATLAB выполняют графические объекты типа Figure. Конечно, в таких
окнах не обязательно присутствие объекта, типа Axes, в котором строятся
графические изображения.
316
Глава 8
Таблица 8.1
Наименование
компонента
Назначение
Аналог в других системах
программирования
Push Button
Toggle Button
Radiobutton
Checkbox
Edit Text
Static Text
Slider
Panel
Button Group
Простая кнопка
Кнопка, фиксирующаяся
в утопленном состоянии
Переключатель —
индикатор альтернативных
вариантов
Окошко — индикатор не-
альтернативных вариантов
Поле для вывода, ввода
И редактирования текста
Область для вывода
текста (метка)
Ползунок, полоса
прокрутки
Рамка, контейнер для
интерфейсных компонентов
Рамка для кнопок типа
Radio Button И Toggle
Button
Visual Basic (VB) — CommandButton
BCB, Delphi — Button
Visual C++ — Push Button
BCB, Delphi — SpeedButton
VB —Option Box
BCB, Delphi —RadioButton
Visual C++— Radio Button
VB — CheckBox
BCB, Delphi — CheckBox
Visual C++ — Check Box
VB — TextBox
BCB, Delphi - Edit
Visual C++ — Edit Box
VB — Label
BCB, Delphi — Label, Static-Text
Visual C++ — Static Text
VB - HScrollBar, VScrollBar
BCB, Delphi - ScrollBar
Visual C++ — Horizontal или
Vertical Scroll Bar
VB — Frame
BCB, Delphi — Frame, Panel, Group
Box
Visual C++ — нет аналога
VB — Frame
BCB, Delphi — Radio Group, Group
Box
Visual C++ — нет аналога
Проектирование интерфейса
317
Таблица 8.1 (окончание)
Наименование Назначение
компонента
Аналог в других системах
программирования
Listbox
Список, окно для
отображения массива строк
Popup Menu Всплывающее меню
VB - ListBox
ВСВ, Delphi — ListBox
Visual C++ — List Box
VB —Menu Editor
BCB, Delphi — PopMenu
Visual C++ — Menu
Каждый интерфейсный элемент обладает заданным набором свойств,
определяющих внешний вид и поведение компонента на стадии выполнения
программы. Если большинство современных систем визуального
программирования закрепляет за компонентами каждого класса индивидуальный
набор свойств, то в пакете MATLAB любому интерфейсному элементу
всегда приписано 41 свойство (табл. 8.2). Однако некоторые из них имеют
смысл только для определенных элементов. Так, например, свойство
ListBoxTop, определяющее индекс отображаемого элемента списка, для
объекта типа Listbox представляет интерес, а для других интерфейсных
элементов ничего не значит. Точно так же свойством, ориентированным только
на обслуживание объектов типа slider, является минимальный и
максимальный шаг перемещения ползунка при щелчках мышью (вектор значений
свойства siiderstep). Свойства некоторых компонентов в пакете MATLAB
трактуются не совсем обычно. Например, у выделенной кнопки типа Radio
Button значение свойства value устанавливается в 1, а у невыделенной — в 0.
Более подробно специфика использования каждого из интерфейсных
компонентов и их свойств рассматривается ниже.
Таблица 8.2
Свойство
Назначение
Допустимые значения
BackgroundColor
BeingDeleted
BusyAction
Цвет фона (по умолчанию —
серый [0.753 0.753 0.753])
Признак возможности удаления
(по умолчанию — off)
Реакция на возникновение
нового прерывания во время
обработки текущего события (по
умолчанию — queue)
Вектор, задающий
значения RGB-компонентов из
диапазона от 0 до 1
on (разрешено),
off (запрещено)
queue
(поставить в очередь),
cancel (проигнорировать)
318
Глава 8
Таблица 8.2 (продолжение)
Свойство
Назначение
Допустимые значения
ButtonDownFcn
Cdata
Callback
Children
Clipping
CreateFcn
DeleteFcn
Enable
Extent
Font'Angle
FontName
FontSize
FontUnits
FontWeight
Указатель на функцию обработки
события "Нажатие правой кнопки
мыши"
Массив для хранения
изображения в формате truecolor,
которое "наклеивается" на
поверхность объекта
Указатель на функцию —
обработчик события Callback
Массив указателей на потомков
Признак отсечения при выходе
изображения за границы объекта
(по умолчанию — on)
Указатель на функцию обработки
события "Создание объекта"
Указатель на функцию обработки
события "Удаление объекта"
Признак доступа к объекту (по
умолчанию — on)
Габаритный прямоугольник
Признак наклона букв (по
умолчанию — normal)
Имя шрифта (по умолчанию — MS
Sans Serif)
Размер (высота) букв в
установленных единицах (по
умолчанию — 8 пунктов)
Единицы измерения (по
умолчанию-points)
Толщина контура букв (по
умолчанию — normal)
on (включено),
off (отключено)
on (доступ разрешен),
off (доступ запрещен)
normal (прямой шрифт),
italic (курсив),
oblicue (наклонный)
Список имен шрифтов,
установленных в Windows
inches (дюймы),
centimeters
(сантиметры),
normalized,
pixels (пикселы),
points (пункты,
1 пункт = 1/72 дюйма)
normal (нормальная),
light (утонченная),
derai (полужирная),
bold (жирная)
Проектирование интерфейса
319
Таблица 8.2 (продолжение)
Свойство
Назначение
Допустимые значения
ForegroundColor
Handle
Visibility
HitTest
Horizontal
Alignment
Interruptible
KeyPressFcn
ListBoxTop
Max
Min
Parent
Position
Selected
Selection-
Highlight
Цвет рисования (по умолчанию -
черный= [0.0 0.0 0.0])
Признак видимости указателя
обработчика событий (по
умолчанию — on)
Признак разрешения поиска
объекта по значению свойства
(по умолчанию — on)
Способ размещения надписи в
поле объекта (по умолчанию —
center)
Признак разрешения прервать
обработчик события (по
умолчанию — on)
Указатель на функцию обработки
события "Нажата клавиша" в тот
момент, когда компонент
находился в фокусе
Индекс строки
разворачивающегося списка, которая отображена
в верхнем окне (по умолчанию— о)
Максимальное значение
свойства Value (по умолчанию — Д.)
Минимальное значение свойства
Value (по умолчанию — 0)
Указатель на родительский
объект
Позиция объекта — вектор,
определяющий координаты нижнего
левого угла объекта, его ширину
и высоту в установленных
единицах измерения
Признак выбора объекта
Признак повышенной яркости
для выделения того или иного
элемента в объекте (по
умолчанию — on)
Вектор значений RGB-
компонентов
on (доступен),
off (не доступен)
on (поиск разрешен),
off (поиск запрещен)
left (левый прижим),
right (правый прижим),
center (по центру)
on (прерывание
разрешено),
off (прерывание
запрещено)
on (выбран),
of f (не выбран)
on (включен),
off (выключен)
320
Глава 8
Таблица 8.2 (окончание)
Свойство
Назначение
Допустимые значения
SliderStep
String
Style
Tag
TooItipString
Type
UIContextMenu
Units
UserData
Value
Visible
Вектор малых и больших
перемещений ползунка
Символьная строка, задающая
надпись или значение,
приписанное объекту
Символьная строка с типом
компонента (например, pushbutton,
slider и др.)
Символьная строка, в которой,
как правило, хранится имя
объекта (например, pushbuttonl,
pushb.utton2 и Др.)
Текст всплывающей подсказки
(по умолчанию — пустая строка)
Класс объекта
Всплывающее меню,
привязанное к данному объекту
Единицы измерения линейных
величин (ширины, высоты, длины
и т. п.). Для объектов разного
типа по умолчанию может быть
разным
Массив данных,
ассоциированный пользователем с этим
объектом (по умолчанию — пустой
массив)
Значение, характерное для
данного объекта (например,
величина смещения ползунка)
Признак видимости объекта (по
умолчанию — on)
inches (дюймы),
centimeters
(сантиметры),
normalized,
pixels (пикселы),
points (пункты)
on (объект виден),
off (объект невидим)
Из состава компонентов в версии 7.0 исключена рамка Frame, которая
заменена эквивалентным интерфейсным элементом Panel. Компоненты,
размещенные на панели, считаются ее дочерними элементами и перемешаются
вместе с панелью. По сравнению с рамкой Frame панель имеет немного
меньше свойств, ио у нее появилась возможность изменять форму и ширину
своих границ (свойства вогаегтуре и Borderwidth), а также местоположение
Проектирование интерфейса
321
надписи (свойство Tideposition). На рис. 8.1 и 8.2 отображены
возможности по управлению этими свойствами.
попе
-beveledin-
-etchedin-
etchedout-
"' beveledout
line' '■*
Рис. 8.1. Управление формой границ панели
V iBfttop
., centertop '''-
righttop
iBftbottom
centerbottom
rightbottom
TitlePosition
none
** etchedin
etchetiout
beveledin
' "beveledout
line
BorderType
Рис. 8.2. Варианты размещения подписи на панели
8.1. Динамическое создание
интерфейсных элементов
В системе MATLAB предусмотрены два способа организации интерфейса с
пользователем. Первый из них условно назовем динамическим. Он
заключается в том, что на стадии выполнения программы создаются те или иные
графические объекты и их свойствам присваиваются соответствующие
значения. Для создания любого интерфейсного компонента с заданными
свойствами используется функция uicontroi, возвращающая указатель на
формируемый компонент:
hUIC = uicontroi([hFig,] 'Style','тип_компонента',...
1Свойство_1',Значение_1,...
'Свойство 2',Значение 2,...
'Свойство к'. Значение к);
322
Глава 8
Первый аргумент функции uicontroi не является обязательным, и если он
отсутствует, то родителем (владельцем) создаваемого компонента является
текущий графический объект.
У существующего интерфейсного объекта можно изменить те или иные
свойства с помощью функции set:
set(UIC,'Свойство_1',Значение_1,...
'Свойство_2',Значение_2,...
'Свойство_к',Значение_к)
Поясним сказанное на примере решения квадратного уравнения
a ■ х2 + b ■ х + с = 0. Предположим, что нам хотелось бы видеть на форме
главного приложения три окна для ввода коэффициентов уравнения, два
окна для отображения значений найденных корней и кнопку для запуска
алгоритма вычисления корней после ввода очередных значений
коэффициентов (пример 8.1). В этом приложении очень полезным оказалось бы окно,
воспроизводящее график функции у = a • х2 + b ■ х + с и визуально
подтверждающее расположение найденных корней. Для контроля работы нашего
будущего приложения предварительно проделаем все вычисления в командном
окне. Набор коэффициентов (а, ь, с) целесообразно оформить в виде вектора,
который понадобится как для вызова функции roots, вычисляющей корни
полинома, так и для функции poiyval, вычисляющей значение полинома в
заданной точке. Если результаты вычислений, выведенные по формату short,
нам покажутся не очень удовлетворительными, то можно воспользоваться
форматом long, чтобы увидеть значения корней и полинома с более высокой
точностью.
i Пример 8.1. Поиск решения квадратного уравнения '-
г<: .••'. '. Л :; :...;. :.'....v.'.
» а=1.5;
» Ь=-2.4;
» с=0.75;
» р=[а b с];
» x=roots(р)
X =
1.1742
р. 425.8
» poiyval(р,1.1742)
Проектирование интерфейса
323
ans =
3.8460е-005
» polyval(p,0.4258)
ans =
3.8460е-005
» format long
» x
X =
1.17416573867739
0.42583426132261
»polyval(p, 1.17416573867739)
ar.s =
-4.329869796038111e-015
» polyvalfp, 0.42583426132261)
ans =
-4.551914400963142e-015
•> Figure 1
File Edit View Insert Tools Desktop Window Help
ВПЕЗ
0.8
0.6
0.4
о.:2
о
-0.2
п
iJ <'
\
л
1
!
\
\ j
\ 1
\ 1
\1
1
и
•/
?
/;
71
j
/ ;
i
05
1:5
Рис. 8.3. График функции у = а-х2 + Ь-х + с
324
Глава 8
Теперь построим график нашей функции, положив в качестве граничных
интервалов по оси X значения xmin=jnin(real(x(l)), real(х(2)))-0.5 И
xmax=max[real(х(1)), real[х (2)))+0.5:
» xrl=real{x(l));
» xr2=real(x(2));
» xmin=rrdn(xrl,xr2)-0.5,-
» xmax=max(xrl,xr2)+0.5;
» xx=xmin:0.1:xmax;
» yy=polyval(p,xx);
» plot(xx,yy)
» grid on
Окно приложения с графиком нашей функции приведено на рис. 8.3.
Любые попытки расширить созданное окно, чтобы освободить пространство
для предполагаемых полей ввода и кнопки, ни к чему не приведут. При
изменении размеров фигуры график функции автоматически подстраивается
под новые габариты.
Поэтому придется принудительно задавать параметры окна, поля графика и
всех интерфейсных компонентов на стадии выполнения программы.
Предварительный дизайн формы можно провести на миллиметровке и не забыть
после этого перевести миллиметры в пикселы (коэффициент пересчета для
разных мониторов и установленного разрешения может оказаться разным).
Числовые данные, которыми мы воспользовались для построения макета
формы (рис. 8.4), хранятся в файле roots2.m (пример 8.2).
Пример 8;2> Функция\х£бЬё?ЩЩг ' '••Ш^^ФЩк f - : • ".- " Щ
h.....i ?....\v..v#..w.vi.,..:.....!T...i. . ..' .-.1 ,.....*.... .n.v.' л"..* . ... . ...... . ,t\.t.t ,V.-;.i . ni.'lh'u i :.'л . . i. .1 . .....v ..>... it -Gil . ...:}
function roots2
% глобальные переменные
global hFig hAxes hBtn
global hTxta hTxtb hTxtc hTxtxl hTxtx2
global hEda hEdb hEdc hEdxl hEdx2
hfig=figure('Position',150,50,480,300]) ;
hAxes=axes;
set(hAxes,'Unit','pixels','Position',[30,70,280,220])
hTxta=uicontrol(hFig,'Style','text','String','a=',...
•Position',[340,253,30,21],'BackgroundColor',[1 1 1]);
hTxtb=uicontrol{hFig,'Style','text','String■,'b= *,...
•Position',[340,218,30,211,'BackgroundColor',[1 1 1]);
Проектирование интерфейса
325
hTxtc=uicontrol(hFig,'Style','text','String','c=', . . .
'Position',[340,188,30,21],'BackgroundColor',[1 11]);
hTxtxl=uicontrol(hFig,'Style','text','string','xl=',...
'Position',[340,113,30,21],'BackgroundColor',[1 1 1]) ;
hTxtx2=uicontrol(hFig,'Style','text','String','x2=',...
'Position', [340,78,30,21], 'BackgroundColor', [1 1 1].) ;
hEda=uicontrol(hFig,'Style','edit','Position',[380,250,100,25],
'BackgroundColor',[1 1 1],'HorizontalAlignment','left')
hEdb=uicontrol(hFig,'Style','edit','Position', [380,215,100,25],
•BackgroundColor',[1 1 1],'HorizontalAlignment','left'>
hEdc=uicontrol(hFig,'Style','edit','Position',[380,185,100,25],
'BackgroundColor',[1 1 1],'HorizontalAlignment','left')
hEdxl=uicontrol(hFig,'Style','edit','Position', [380,110,100
'BackgroundColor',[1 1 1],'HorizontalAlignment','left')
hEdx2=uicontrol(hFig,'Style','edit','Position', [380,75,100,25],
'BackgroundColor',[1 1 1],'HorizontalAlignment','left')
hBtn=uicontrol(hFig,'Style','pushbutton','String','Решение',
•Position',[340,150,140,25],'Callback','roots3');
25],
•> Figure 1 НПО
File Edit View Insert jrools Desktep Window 'Helpjf
...
0.8-
.0.6
0.4
0.2'
0
■!_-■= ЗД5- -■..
& *°
-¾
b=
<; c=
i .-*K»v
№ ■
■■•
■$-• Xl=
Ui.
■V* x2=
]ит,- с* ■' * ;:. ■
1
г •*.
1
|
,КС№Й£Ч-
Решение |
|
1
■0.2 0:4 0.6: 0.8
Рис. 8.4. Эскиз окна предполагаемого приложения
Прокомментируем содержимое файла roots2.m. Глобальные переменные,
описанные в строках 3—5, предназначены для хранения указателей на
динамически создаваемые объекты:
П hFig — указатель на графическое окно;
П hAxes — указатель на поле графика;
326
Глава 8
П hBtn — указатель на кнопку Решение;
П hTxta — указатель на метку а=;
П hTxtb — указатель на метку Ь=;
П hTxtc — указатель на метку с=;
П hTxtxi — указатель на метку xl=;
П hTxtx2 — указатель на метку х2=;
□ hEda — указатель на поле ввода значения а:
П hEdb — указатель на поле ввода значения ь;
П hEdc — указатель на поле ввода значения с;
П hEdxi — указатель на ноле вывода значения xi;
П hEdx2 — указатель на поле вывода значения х2;
Вообще говоря, некоторые из этих указателей можно было бы исключить из
списка глобальных переменных. Например, метки, представленные
объектами гипа static Text, после своего появления на форме изменяться не
будут, и их указатели больше никому не потребуются.
Создавая форму нашего приложения с помощью функции figure, мы
задаем координаты ее нижнего левого угла в пикселах (50, 50), ширину (480) и
высоту (300). Эта четверка образует вектор, представляющий значение
свойства position. Не забывайте, что начало системы координат расположено в
нижнем левом углу экрана, и направление координатных осей совпадает с
общепринятым. Указатель на созданную фигуру запоминается в переменной
hFig и может быть использован при размещении па форме других
графических объектов.
Создание поля графика (объект класса Axes) пришлось выполнить в два
этапа. Сначала с помощью функции axes было построено поле графика с
автоматическим выбором его размеров и положения в графическом окне.
А на втором шаге с помощью функции set пришлось изменить значение
свойства units. По умолчанию для осей устанавливается режим normalized,
при котором нижний левый угол рабочего поля графического окна
соответствует точке (0, 0), а правый верхний — точке (1, I). В этих единицах
довольно сложно подобрать нужные размеры поля графика (нам это удалось с
пятой попытки— [0.1 0.25 о.5Ь 0.68]). Размеры в миллиметрах гораздо
удобнее переводить в пикселы, что было и сделано с помощью второй пары
аргументов функции set. Указатель поля графика hAxes понадобится в
дальнейшем при построении графика- пашей функции. Маркировка осей
выполнена по умолчанию, однако после построения конкретного графика
эти числовые значения изменятся.
Все интерфейсные компоненты создаются с помощью функции uicor-troi,
которой передаются указатель на "владельца" (hFig) и тип создаваемого эле-
Проектирование интерфейса
327
мента (значение свойства style). Заметим, что только что созданное
графическое окно является текущей фигурой, поэтому в функциях uicontrol
первый параметр можно было бы опустить. По умолчанию владельцем
создаваемых компонентов является текущая фигура. Для объектов класса static
Text (статический, т. е. неизменяемый текст) кроме параметров положения
и единиц их измерения задается значение свойства string — текст, который
появится в поле метки. Объект класса Push Button тоже снабжается
надписью, располагаемой- на кнопке. Для объектов класса Edit Text
(редактируемый текст) свойство string по умолчанию представлено пустой строкой,
а значение left у свойства HorizontaiAiignment прижимает набираемое
значение к левой границе. Все интерфейсные элементы лучше смотрятся,
если их фоновый цвет — белый (значение свойства Backgroundcolor).
С кнопкой Решение ассоциирован обработчик событий (callback-функция),
представленный файлом roots3.ni. Текст этой функции приведен в
примере 8.3. Строки функции пронумерованы только с целью комментария.
1. function roots3
2. global hAx.es
3. global hEda hEdb hEdc hEdxl hEdx2
4. axes(hAxes);
5. cla;
6. str=get(hEda,'String');
7. a=str2num(str);
8. str=get(hEdb,'String'>;
9. b=str2num(str);
10. str-get(hEdc,'String');
11. c=str2hum.(str) ;
12. p=[a b c];
13. x=roots(p)
14. xrl=real(x(l));
15. xr2=real(x(2));
16. xmin=niin(xrl,xr2) -0.5;
17. xmax=max(xrl,xr2)+0.5;
18. xx=xmin:0.l:xmax;
19. yy=polyval{p,xx);
20. plot(xx,yy)
21. grid on
22. set(hEdxl,'String',num2str(x(1))>;
23. set(hEdx2,'String',num2str(x(2))>;
328
Глава 8
9ftdi*v. "> ^/^ [-П;'ЩЬЩ^ШШ§Ш^*:^ -ЛИЛ]
File Edit Text Cell tools Debug Desktop Window Help ■■ - • * j к .x
1
2
3-
4 -
5-
6-
T -
8 -
9 -
ID
11-
12
13 -
14
15 -
16
•> Figure 1
V
a=
b=
-2 4
function cootsZ
i i-.7[QO,3jjt,i-:..« c<bp-.7i«;[ p||e Edi V[ew Insert Too(s [-jg^top W|ndow He[p
global hfxg hAxes hB -- --- - ~ - = ~* ~ —--
tllobdl hTxta hTxtb h
global hEda hEdb hEd
hFig=figure (" Fes it ю ■■'"
hAxes=axes; 05
set (hAxes, ' 'Jn.Lt. ', *pi
hTxta=uiconteol(hFig
'Position', [340, о
hTxtb=uicontcol(hFig - ■
•posiLion',[340, ■.
hTxtc=u icont со 1 (hF ig
'Eos L>.ion', [340,
hTxtxl=uicontrol(hFi
"Position*, [340,
НПО
051—
'-0j5
/
к„,г
0.75
Решение
y1= \\.\7A2
*2=. Ic.42583
0,5
1..5
Рис. 8.5. Решение квадратного уравнения
После набора значений коэффициентов а, Ь, с в редактируемых полях ввода
и щелчка по кнопке Решение возникает событие, для обработки которого
автоматически вызывается Callback-функция root3.m. Для страховки
четвертой строкой активизируется окно графика, на которое смотрит указатель
hAxes. В нашем приложении такое окно единственное, поэтому именно оно
и является текущим, следовательно, в обращении к функции axes особой
нужды нет. В пятой строке производится очистка текущего поля графика.
Затем в строках 6—11 выполняется считывание содержимого тестовых окон
и преобразование извлеченных строк в числовой формат. Строки 12—21
повторяют вычислительную схему, апробированную нами в командном окне.
Найденные значения корней преобразуются из числового формата в
символьный вид и заносятся в соответствующие окна вывода. Результат работы
нашего приложения, представленного файлами roots2.ni и roots3.m,
приведен на рис. 8.5.
8.1.1. Командная кнопка
Командная кнопка типа push Button создается с помощью функции
uicontroi, в которой параметру 'style' приписано значение 'pushbutton'.
По умолчанию она не снабжается никакой надписью, имеет серый цвет и
располагается в левом нижнем углу фигуры (рис. 8.6).
Всем ее свойствам, кроме указанной характеристики 'style', присвоены
значения по умолчанию, в чем можно убедиться, обратившись к функции get
(пример 8.4).
Проектирование интерфейса
329
Рис. 8.6. Создание простейшей командной кнопки
| Пример£4. Свойства команднойкнопки -..'i^.r ■ „ ' ■ .** V". V :.'"и
» get(hBtn)
» BackgroundCblor = [0.831373 0.815686 0.784314]
Callback =
CData = []
Enable = on
Extent = [0 0 4 4]
FontAngle = normal
FontName = MS Sans Serif
FontSize = [8]
FontUnits = points
FontWeight = normal
ForegroundColor = [0 0 0]
HorizontalAlignment = center
KeyPressFcn =
ListboxTop = [0]
Max = [1]
Min = [0]
Position = [20 20 60 20]
String =
Style = pushbutton
SliderStep = [0.01 0.1]
TooltipString =
Units = pixels
Value = [0]
BeingDeleted = off
.330
Глава 8
ButtonDownFcn =
Children = []
Clipping = on
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVi.sibility = on
HitTest = on
Interruptible = on
Parent = [1]
Selected = off
SelectionHighlight = on
Tag =
Type = uicontrol
UIContextMenu = []
UserData = []
Visible = on
Несмотря на свою безликость (отсутствие надписи и собственного имени)
созданная кнопка умеет утапливаться при щелчке левой кнопкой мыши в
тот момент, когда ее курсор находится над поверхностью кнопки. Именно
эта акция вызывает появление события callback для кнопки, однако в
нашем приложении не была предусмотрена ответная реакция (указатель
Callback "смотрит" в никуда).
Попробуем модифицировать процедуру создания кнопки, задав
дополнительно значения некоторых свойств (рис. 8.7).
function pushbtn
hfig=figuceС Position', [200,200,300,100]) ;
tiBtn=uicontrol('Sty.lir:', 'pushbutton1, ...
1 st ring','кнопка I');
♦> Figure 1 НПП
File Edit View Insert fools Desktop Window Help »
Кнопка 1
Рис. 8.7. Кнопка с надписью (Strings ' Кнопка 1')
Проектирование интерфейса
331
Теперь при щелчке на кнопке вокруг ее надписи появляется пунктирный
прямоугольник, свидетельствующий о том, что кнопка "находится в фокусе".
Щелчок за пределами поверхности кнопки выведет ее из фокуса, и
пунктирная рамка пропадет.
Добавим еще одну кнопку, сместив ее на 80 пикселов вправо (рис. 8.8).
function pushbtn
hfig=figureГ Position",[200,200,300,100]);
hBtnl=uicontrol('style','pushbutton',...
'St ring', *Кнопка 1') ;
hBtn2=uicontrol('Style','pushbutton', ...
'St ring','Кнопка 2 ', ...
'Position',[100,20,60,20]);
-> Figure 2 НПО
File Edit View Insert Tools Desktop Window. Help ■».
■>-., v*~ "' '' *'*? l^ifeK^^Jife^
■■."- »-~№Й7 "йЗрчй^'
Кнопка 21 " : -■". Гт.Д:
Рис. 8.8. Две кнопки на форме
Позицию второй кнопки мы сформировали по позиции первой, которая
была привязана левым нижним углом к точке с координатами (20, 20),
имела ширину 60 и высоту 20 пикселов. Теперь щелчки на любой из кнопок
создают пунктирную рамку вокруг надписи выбранного элемента. Передача
фокуса от одной кнопки к другой возможна и путем нажатия клавиши
<ТаЬ> (или комбинации клавиш <Shift>+<Tab>).
Однако главным назначением командной кнопки является вызов
процедуры, реагирующей на соответствующее событие Callback. Поэтому нашим
следующим шагом станет создание m-файла, который будет вызываться
системой автоматически в случае щелчка по той или иной кнопке. Назовем эту
функцию pushbtni и возложим на нее обязанности реагировать на щелчок
по первой или второй кнопке. Например, пусть в случае щелчка по кнопке
I на ней появляется надпись Нажата 1, а на кнопке 2 восстанавливается ее
начальный заголовок. А в случае щелчка по кнопке 2 на ней появляется
надпись Нажата 2 и восстанавливается начальный заголовок на кнопке 1.
Для упрощения процедуры анализа, по какой из кнопок произошел щелчок,
объявим указатели hBtni и hB.tn2 глобальными и при попадании в
обработчик события callback проверим указатель объекта — инициатора события.
Значение последнего опрашивается с помощью функции gcbo (пример 8.$).
332
Глава 8
function pushbtn
% Головная программа, создающая форму с двумя кнопками
global hBtnl hBtn2
hf ig=f igure (' Position', [200,200,.300,100]);
hBtnl=uicontrol('Style','pushbutton', ...
'String','Кнопка 1',...
'Position',[10,20,70,25],...
'Callback','pushbtnl');
hBtn2=uicontrol('Style','pushbutton',...
'String','Кнопка 2',...
' Position', [100,20, 70, 25.]
'Callback','pushbtnl');
end
function pushbtnl
% Обработчик события Callback для обеих кнопок
global hBtnl hBtn2
set(hBtnl,'String','Кнопка 1')
set(hBtn2,'String','Кнопка 2')
if gcbo=hBtnl
set(hBtnl,'String','Нажата 1")
end
if gcbo=hBtn2
set(hBtn2,'String','Нажата 2')
end
После запуска головной программы pushbtn появляется форма с двумя
кнопками, щелчки по которым вызывают описанную смену заголовков
(рис. 8.9).
( Замечание J
Если обработчик события callback вынесен в отдельный m-файл, то
приведенный выше пример работает правильно. У этого решения есть свои плюсы
и минусы. К автономному обработчику событий могут обращаться разные
функции, но выделение его в отдельный файл ведет к увеличению общего
числа файлов в составе приложения. Однако обработчик pushbtnl может
быть включен в число подфункций файла pushbtn.т. Для этого функция
pushbtn вместо необязательного оператора end должна заканчиваться опера-
Проектирование интерфейса
333
тором waitfor (hfig). функция waitfor (hf ig) ожидает события "Уничтожение
объекта" с указателем hf ig. Поэтому выход из файла pushbtn задерживается,
и функция pushbtnl имеет доступ к рабочему пространству головной функции,
т. е. к глобальным переменным hBtnl и hatn2. Без такой задержки callback-
события происходят после выхода из файла pushbtn и указанные переменные
в глобальном рабочем пространстве уже не видны.
•> Figure 1
File,' Edit View
" H' -
Insert
Кнопка 1 | |Нажатз2|
. i«»A«-i . . -
*-■
Tools
7.3£ -
4--
Desktop
:»i ;>'-;
Window..
ипп
Help
Рис. 8.9. Кнопки, реагирующие на события
Кнопка, как и любой другой интерфейсный компонент, может быть
снабжена всплывающей подсказкой, текст которой задается в свойстве
TooltipString (рис. 8.10).
function pushbtn
global hBtnl hBtn2
hfig=figuce(,Posit.Lori,# [200,200,300,120]) ;
hBtnl=uicontcol('Style','pushbutton',...
'String *,'Кнопка 1',.. .
•Position',[10,20,70,25], ...
•Callback*, 'pashbtnl') ;
set(hBtnl,'ToolcipStcing','Командная кнопка');
-/Figure 1 ЯОЕЗ
File Edit View Insert Tools Desktop Window Help ■»
j.:'- .--¾¾¾^¾. л-- •%•:-
.-- 4ff^r "' r-b
Кнопка 1 I Кнопка 2. |
■■'-'- (Командная кнопка| ■ ---1
Рис. 8.10. Всплывающая подсказка у командной кнопки
В отличие от большинства визуальных сред, где цвет командных кнопок
остается неизменным, MATLAB позволяет окрасить поверхность кнопки в
любой цвет и использовать любой цветовой оттенок для символов надписи.
Для этого достаточно задать нужные значения свойств BackgroimdCoior и
334
Глава 8
Foregroundcoior (пример 8.6). Ими могут быть символьные константы,
определяющие наиболее используемые цвета, или трехкомпонентные
векторы, устанавливающие интенсивности RGB-составляющих.
™гч; ■?;."" w v.".-" ■; v^;;----™^-^:---.--.:--.-.- ■ •» -,- ;-.- :-.ут -
\. Призер,6,6. Разноцветные ^оманднмв кнопки .¾¾.. . я . и у, *-,". /-LJ-. f ,;
hBtnl=uicontrol('Style','pushbutton',...
'String','Кнопка 1',...
•Callback",'pushbtnl');
setfhBtnl,'BackgreundColor',[0 1 0],...
'ForegroundColor', 'Red') ;
В приведенном выше примере будет создана зеленая кнопка с красной
надписью. Аналогичную раскраску допускают и некоторые другие
интерфейсные компоненты.
Событие callback не является единственным событием, которое может
быть связано с командной кнопкой. Второе по значимости событие,
ассоциируемое со свойством ButtonDownFcn, возникает в одной из следующих
ситуаций:
П происходит щелчок левой или правой кнопкой мыши в тот момент,
когда острие курсора находится снаружи контура в пределах 5-пиксельной
зоны кнопки;
□ происходит щелчок правой кнопкой в тот момент, когда острие курсора
мыши находится внутри контура кнопки.
Событие ButtonDownFcn не вызывает каких-либо изменений во внешнем
виде кнопки, она не утапливается, как это происходит в случае основного
события callback. Более того, обработчик события Callback можно
заблокировать, установив свойство Enable в состояние off (доступ запрещен) или
inactive (кнопка не активна). Обработчик события ButtonDownFcn в любом
из этих случаев все равно будет автоматически вызван, и этим можно
воспользоваться, например, для изменения размеров или положения кнопки.
В большинстве визуальных сред подобным образом осуществляют
буксировку компонентов (технология drag & drop).
Существуют еще два события, характерные для всех интерфейсных
элементов, возникающие в момент создания и уничтожения объекта. На первое из
них реагирует функция, на которую "смотрит" указатель createFcn. Это
событие возникает непосредственно вслед за созданием компонента, так что
его обработчик может воспользоваться свойствами появившегося объекта
Функция — обработчик события DeieteFcn получает управление
непосредственно перед удалением объекта и еще может использовать в своей работе
значения свойств уничтожаемого компонента.
Проектирование интерфейса 335
8.1.2. Кнопка,
фиксирующаяся в утопленном состоянии
Кнопка типа Toggle Button отличается от командной кнопки тем, что
фиксируется в утопленном состоянии после первого щелчка и возвращается в
начальное состояние после следующего щелчка. Такие кнопки, как правило,
используются на панелях инструментов или в палитрах компонентов.
Вместо надписи на них обычно размещают небольшие изображения, которые
могут изменяться в зависимости от состояния кнопки.
Продемонстрируем эту возможность на примере кнопки с изображением
увеличительного стекла (стандартная операция Zoom (Масштаб) в
большинстве графических систем). Рисунок для этой кнопки был сделан с помощью
редактора Paint по следующей схеме. После запуска редактора была нажата
клавиша <Print Screen> для запоминания среды редактора в буфере обмена.
Затем содержимое буфера обмена было извлечено по команде Правка |
Вставить (Edit | Paste), изображение соответствующей кнопки было
вырезано и сохранено в формате 24-разрядного рисунка с расширением bmp (файл
zoom.bmp).
С помощью функции tbutton формируется графическое окно с двумя
фиксирующимися кнопками. Содержимое файла с изображением лупы считы-
вается в массив, а с помощью функции imread и загружается в свойство
cData обеих кнопок (пример 8.7). На рис. 8.11 показана форма приложения,
на которой одна из кнопок зафиксирована в утопленном состоянии.
| Призер 817. функция tbatton. ^¾¾¾¾¾^ '»'J?1 "J ' "" '.' ' ■••
function tbutton
hFig=figure<'Position',[50,50,300,100]);
hTBtnl=uicontrol('Style','togglebutton',...
'Position',[50,50,30,30]);
a=imread('zoom.bmp','bmp');
set(hTBtnl,'CData', a);
hTBtn2=uicontrol('Style','togglebutton*,...
'Position',[62,50,30,30]);
set (hTBtr_2, ' CData', a) ;
Для того чтобы в обработчиках событий разобраться, в каком состоянии
находится кнопка, необходимо проанализировать значение свойства Value.
Если оно совпадает со значением свойства мах, то кнопка находится в
утопленном состоянии. Равенство vaiue=Min означает, что кнопка отжата.
336
Глава 8
•> Figure 1 ВПЕЗ
Flle_ Edit .View Insert; Tools. Desktop Window. Help ■*
--"4tf
Рис. 8.11. Фиксирующиеся кнопки
8.1.3. Рамки, индикаторы альтернативных
и неальтернативных комбинаций
Новые интерфейсные компоненты типа Panel и Button Group
используются в качестве рамок-контейнёров, во внутренней области которых
группируются однотипные индикаторы альтернативных (Radiobutton) или
безальтернативных (checkbox) компонентов. Конечно, в панели можно размещать
компоненты и других типов. Удобство таких контейнеров заключается в
том, что они перемещаются по графическому окну вместе со своей
начинкой. Во-вторых, рамки могут быть снабжены пояснительной надписью, как
это делается в других визуальных средах. К сожалению, непосредственная
манипуляция с новыми интерфейсными компонентами достаточно сложна.
Поэтому знакомство с ними мы отложим до разд. 8.3.
•> Figure 1 ВПЕЗ
File Edit View Insert Tools Desktop Window .Help, . -»
1
0.8
0.6
0.4.
0.2
0
J. - -*.
Г бВД.
•: r cosfr)
4Г
D 0.2 0.4 0.6 0.8 1
Рис. 8.12. Приложение с лереключатеугсми
Проектирование интерсрейса
337
А пока продемонстрируем использование переключателей на примере выбора
функции, график которой должен воспроизводиться в поле hAxes. Далеко не с
первого раза нам удалось подобрать подходящие размеры и расположение
компонентов, представленных на рис. 8.12.
Если размеры и положение рамки с кнопками были установлены
сравнительно быстро, то поле графика упорно не хотело рисоваться до тех пор, пока не
было задано значение свойства units. По умолчанию единицы измерения
соответствуют режиму Units=r.ormalized, но позицию компонентов
привычнее задавать в пикселах. Оказалось, что важны не только единицы измерения,
но и тот факт, что они должны быть установлены до задания положения и
габаритов поля графика (т. е. на порядок задания свойств в функции set
следует обращать внимание).
Соответствующая заготовка файла buttongroupl.m без ссылок на
обработчики событий Callback содержит операторы, представленные в примере 8.8.
&&А .!.:;.■ .гл. ". ".si&i^.iA..M£-&..it«i3l .-.ш'ЗиЛ'.*..-.-. гя.гйй..." Ш~я . Г\, .... smL* .«л?;-..*7..... !. Ллк:.-.....\Ш.'!
function buttongroupl
global hAxes
global hRbl hRb2 hBb3
hFig=figure(' Position1, [50,50,500,30.0]) ;
hAxes=axes;
set(hAxes,'Units','pixels','Position',[50,50,350,230]);
hRbl=uicontrol('Style','radiobutton',...
'String','sin(x) ', . . .
'Position',[420,250,60,20]);
hRb2=uicontrol('Style', *radiobutton',...
'String','cos(x)',...
'Position',[420,220,60,201);
hRb3=uicontrol('Style','radiobutton',...
'String','exp(x)',...
'Position',[420,190,60,20]);
Несколько разочаровало то, что после запуска программы buttongroupl
щелчки по любой радиокнопке (переключателю) приводили к ее выделению
независимо от состояния других кнопок. Поэтому восстановление
справедливости пришлось перенести на обработчики события callback, которые
удалось объединить, в функции radioI.m (пример 8.9).
338
Глава 8
w'm?""®
%■ активизация объекта hAxes
% очистка поля графика
% если был сделан щелчок по первой кнопке
% сброс альтернативных кнопок
% сброс альтернативных кнопок
% построение синусоиды
function radiol
% функция для обработки событий Callback
global hAxes
global hRbl hRb'2 hRb3
axes(hAxes)
cla
x=0:0.1:6.28;
if gcbo==hRbl
set(hRb2,•Value',0)
set(hRb3,'Value',0)
y=sin(x);
plot(x,y);
end
if gcbo=hRb2 % если бьш сделан щелчок по второй кнопке
set(hRbl,'Value',0) % сброс альтернативных кнопок
set(hRb3,"Value',0) % сброс альтернативных кнопок
y=cos(к);
plot(х,у); % построение косинусоиды
end
if gcbo==hRb3 % если был сделан щелчок по третьей кнопке
set(hRbl,'Value',0) % сброс альтернативных кнопок
set(hRb2,'Value',0) % сброс альтернативных кнопок
у=ехр(х);
semilogy(х,у); %: построение экспоненты
end
grid oil % нанесение сетки
Одно из альтернативных состояний приложения с выделенным графиком
функции у = ех приведено на рис. 8.13.
Событие callback для переключателя возникает не только в момент щелчка
левой кнопкой мыши, когда острие ее курсора находится внутри окружности,
обозначающей кнопку. К внутренней области кнопки относится и
прямоугольник с пояснительной надписью, и щелчок по надписи также приводит
к выделению кнопки. Для выделенной кнопки автоматически
устанавливается значение свойства value, по умолчанию совпадающее со значением
свойства мах и равное д.. Отмена выделения других альтернативных кнопок
Проектирование интерфейса
339
возлагается на программиста и сводится к установке нулевого значения их
свойств Value.
■> Figure 1 НПО
File Edit View insert Tools Desktop Window Help ■»
юэ
101
101
. 10°
(
'; ' " _■ """ "~
ё^шйёшё^ш
i \--^.i-..-
=:::::rt:::::;::::::;-:::=
--^--- f ---4--
• ;
Г cosM
с exp[x)
: *
Э - 2 7-,..4 A --. 6. 8
.. ' ■ .-: - . .1
Рис. 8.13. График у = e* в полулогарифмическом масштабе
Кнопки типа checkbox (флажки), используемые для индикации
неальтернативных комбинаций, отличаются от переключателей только формой —
квадратиком, в котором при выделении кнопки пояштяется галочка. Генерация
события Callback и автоматическое выделение кнопки происходят при
щелчке на квадратике или сопровождающей его надписи. Если кнопка типа
Checkbox выделена, то значение ее свойства value совпадает со значением
свойства мах, по умолчанию равного х. Повторный щелчок по кнопке
checkbox автоматически изменяет ее состояние на противоположное.
Модифицируем предыдущий пример, заменив в нем переключатели на
флажки checkbox. В зависимости от комбинации отмеченных флажков в
поле графика должна появиться координатная сетка, синусоида,
косинусоида или оба графика вместе. Головная программа buttongroup2.ni мало чем
отличается от предыдущей, разве что на одну кнопку стадо меньше
(пример 8.10).
|м.ч;,ь"чд?/л*ч.; •'
||Прим;ер8.10.ФуНкц^ШЪ%>пдгоир2 i£. ; .-
аШЕ^ЕГЗ
function buttongroup2
global hAxes
global hCbl hCb2
hFig=f igure [' Position', [50,50, 500,300]) ,-
hAxes=axes('Units','pixels','Position', [50,50,350,230]);
340
Глава 8
hCbl=uicontrol('Style','checkbox',...
'String','sin(x)', ...
•Position', [-920,250,60,20], . . .
• Callback','checkl'>;
hCb2=uicontrol('Style','checkbox', . . .
'String','cos(x)',...
'Position',[420,220,60,20],...
'Callback','checkl');
В обработчике события Callback пришлось позаботиться только о том,
чтобы после воспроизведения какого-либо графика была возможность
построить график другой функции. В этом нам помогла процедура hold on,
предотвращающая создание нового фафического окна при выполнении в
очередной раз функции plot (пример 8.11).
:-;£?«Д|.,.-у.л.-.. .&&<№,« .-. .-; . . S .ii ..ййМаяшяяЯт ш&№&-..,!..: '$ .; ' ... Я51..:?л;х]н..-л* uisa£S&:
function checkl
global hAxes
global hCbl hCb2
axes(hAxes)
cla
get(hCbl)
get(hCb2)
x=0:0.1:6.28;
% если первая кнопка выделена
if (get (пСЫ, 'Value' )==1)
y=sin(x);
plot(x,у);
hold on
end
% если вторая кнопка выделена
if (get (hCb2,'Value')=1)
У=соб(x) ;
plot(x,y);
hold on
end
grid on
Один из фрагментов работы описанного приложения приведен на рис. 8.14.
Проектирование интерфейса
341
•> Figure 1 НПЕЗ
gie_gdlt View insert_TOob Desktop. Window Help .^. _^ *
' 1
0.5
f).
0
-05
0 2 4 6 8
Рис. 8.14. Два графика — оба флажка отмечены
8.1.4. Ввод, редактирование
и отображение текстов
Поле отображения текстовой информации— объект типа static Text —
является полным аналогом визуальных компонентов типа Label. Он
предназначен для вывода символьной строки (или нескольких строк) в
выделенном прямоугольнике. Отображаемый текст — значение свойства string —
не может быть изменен пользователем.
С помощью функции static_text.m (пример 8.12) формируется окно (рис. 8.15),
содержащее 4 ПОЛЯ С разными значениями свойства HorizontalAlignment
(горизонтальный прижим).
»> Figure 1
ипи
File Edit View Insert Tools Desktop Window Help *
Метка A
Метка 3
Метка 2
Метка 1
" J'
Рис. 8.15. Метки с различным расположением текста
/ \
■\
\
\
-V
i Л
А
уу ;
:.Psin(x)
17 cos(x)
ч&Ш
342
Глава 8
По умолчанию для объекта установлен центральный прижим
(HorizontaiAiignment=center), что хорошо просматривается на тексте
Метка 4. Белый фон окаймляющего прямоугольника позволяет более четко
рассмотреть положение выводимого текста.
?»"•-' ■-.-„w^jf.-ewivvr ^л"^гщг^тщ^«ж^-теч^«й^^^Ш5а^^Щ"'"~"'""г"'"'?'"тг: "*:
:&£:£:!::^..К^^ .-.. .:1
function static_text
hFig=figure('Position',[50,50, 300, 200J) ;
hStl=uicontrol('Style','text','Position',[30,30,150,20],...
'HorizontalAlignment', 'left', ...
'BackgroundColor',[1 1 1],•String','Метка 1') ;
hSt2=uicontrol('Style','text','Position',[30,60,150,20],...
'HorizontalAlignment','center',...
'BackgroundColor',[1 1 1],'String','Метка 2');
hSt3=uicontrol('Style','text','Position',[30,90,150,20],...
'HorizontalAlignment','right', ...
'BackgroundColor',[1 1 1],'String','Метка 3');
hSt4=uicontrol('Style','text','Position',[30,120,150,20], ...
'BackgroundColor',[1 1 1],'String','Метка 4');
Варианты создания многоэтажной надписи (рис. 8.16) демонстрирует
программа static_text2 (пример 8.13).
! Пример В\{^.Фуьщ^я-в^^щ2^Ш^\.§:н' -.4^ -ЙЙ^'Ч---- ч" ■ I
function static_text2
hFig=figure('Position',[50,50,300,200]);
hStl=uicontrol('Style",'text','Position', [30,30,60,55], . . .
'HorizontalAlignment', 'left', ...
'BackgroundColor', [1 1 1],...
■String',{'Строка 1','Строка 2','Строка 3'});
hSt2=uicontrol('Style','text','Position',[30,120,60,55],...
'HorizontalAlignment','left',...
'BackgroundColor',[1 1 1],...
'String',['String 1';'String 2';'String 3']);
Интерфейсный элемент типа Edit Text (редактируемый текст) может
использоваться как для вывода символьной информации, так и для ввода
Проектирование интерфейса
343
строк во время работы программы. Текст, набираемый в поле ввода, можно
корректировать, производить вставки и удаления, использовать фрагменты
из буфера обмена. Процедура ввода, завершаемая нажатием клавиши
<Enter>, генерирует событие callback. Второй способ генерации этого
события происходит в момент потери фокуса окном ввода. Для этого нужно
после набора данных перевести курсор мыши за пределы окна ввода и
произвести там щелчок левой или правой кнопкой.
-> Figure 1 НПО
File gdlt^lew ]nsert_Tools Desktop WlndouHelp ■»
Slnng 1
Slnng2
Slnng 3
Строка 1
Строка 2
Строка 3
Рис. 8.16. Многострочные метки
В программе edittextl.m (пример 8.14) демонстрируется стандартная
техника ввода данных, которые после возникновения события callback
переносятся в окно статического текста. Две другие метки используются для
идентификации полей ввода и вывода (рис. 8.17).
\ Прим^й.1-С<Ьуйкцияedxtjbe«ti vf^-^Й-^-^'-* - !'""'' ^~*\^-^-^jj0£M
function edit_textl
global hEd hSt
hFig=figure['Position', [50,50,400,150]);
hStl=uicontrol('Style','text','Position',[30,30,150,20],...
'String','Окно ввода');
hSt2=uicontrol('Style','text','Position', [200,30,150,20], ...
'String','Окно вывода');
hEd=uicontrolС Style','edit','Position', [30,60,150,20],...
'BackgroundColor',[1 1 1],'Callback','textl');
hSt-uicontroi('Style', 'text','Position',[200,60,150,20],...
'BackgroundColor', [1 1 1]');
12 3ак. 899
344
Глава В
-> Figure 1 НПО
File Edit View Insert Tools/Desktop Window Help *
'■'^"' '.'"Г»*' '" =¾1^1 "'■ ' *""'''л:1 v- ■'
■I " & - ^d,~,s
Окно ввода Окно вывода
" , Г'
Рис. 8.17. Форма приложения для ввода строки
Обработчик события callback переписывает содержимое поля ввода в окно
вывода (пример 8.15).
function textl
global hEd hSt
s=get(hEd,'String');
set(hSt,'String',s)
Результат работы этой простенькой функции представлен на рис. 8.18.
~> Figure 1
НПО
File Edit View Insert Tools Desktop Window Help «
й^'-'-^1^г;
| Helic. world!
Окно ввода
Hello, worldl
Окно выводе
Рис. 8.18. Пример ввода символьной строки
Вводимый текст может быть прижат к левому или правому краю окна ввода,
если задать соответствующее значение свойства HorizontalAlignment. Если
вводимый текст представляет собой числовое значение, которое должно
быть использовано в работе программы, то содержимое свойства string
переводится в числовой формат с помощью функции 5tr2num (в примере с
решением квадратного уравнения именно так и поступали при вводе
коэффициентов а, ь, с).
Проектирование интерфейса
345
8.1.5. Списки строк
Интерфейсный компонент типа Listbox представляет собой окно, в
котором может находиться список строк. Если длина списка превышает высоту
окна, то для перемещения по списку может использоваться вертикальная
полоса прокрутки. Список позволяет пользователю выбрать одну или
несколько строк и в зависимости от выбора произвести то или иное действие.
Список, предоставляющий возможность выбрать единственную строку,
характеризуется тем, что разность между значениями его свойств мах и Min
равна 1. По умолчанию это условие выполнено, т. к. мах=1, a Min=o. Выбор
строки осуществляется щелчком левой кнопки мыши в тот момент, когда
острие курсора указывает на выбираемую строку. Одновременно с
подсветкой строки ее номер заносится в свойство Value и генерируется событие
callback. Строки в. списке нумеруются от 1.
Если разность Max-Min превышает 1, то список допускает множественный
выбор. Сделать его можно несколькими способами. Для выбора
разрозненных строк нужно зажать клавишу <Ctrl> и щелкать мышью по выделяемым
строкам. При этом каждая выделяемая строка подсвечивается, а ее номер
запоминается в векторе value. Для выбора группы подряд идущих строк
можно нажать и удерживать клавишу <Shift>, а затем щелкнуть по первой и
последней строке группы. Все промежуточные строки тоже будут выделены
и все их номера запомнятся в векторе Value. При групповом выделении
событие callback возникает в момент отпускания кнопки мыши (таким
образом, это случится сразу же после выделения первой строки). Поэтому
обработку выделенных строк следует увязать с каким-нибудь другим
интерфейсным элементом, например, кнопкой с надписью Выбор сделан. И уже в
ее обработчике события Callback разбираться с компонентами вектора
value, принадлежащими списку.
Продемонстрируем работу с небольшим списком на примере построения
одной из функций — sin(x), cos(x) или ехр(х). Процедура создания и
заполнения списка включена в состав функции listl.m (пример 8.16).
[^йм!^^ ■ *** ''". - - ^Ш&Ж?&&Шь!*ё';|
function listl
global hAxes hLB
hFig=figure('Position', [50,50,500,300]);
hAxes=axes['Units','pixels','Position',[50,50,300,230]) ;
hLB=uicontrol('Style','listbox',...
■String',{'sin(x)','cqs(x)','exp(x)'},...
346
Глава 8
•Position",[370,150,100,100],...
•BackgroundColor',[1 1 1],...
•Callback',4ist2');
Обратите внимание на технику заполнения списка. Значением свойства
string здесь является массив ячеек, т. к. длины строк могут быть разными.
Этот массив можно было бы сформировать отдельно, сохранив, например,
под именем stri:
strl = {'sin(x)','cos(х)','ехр(х)');
И тогда задание свойства string могло иметь следующий вид:
'String',strl,...
Так как серый фон списка смотрится хуже, его заменили белым фоном (см.
значение свойства BackgroundColor).
Обработчик события Callback оформлен в виде функции Hst2.m
(пример 8.17).
function list2
global hAxes hLB
x=0:0.1:6.2B;
axes(hAxes)
k=get(hLB,'Value');
switch (k)
case 1
y=sin(x);
case ?
y=cos(x) ;
case 3
y=exp(x) ;
end
с la
plot(x,y
Результат работы описанного приложения приведен на рис 8.19.
Проектирование интерфейса
347
•> Figure 1 НПО
File Edit View Insert Tools Desktep Window Help . ■»
500
400
300
200
100
/
/
/
/
/
У \
i'.-
) 2 4 ,. 6 .8
' ^ ■*&
«W ij." i
ife. r-
Рис. 8.19. Выбор графика функции с помощью списка
8.1.6. Полоса прокрутки
Интерфейсный компонент типа Slider представляет собой обычную полосу
прокрутки, которую можно использовать либо в качестве средства ввода
числового значения из диапазона [Min, м.ах], либо в качестве индикатора
объема выполненной работы.
В зависимости от соотношения длины w и высоты h, заданных в качестве
значения свойства Position=[x у w h], полоса прокрутки принимает
горизонтальное (w > h) или вертикальное (w < h) положение. Точка с
координатами (х, у) соответствует позиции левого нижнего угла полосы.
Смещеггие ползунка (в горизонтальном положении — относительно левой
границы, а в вертикальном — относительно нижней границы) линейно
изменяет значение свойства Value в диапазоне от минимума (значение
свойства Min) до максимума (значение свойства мах). По умолчанию Min=o, а
мах=1. Пользователь может перемещать ползунок тремя способами:
D захватив ползунок мышью с нажатой левой кнопкой и перемещая его в
том или ином направлении до момента отпускания кнопки;
О щелкая по одной из граничных стрелок полосы прокрутки (малый шаг);
□ шелкая по области полосы между ползунком и стрелкой (большой шаг).
Каждое из этих действий вызывает событие callback. В двух последних
случаях величина смешения ползунка определяется компонентами
свойства siiderstep=[hl h2]. Первая составляющая этого вектора (по
умолчанию hi=0.oi) определяет долю малого шага, а вторая составляющая (по
348
Глава 8
умолчанию h2=o.l) — долю большого шага относительно длины интервала
(Max-Min).
Для изменения положения ползунка программным путем достаточно
изменить значение свойства Value, например, с помощью функции set.
Продемонстрируем поведение полосы прокрутки в следующем приложении.
Поместим на форму приложения горизонтальную линейку, положение
ползунка которой будет отслеживать упомянутые выше манипуляции. Текущее
значение свойства Value отображается в поле вывода обработчиком события
Callback (функция sid). Ползунок вертикальной полосы отображает
значение числа, набираемого в поле ввода. Текст программы и обработчики
событий Callback приведены в примере 8.18.
;Пример 8.18. Функция sli^rl ^;j^bi^^il^^H ^., . ^5,.. ^¾¾¾1 * И<.-»
function sliderl
global hStl hEd2 hSldl hSld2
hFig=figure('Position',[50,50,400,300]);
ftStl=uicontrol('Style','text','Position',[135,25,60,20],...
•Backgroundcolor',[1 1 1],'String', ' 0');
hSldl=uicontrol('Style','slider','Position',[50,50,200,20],...
'Callback','sld');
uicontrolfStyle','text','Position',[50,25,80,20],...
'String','Окно вывода');
hEd2 =uicontrol('Style','edit','Position', [260,255,40,20], ...
'Backgroundcolor',[1 1 1],'String*,'0',...
•Callback','fed');
uicontrol('Style','text','Position',[170,255,80,20], ...
'String','Окно ввода');
hSld2=uicontrol('Style','slider','Position',[270,50,2Q,200]);
% Обработчик события Callback горизонтальной линейки
function sld
global hStl hSldl
set(hStl,'String',num2str{get(hSldl, 'Value')));
% Обработчик события Callback для окна ввода
function fed
global hEd2 hSld2
set[hSld2,'Value',str2num(get(hEd2,'String')));
Проектирование интерфейса
349
Общий вид приложения приведен на рис. 8.20.
•> Figure 1 ЯПЕЗ
File Kit view insert Tools Desktop Window Help *
. ■,'.-■'.„."" '-'■' v *• - -v*'■•;.■*
1¾¾^.. i; ■
■■ ■■"-" ■ '■
'^■.■г*^/ Г''
_j—_^, —j— ..-. -J
.. Окисей «.V^
:-.- «№*-'
■Ш
t *:li*m
Рис. 8.20. Приложение с линейками прокрутки
Так как обработчики событий представлены простейшими функциями, то
использование анонимных функций позволяет написать более компактную
программу, состоящую из единственного файла (пример 8.19).
function slider2
global hStl hEd2 hsldl hsid2
hFig=figure (' Position', [50, 50, 400, 300]) ,-
hStl=uicontrol('Style*,'text*,'Position*,[135,25,60,20],...
'Backgroundcolbr', [1 1 1],'String','0'),■
hSldl=uicontrol(*Style','slider','Position',[50,50,200,20],...
'Callback', 'sld');
uicontroK'Style','text','Position',[50,25,80,20],...
'String','Окно вывода'),-
hSd2 = uicontrol('Style','edit','Position',[260,255,40,20], .. .
'Backgroundcolor',[1 1 1],'String','0',...
'Callback', 'fed');
ui'control('Style','text*,'Position',[170,255,80,20], ...
'String','Окно ввода');
hSld2 = uicontrol('Style','slider','Position',[270,50,20,200]);
fed = @() set(hSld2,'Value',str2num{get(hEd2,'String'))),-
sld = GO set(hStl,'String',num2str(get(hSldl,'Value')));
350
Глава 8
8.2. Создание всплывающего меню
Всплывающее (или контекстное) меню может быть приписано любому
интерфейсному компоненту или графическому объекту. Оно появляется в
момент нажатия правой кнопки мыши, если ее указатель находится на
территории компонента или в непосредственной близости от объекта. Создается
всплывающее меню по следующей схеме:
1. С помощью функции uiconextmenu создается указатель на всплывающее
меню:
hMenu = uicontextmenu;
2. С помощью функций uimenu формируются команды меню, с каждой из
которых связывается функция обработки события Callback:
iteml=uimenu(hMenu,'Label','имя_команды1', * Callback *,cbf1);
item2=uimenu(hMenu,'Label','имя_команды2','Callback',cbf2);
item3=uimenu(hMenu,'Label','имя_командыЗ','Callback',cbf3);
3. Указатель на всплывающее меню присваивается свойству uicontextmenu
того объекта, с которым мы связываем созданное меню:
set(hObj,'Uicontextmenu',hMenu);
Продемонстрируем эту схему на примере всплывающего меню, которое
изменяет стиль линии нарисованного графика. Для этой цели достаточно
изменить значение свойства линии Linestyle (пример 8.20).
...„.„....,,v„.^...,,..^^^^
Шример 8.20. Всплывающее меню с Са&Ш&)&ф^
function popupjmenu
global hLine
hMenu=uicontextmenu; % создание указателя на меню
х=0:0.1:6.28; % задание аргумента
y=sin(x); % формирование значений функции
hLine=pldt(х,у,'Uicontextmenu',hMenu); % построение графика
% создание команд всплывающего меню
iteml=uimenu(hMenu,'Label','штриховая','Callback','cbl');
itern2=uimenu(hMenu,'Label','пунктирная', * Callback','cb2');
item3=uimenu(hMenu,'Label','сплошная•,'Callback','cb3');
end f
Проектирование интерфейса
351
function сЫ "*•
global hLine
set(hLine,'LineStyle','—');
end
% штриховая линия
function сЬ2
global hLine
set (h.Line, 'LineStyle' ,':');
end
% пунктирная линия
function сЬЗ
global hLine
set(hLine,'LineStyle','-');
end
% сплошная линия
Результат работы этого мини-приложения представлен на рис. 8.21. Не
забудьте только поместить функции обработки команд меню в отдельные т-
файлы.
•> Figure 1
.File Edit View Insert Tools
DcSsyal fe|Sl€lf7®
mi-
A.-
Й
. \ -0.5
Desktop Window
M.I D Щ а lu
HDD
i Help. ... ■•'
]•■■;: »-
■ ■ ■ -^t: ^,
■ / - ■
*
пунктирная
сплошая
\
\
/
/
/
/
) 1-2 3 4 5 ' sfe .
■.-'-
---
г "'■
Рис. 8.21. Иллюстрация работы всплывающего меню
Обработчики событий могут быть оформлены и как строки в теле головной
функции. Обратите внимание на то, что в примере 8.21 в состав строк
352
Глава 8
включены описания глобальной переменной hLine и все кавычки в
командах заменены двойными кавычками.
I Прйм^&ЙГЙспрльзрванйвстрок при- обработ й.ком^Д'й^ню;^**'^^^'^^^
function popup_menu2
global hLine
hMenu=uicontextmenu; % создание указателя на меню
х=0:0.1:6.28; % задание аргумента
y=sin(х); %■ формирование значений функции
hLine=plot(х,у,'UlContextmenu',hMenu);к построение графика
% описание строк — функций обработки событий
сЫД.= ' global hLine, set (hLine, ''LineStyle'', '' —'')'; % штриховая линия
cb21='global hLine, sot(hLine,''LineStyle'','':'')'; % пунктирная линия
cb31='global hLine, set(hLine,''LineStyle'',''-'')'; % сплошная линия
% создание команд всплывающего меню
iteml=uimenu(hMenu,'Label','штриховая','Callback',cbll);
item2=uimenu (hMenu, ' Label', ' пунктирная', ' Callback', cb21) ,-
itera3=uimenu(hMenu,'Label','сплошная','Callback',cb31);
8.3. Проектирование интерфейса
в среде GUIDE
Динамический способ проектирования интерфейса в системе MATLAB
обладает рядом недостатков по сравнению с возможностями, которые
предоставляют наиболее распространенные среды визуального программирования.
Во-первых, программа приложения, формируемая пользователем, разбухает
за счет операторов, создающих интерфейсные элементы. В визуальных
средах интерфейсные элементы включаются в окна приложения путем их
перетаскивания из палитры компонентов и настройки нужных свойств с
помощью достаточно удобных редакторов типа Object Inspector (Инспектор
объектов). И ни одной строчки кода для этой цели писать пользователю не
приходится (все заботы по обустройству интерфейса приложения визуальная
среда берет на себя). Кроме того, внешний вид большинства интерфейсных
компонентов в визуальной среде можно наблюдать и корректировать до
запуска приложения.
Во-вторых, в визуальной среде очень просто управлять положением
интерфейсных элементов на форме и их размерами.
Проектирование интерфейса
353
Наконец, в визуальных средах унифицированы форматы вызова
обработчиков различных событий и перечни передаваемых им параметров. Оболочка
для каждого обработчика формируется визуальной средой автоматически.
Пользователю остается только заполнить тело предоставленной процедуры.
Все это послужило поводом к созданию в рамках системы MATLAB
сервисных средств, упрощающих проектирование интерфейса приложения.
Перечень этих средств приведен в табл. 8.3.
Таблица 8.3
Наименование Назначение
GUIDE (GUI Builder) Конструктор графического интерфейса
Property Inspector Инспектор свойств
Object Browser Просмотр объектов
M-file Editor Редактор m-файлов
Component Callbacks Создание функций обработки событий для компонентов
Figure Callbacks Создание функций обработки событий для окна
Align Objects Выравнивание объектов
Grid and Rulers Управление сеткой и линейками
Menu Editor Создание и редактирование меню
Tab Order Editor Изменение порядка активизации компонентов при
нажатии клавиши <ТаЬ>
8.3.1. Вызов редактора GUIDE
Редактор GUIDE (Конструктор фафического интерфейса) является главным
инструментом в конструировании графического интерфейса приложения.
Его первоначальная настройка производится после выполнения цепочки
команд File | Preference | GUI (Файл | Предпочтения | Интерфейс). При этом
появляется окно, представленное на рис. 8.22. Простановка
соответствующих флажков позволяет:
П подключить или отключить панель инструментов (Show toolbar (Показать
панель));
П сделать более наглядной палитру компонентов, снабдив каждый
интерфейсный элемент подписью (Show names in component palette
(Отображать имена в палитре компонентов));
П отображать полные или укороченные имена файлов (Show file extension in
window title (Отображать расширение файла), Show file path in window title
(Отображать путь к файлу));
354
Глава 8
П фильтровать список имен файлов или показывать все файлы в
диалоговых окнах (Show all files in file open dialog (Отображать все файлы));
П запрашивать подтверждение на запоминание файла интерфейса (Show save
confirmation on activate (Отображать подтверждение сохранения файла));
П запрашивать подтверждение на запоминание файла при экспорте (Show
save confirmation on export (Отображать подтверждение сохранения файла)).
«Jt. Preferences
' 1+1-General
Ijti-Fonts
j~~Colors
!=!-■ -Commend Window
'—Keyboard & Indenting
i—Command History
1+1 -Editor/Debugger
i-Help
—Web
—Current Directory
j —Workspace
—Array Editor
] j-CTra
j air-Figure Copy Template
I Й-Slmullnk
i
i
■j
■s *'b ■;!';>;':K-':V''"0:";i
' .. * -
GUIDE Preferences :, ' ... *"•'
SWMtwftw^ яхшж&ешг rie» >*f-te "
P Show toolbar
P Show names fn component palette
P Show file extension In window title
Г" Show tile path In window title
V Show all tiles in file open dialog
P Show save contirmrflon on activate
P Show save confirmation on export
OK | Cancel
НЕЮ
•jfi Л T ■*!.-. * Jlfl} *
1 Apply | Help j
Рис. 8.22. Предварительная настройка редактора GUIDE
Редактор GUIDE вызывается командой guide из командного окна путем
выполнения цепочки команд главного меню File | New | GUI (Файл | Создать |
Графический интерфейс) или с помощью стандартной схемы запуска Start |
MATLAB | GUIDE (GUI Builder) (Пуск | MATLAB | GUIDE (GUI Builder)).
Две вкладки, присутствующие в стартовом окне (рис. 8.23), позволяют начать
проектирование нового интерфейса (вкладка Create New GUI (Создать новый
интерфейс)) или воспользоваться ранее созданным интерфейсом (вкладка
Open Existing GUI (Открыть существующий интерфейс)). Дело в том, что
описание формы приложения вместе с расположенными на ней интерфейс-
Проектирование интерфейса
355
ными компонентами может быть сохранено в файле с расширением fig. Если
на диске хранится нечто похожее на наше будущее приложение, то
существующим файлом можно воспользоваться с целью экономии времени.
GUIDE Quick Start И
CrealeNewGUi | Open Existing GUI ) "^^j" #)• ■" ""*""***" '' :i'
Preview*——■■—■ — ■■■- : — -rnvj
BUNK
Г Save on startup as: iHtMATi^rivvoitturiKiedl.lki Browse,.'
OK I Cencel Help
Рис. 8.23. Начальное окно GUIDE
Список шаблонов (GUIDE templates) предлагает четыре варианта
компоновки, которые можно положить в основу проектируемого приложения:
□ Blank GUI (Default) (Шаблон интерфейса) — проект начинается с нуля и
в нашем распоряжении оказывается пустая форма, на которой можно
размещать любые интерфейсные элементы (uicontrois), поля графиков
(axes), Главное И всплывающие меню (Main И Popup Menu);
□ GUI with Uicontrois (Типовой интерфейс) — в качестве прототипа
предлагается готовое к исполнению несложное приложение, содержащее 15
интерфейсных компонентов (окна ввода, метки, панели, кнопки,
переключатели). В качестве результата работы оно выдает произведение двух
физических величин — плотности и объема, значения которых
пользователь вводит в соответствующих окнах. Исходный текст m-файла и
Property Inspector (Инспектор свойств) позволяют "рассмотреть основные
моменты, связанные с функционированием интерфейсных элементов, с
программированием функций — обработчиков соответствующих
событий, с реакцией на ввод ошибочных данных;
WWIUL. LCIIipiCHCO
-i Blank GUI (Default)
<ф, GUI with Uicontrois
ф. GUI with Axes and Menu
■ф. Modal Question Dialog
356
Глава 8
П GUI with Axes and Menu (Интерфейс с координатными осями и меню) —
в качестве прототипа предлагается готовое к исполнению приложение,
воспроизводящее график одной из шести функций в зависимости от
выбранной строки раскрывающегося списка. Текст исходной
программы также открыт для изучения техники использования поля графики и
команд меню;
П Modal Question Dialog (Модальное диалоговое окно) — в качестве
прототипа предлагается приложение, использующее диалоговое окно,
содержащее запрос, предполагающий два варианта ответа.
Приведенный ниже список поможет вам разобраться со спецификой
приложений, предлагаемых в качестве прототипов.
D Приложение с интерфейсными компонентами (рие. 8.24).
Это приложение предназначено для демонстрации техники ввода
числовых значений плотности (окно с меткой Density (Плотность)) и объема
(окно с меткой Volume (Объем)). По нажатию кнопки Calculations
(Вычисления) производится вычисление произведения плотности d на
объем v, результат отображается в окне с меткой Mass (Масса). В рамке с
меткой Units (Единицы измерения) размещены два переключателя, с
помощью которых выбирается одна из систем измерения физических
величин — английская (фунты — lb, кубические дюймы — cu.in) или СИ
(килограммы — kg, кубические метры — cu.m). При изменении системы
измерения меняется содержимое меток text4, texts, text6. Попытка
ввести нечисловое значение, например, Density=abc, вызывает
диалоговое окно с сообщением об ошибке (рис. 8.25).
textl
text2 —
text3 —
radiogroup
panel density
(edit)
text4
[Measures-
-fDensityMI
Volume(V):
Mass(D*V):
volume
(edit)
english si
(radiobutton) (radiobutton)
D Ib/cu.in
0 cu.ln
0 lb
<— text5
mass i_ text6
(text)
Units—
ff English Unit'System
r S.I. Unit System
Calculate
Reset
pushbutton2
■— pushbuttonl
Рис. 8.24. Индикатор интерфейсных компонентов
Проектирование интерфейса
357
\'J> Error В
n-lxj
j Input must bea number
OK
" :4f
;
Рис. 8.25. Реакция на ввод нечислового значения
На рис. 8.26 приведено окно Object Browser (Просмотр объектов), в
котором отражена информация обо всех объектах приложения.
Object Browser
НПО
ЕН--Н figure (Untitled)
—ЁнЗ uicontrol (calculate "Calculate")
—ШП uicontrol (reset "Reset")
EjH^] uipanel [uipenell "Measures")
■ami uicontrol (textl "Density(D):")
im uicontrol (text2 "Volume (V):")
№ uicontrol (density "0")
■№" uicontrol (volume "0")
-W uicontrol (юаяз "0"|
-.™. uicontrol (text3 "Kass (D*V):")
ftibuicontrol (taxt6 "lb")
—ЭЧП uicontrol (text4 "ib/cu. m")
wuicontrol (texts "cu.in")
B- QS uitools.uibuttongroup (unitgroup "Units")
~в> uicontrol [english "English Unit System")
—ф uicontrol (si "S.I. Unit System")
I Л
Рис. 8.26. Реестр объектов приложения
П Приложение с графиком и меню (рис. 8.27).
Для программистов, работавших в других визуальных средах, покажется
непривычным то, что компонент, напоминающий раскрывающийся
список, на самом деле является всплывающим меню с включенным
свойством visible. Щелчок на его кнопке раскрывает строки меню, команды
которого представлены на рис. 8.28.
Щелчок по кнопке Update (Обновить) приводит к выполнению callback-
функции, представленной в примере 8.22.
358
Глава 8
Sf untitled2.fig
0le Edit View Layout lools detp
.о gs:h"! i.-Щт *■■ r. | & m&jQas*£'!'^"
1 4 Select
S.Push Button
■a Slider
® Radio Button
В Check Box
WF Edit Text
ч>' Stallc Text
еэ Pop-up Menu
JEllUsibox
Ш Toggle Button
|q{ Axes
1¾ Panel
1¾ Button Group
s)f AilivaX Control
plot(rand(5)) jj (jpdale
^\ axesl у/
LI
ИПП
-
p
Рис. 8.27. Приложение с графиком и меню
•> untitled4
File
Рис. 8.28. Раскрытое меню (тип Popup Menu)
Проектирование интерфейса 359
. Пример '8:ЩфаШЪлс^^у^йиищяЩбг1^М^а{0^^^ .^¾½¾¾^^¾1^^^
function pushbuttonl_Callback(hObject, eventdata, handles)
% hObject - указатель на pushbuttonl (см. GCBO)
% eventdata - резерв для будущих версий MATLAB
% handles - структура с указателями на все компоненты (см. GUIDATA)
axes(handles.axesl); % активизация поля графика
cla,- % очистка поля графика
% опрос индекса вьщелеинои команды вспльшающего меню
popup_sel_index = get(handles.popupmenul, 'Value');
% переключатель по номеру выделенной команды
switch popup_sel_index
case 1 % построение ломаной по случайным координатам
plot(rand(5));
case 2 % построение синусоиды
plot(sin(1:0.01:25)),•
case 3 % динамическое построение косинусоиды
comet(cos (1:.01:10));
case 4 % построение столбцовой диаграммы
bar(l:10);
case 5 % построение сечений мембраны
plot(membrane);
case" б % построение поверхности
surf(peaks);
end
ЯГ untitled3. fig
01ё Edit. View Layout Tpols (Help
ИПП
D G*-,JB I .& *i ft -J " | Ф В №> ' Q Й «£ j>
I It Select
И Push Button
• Slider
€> Radio Button
И Check Box
5Ф7 Edit Text
i" Static Text
Do you want to create a question dialog?
Yes ■
No
Рис. 8.29. Приложение с диалоговым -запросом
360
Глава 8
Кроме всплывающего меню приложение снабжено главным меню с
единственным разделом File (Файл), в состав которого включены три
команды — Open (Открыть), Print (Печать) и Close (Закрыть).
□ Приложение с диалоговым окном (рис. 8.29).
' Запуск этого приложения приводит к появлению диалогового окна,
представленного на рис. 8.30.
untitled5
f7\
1 t l Do you want to create a question dialog? ■■
4*4
Yes
No
ЕЭ
Рис. 8.30. Запрос на создание диалогового окна
8.3.2. Управление
конструктором графического интерфейса
По умолчанию работу в конструкторе графического интерфейса (GUIDE)
начинают с пустого приложения. В наше распоряжение предоставляется
окно конструктора (в документации MATLAB его называют Layout Editor
(Редактор компоновки) с пустой формой на рабочем поле (рис. 8.31).
Заголовок конструктора снабжен именем будущего интерфейсного файла —
untitled.fig (безымянный), которому перед записью на диск надо присвоить
более содержательное название. У левой границы конструктора расположена
однорядная палитра интерфейсных компонентов, снабженных подписями
(на вкладке GIUDE Preference (Параметры конструктора графического
интерфейса) был помечен режим Show names in component palette (Отображать
имена в палитре компонентов) — см. рис. 8.22).
Рабочее поле конструктора занято проектируемой формой, на которой
нанесена вспомогательная сетка, обеспечивающая довольно простое
выравнивание компонентов по узлам и линиям. Шаг сетки можно регулировать.
Более точные цифровые размеры и положение компонента на форме можно
будет задать в Property Inspector (Инспектор свойств).
Редактор конструктора располагает собственным главным меню, разделы
которого комментируются ниже.
Проектирование интерфейса
361
aflf untitled, fig
File Edit View Layout Tools
:d g?h'| r^e 1 «!-*b
1 It Select
LsD Push Button
=» Slider
"® Radio Button
В Check Box
''*" Edit Text ..
3«' Static Text
ЕЭрор-up.Menu
JELIstbox
BBToggle Button
IfiiAxes
(¾ РапвГ
(I*: Button Group
s)f ActiveX control
<l
-
Help
НПО
№ ;'"0'Й'* !""•
■
■_
'
■!_
!
1
'-■
.
t
)•
1'
ж
,
—J
J1
Рис. 8.31. Проектирование формы с нуля
Список команд меню File (Файл) содержит довольно обычный набор
процедур по созданию (New (Новый)), открытию (Open (Открыть)), закрытию
(Close (Закрыть)) и сохранению (Save (Сохранить), Save As (Сохранить как))
интерфейсного файла. Команда Preference (Предпочтения) открывает окно
по предварительной настройке параметров системы, которое уже
рассматривалось в гл. 2. По команде Export (Экспорт) в текущем каталоге
запоминается m-файл, включающий команды и функции по формированию
графического окна с встроенными интерфейсными компонентами. Этот файл очень
напоминает интерфейсный файл с расширением fig, и им можно
воспользоваться в других приложениях. Пусть вас не смущают размеры
экспортируемого файла. Например, для пустой формы untitled.fig соответствующий
экспортируемый файл по умолчанию имеет имя untitled_export.m и содержит
315 строк. Большую часть этого файла составляют комментарии,
описывающие использованные данные и функции. Команда Print (Печать)
позволяет выдать на принтер сформированное окно. В нижней части меню File
(Файл) запоминаются имена последних fig-файлов, с которыми работал
пользователь, и это обеспечивает быстрый доступ к любому из них.
Меню Edit (Правка) содержит достаточно известные процедуры по отказу от
только что сделанного исправления (Undo (Отменить ввод)), возврату к
отмененному исправлению (Redo (Повторить)), вырезанию (Cut (Вырезать))
или копированию (Сору (Копировать)) выделенного компонента или
группы компонентов в буфер обмена (clipboard), по извлечению информации из
362
Глава 8
буфера обмена (Paste (Вставить)). Одиночный компонент на поле редактора
выделяется щелчком мыши в тот момент, когда ее указатель находится над
компонентом. Выделенный компонент отмечается небольшими
квадратиками по углам габаритного прямоугольника. Для выделения нескольких
компонентов надо нажать и удерживать клавишу <Shifl> и щелкать мышью по
нужным элементам. С помощью команды Select All (Выделить все) можно
выделить все интерфейсные элементы, установленные на форме.
Выделенные компоненты удаляются с помощью клавиши <Delete> или команды
Clear (Очистить). Команда Duplicate (Дублировать) используется для
дублирования выделенного элемента, что обеспечивает идентичность
большинства свойств у вновь созданного клона (габариты, надпись и т. п.).
Меню View (Вид) обеспечивает вызов таких редакторов, как Property
Inspector (Инспектор свойств), Object Browser (Просмотр объектов), M-file
Editor (Редактор М-файлов). Команды Component Callbacks (Реакция на
события от компонента) и Figure Callbacks (Реакция на события от
графического окна) вызывают дополнительные меню для перехода в режим
запоминания в формате m-файлов функций — обработчиков различных событий,
относящихся к выделенному объекту.
Меню Layout (Разметка) включает группу команд по перестановке объектов,
загораживающих друг друга. По команде Bring to Front (Перенести на
передний план) помеченный объект или группа объектов перемешаются на
передний план, заслоняя собой непомеченные объекты. Команда Send to
Back (Перенести на задний план) заставляет переместиться на задний план
все помеченные объекты. Команды Bring Forward (Перенести вперед) и Send
Backward (Перенести назад) отличаются тем, что перемещаемые ими
объекты не совершают крайние движения — либо в начало, либо в конец, — а
осуществляют свои перестановки только на один уровень. Это напоминает
ситуацию, когда солдат, построенный в колонну по одному, меняется
местами со своим ближайшим соседом спереди или сзади. Команда Snap to
Grid (Привязать к сетке) включает или отключает режим, фиксирующий
размещаемые компоненты на линиях и узлах вспомогательной сетки.
Раздел Tools (Сервис) включает команды вызова инструментальных средств
конструктора графического интерфейса:
□ Align Objects (Выровнять объекты) — инструмент для управления
положением интерфейсных объектов;
П Grid and Rules (Сетка и линейки) — инструмент для управления сеткой и
измерительными линейками;
□ Menu Editor (Редактор меню) — редактор главного и всплывающего меню;
□ Tab Order Options (Порядок табуляции) — инструмент для изменения
порядка следования интерфейсных элементов при последовательных
нажатиях клавиши <ТаЬ>.
Проектирование интерфейса
363
В этот же пункт меню включены команды по запуску сформированного
приложения (Run (Запуск)) и настройке параметров, управляющих
режимами работы конструктора (GUI Options (Опции интерфейса)).
Окно GUI Options (Опции интерфейса), используемое для дополнительной
настройки параметров конструктора графического интерфейса, приведено
на рис. 8.32.
GUI Options
Resize behavior: - j Non-resizable
Command-line accessibility:. 1 Callback (GUI becomes Current Fi
С Generate FlG-file and M-lile
(7 Generate callback function prototypes
17 GUI allows only one instance to run (singlelon)
17 Use system color scheme for background (recommended)
(~ Generate FlG-file only Vi. .-,
OK
fi Sfb
V
9ure within Callback
'■w
4
Cancel
£)
Help
"
"
',
E3
.
Рис. 8.32. Настройка параметров редактора GUIDE
Первый раскрывающийся список Resize behavior (Размеры окна) позволяет
выбрать вариант поведения приложения при попытке пользователя
изменить размеры окна. Возможных вариантов три:
П Non-resizable (Размеры постоянны) — окно не допускает изменения
своих размеров;
□ Proportional (Пропорционально) — изменение размеров окна допускается
и одновременно происходит автоматическое масштабирование всех
компонентов, размещенных на форме;
П User-specified (Задание пользователем) — изменение размеров окна
допускается, но перекомпоновка всех интерфейсных элементов возлагается
364
Глава 8
на программу пользователя, реагирующую на событие Resize (свойство
ResizeFcn является указателем на эту функцию).
Раскрывающийся список Command-line accessibility (Доступ к командной
строке) управляет разграничением доступа к указателю на текущую фигуру
(gcf) между функциями GUI и командной строкой. Здесь выбор
представлен чегырьмя вариантами:
П Callback (Реакция на событие)) — функции обработки событий получают
указатель на текущую фигуру;
П Off (Отключить) — функции обработки событий никогда не получают
указатель на текущую фигуру;
П On (Включить) — функции графического интерфейса могут получить
указатель на текущую фигуру из командной строки;
П Other (Другие) — действуют установки, выполненные пользователем в
Property Inspector (Инспектор свойств).
На способ доступа к указателю на текущую фигуру влияют два свойства —
HandleVisibility И IntegerHand]е.
Первое из них может принимать одно из трех значений — on, off или
Callback. Установка HandieVisibiiity=caiiback означает, что указатель на
текущую фигуру доступен функциям обработки событий и функциям,
которые вызываются из callback-обработчиков. Но для функций, вызванных из
командной строки, указатель на текущую фигуру недоступен. Это защищает
графический интерфейс от вмешательства со стороны пользователя.
Установка HandieVisibiiity=off исключает указатель на текущую фигуру из
списка доступных указателей (из структуры handles), и это налагает запрет
на использование ряда Команд — xlabel, ylabel, zlabel, gca, gcf, findobj.
В режиме Handievisibiiity=on указатель на текущую фигуру доступен
любым функциям.
Перевод свойства integerHandie в состояние off вынуждает MATLAB
генерировать непредсказуемые вещественные значения указателей, что может
предотвратить случайное нарушение функционирования графического
объекта. Целочисленное значение указателя легко отобразить на экране и
воспользоваться им для обращения к той или иной функции, изменяющей
поведение объекта.
Два переключателя позволяют выбрать один из режимов генерации
интерфейсных файлов — только файл с расширением fig (Generate FIG-file only
(Создать только fig-файл)) или оба файла с расширениями fig и m (Generate
FIG-file and M-File (Создать fig- и m-файлы)). В последнем варианте имеется
возможность задания любой комбинации следующих параметров:
П Generate callback function prototypes (Создать прототипы функций
реакции на событие) — генерировать прототипы саНЬаск^функций;
Проектирование интерфейса
365
П GUI allows only one instance to run (singleton) (Запуск одной копии
приложения) — интерфейс допускает запуск единственного приложения
(т. е. одновременное функционирование двух копий приложения
запрещено);
□ Use system color scheme for background (recommended) (Использовать в
качестве фона цветовую схему системы (рекомендуется)) — использовать
для фона цветовую установку системы.
Режим генерации прототипов Callback-функций обеспечивает вставку в
интерфейсные файлы заготовок для программирования обработчиков всех
событий, связанных с размещенными на форме компонентами. Эти вставки
снабжены подробными комментариями по поводу смысла параметров и
назначения соответствующих функций.
Меню Help (Справка) содержит две команды, вызывающие цепочку кадров
со справочной информацией по вопросу использования конструктора
интерфейса (Using the Layout Editor (Использование редактора компоновки)) и
технологии создания графического интерфейса (Creating GUIs (Создание
графического интерфейса)).
Под главным меню расположена панель инструментов (рис. 8.33), на
которой представлены кнопки быстрого запуска наиболее часто используемых
команд.
г Cut
г Copy
- Paste
- Align Objects
" Menu Editor
г Tab Order Editor
Run -
dj^jbJ ^j4j®j^J_^|^Jjgj№]|s]a]^J|iiJ
- Save
-Open
- Redo
l-Undo
- New M-file Editor -
Property Inspector-
О
3jec
ЛВгс
ws
ar J
Рис. 8.33. Панель инструментов конструктора графического интерфейса
8.3.3. Размещение интерфейсных элементов
Выделим в палитре компонентов интересующий нас интерфейсный элемент
и переведем курсор мыши в точку формы, соответствующую левой верхней
366
Глава 8
точке компонента. Теперь нам предоставляются две возможности. Во-
первых, после щелчка на форме появляется выбранный интерфейсный
компонент стандартных размеров. Во-вторых, можно нажать левую кнопку
мыши и растянуть компонент до нужных размеров. Когда кнопка мыши
отпускается, размеры элемента будут зафиксированы. Как правило, выбранный
компонент прижимается к линиям координатной сетки, если
соответствующий режим, действующий по умолчанию, не был отменен (см. команду
Layout | Snap to Grid (Разметка | Режим сетки)).
Компонент, попавший на форму, можно переместить. Для этого надо
щелкнуть по компоненту (выделить его), после чего по углам выделенного
компонента появляются небольшие квадратики. Затем зажимают левую кнопку
мыши, и элемент перетаскивают на новое место. Если зацепиться
указателем мыши за любой из выделенных уголков, то его размеры можно
изменить вручную.
Если по тем или иным причинам нас не устраивают положение и размеры
выделенного компонента, то можно прибегнуть к услугам Property Inspector
(Инспектор свойств). Если свойство Position "закрыто" (слева в квадратике
виден знак +), то его надо "раскрыть", щелкнув по знаку. Затем в поле
значений свойств можно изменить координаты точки привязки (х, у), ширину
(width) или высоту (height) объекта (рис. 8.34).
.... _-
■rjl- Position
— X
„у
-width
1— height
[14,143 28,25 21,571 1,5]
14.143
28.25
21.571
1.5
Рис. 8.34. Изменение позиции и размеров кнопки
Компонент, попавший на форму по ошибке, можно удалить. Для этого его
нужно выделить и нажать клавишу <Delete>.
Для размещения на форме следующего компонента такого же типа и таких
же размеров надо выделить элемент-прототип и выполнить команду Edit |
Duplicate (Правка | Дублировать) — рис. 8.35. Над выделенным компонентом
появится клон, который можно отбуксировать на нужное место.
Вторая возможность создания клона существующего на форме компонента
связана с использованием буфера обмена. Выделенный элемент копируется
в буфер обмена (Edit | Сору (Правка | Копировать)), а затем по команде
Edit | Paste (Правка | Вставить) вставляется один или несколько раз.
Проектирование интерфейса
367
Edit
Undo Ctrl+2
Redo ОгГ+Л
'"' Cut Ctrl+X
Ccpy Ctrl+C
Paste Ctrl+V
Clear
Select All Ctrl+A
| Duplicate Ctrl+D
■' Push
Г
•"
. ■>"
Button
" ■ 1
■
~
1
p
■
Рис. 8.35. Создание клона
Визуальное размещение и выравнивание нескольких элементов на форме
облегчается за счет использования измерительных линеек и механизма
выравнивания. После выполнения команды Tools | Grid and Rulers (Сервис |
Сетка и линейки) на экране появляется вспомогательное меню (рис. 8.36).
В нем можно отметить следующие средства выравнивания:
П показать измерительные линейки (Show rulers (Отображать линии));
П показать направляющие линии (Show guides (Отображать направляющие
линии));
П показать сетку (Show grid (Отображать сетку)).
Ql-
«I'll» "
8-
#
■Л"
(Я-
so 100
«♦JkGrid an .
■Р" Show rulers
P Show guides
P Show grid
- Grid Size (in Pixels):
W Snap to grid
it
OK
L50 200 250
1 1
Ш^^^^^Н*
60 i
70
80
90
ЕЕ^К.
| Cancel |
1 1
1 1 _ 1
- ^-
Рис. 8.36. Управление линейками и сеткой
368
Глава 8
Измерительные линейки, которые появляются на левой и верхней границах
формы, снабжены цифровыми метками, позволяющими более точно
выбирать положение интерфейсных компонентов. Шаг сетки можно
регулировать с точностью до пиксела или выбирать из раскрывающегося списка.
Команда выравнивания Align Objects (Выровнять объекты) вызывается из
меню Tools (Сервис) или с помощью аналогичной кнопки на панели
инструментов (рис. 8.37).
Push Button
Push Button
Push Button
'Jk.Align Objects
Vertical -^- '■ —^
Allgn
Distribute
Г Setspacncpor;i>-£l?
В
o3
Eps
S*
Ща
S3
qQb
§3
•Horizontal ■
Align '
. Distribute
Г" г:.ц\ sflacina |
p&
§
4
ip|tp ^ 03'
20 nwelf
OK
Apply
Cancel
Рис. 8.37. Окно команды выравнивания компонентов
Перед вызовом команды выравнивания следует выделить выравниваемые
компоненты. Сделать это можно двумя способами — либо обвести
контурным прямоугольником при нажатой левой кнопке мыши (рис. 8.38), либо
нажать и удерживать клавишу <Shift> и щелкать мышью по нужным
компонентам.
Выравнивание выделенных компонентов производится либо по вертикали
(см. группу Vertical (Вертикально) на рис. 8.37), либо по горизонт&чи (см.
группу Horizontal (Горизонтально) на рис. 8.37). Утилита позволяет
выровнять положение компонентов по любой из границ или по центру (для
выбора варианта воспользуйтесь рисунком на кнопках), если будет сделан
щелчок по одной из кнопок ряда Align (Выровнять) и нажата кнопка Apply
(Применить). На рис. 8.39 показано расположение кнопок до выравнивания,
а на рис. 8.40 — после выравнивания по левой границе. Приведенный
пример демонстрирует, что в качестве границы при выравнивании влево
выбирается компонент, расположенный левее всех. При выравнивании вправо
Проектирование интерфейса
369
ведущим становится элемент с самой правой границей, а при выравнивании
по центру выбирается ось, расположенная между центрами самого левого и
самого правого элемента.
•
:
Push Button |
1
m m
Push Button 1
■
Push Button
-- J
i
г ~
г
1
Рис, 8.38. Выделение компонент
Push Button
- ' ■
-
Push Button [
1
.
Pu
■
■Pt
sh Button [
■'
«/.Align Objects РШЦиДЕЩ
1 я—
Align off
Distribute
Г ЙР-tEPilUn
^
„Ли
HJ
]?
№
u~l
□-*
rJL
Si
pi№it.
i Hurlzuntal ;■'-.' -. .
Alien off
Г- T:?! Fp.ii-;»'
w
а|эо"
p
2?
-"■ I
§
Щ?
31
49
|>i?*fS
СЖЛ
Apply
Cancel
Рис. 8.39. Кнопки до выравнивания
Кнопки ряда Distribute (Распределить) позволяют задать расстояние между
соответствующими границами выделенных компонентов. Для выполнения
этой операции следует поставить флажок Set spacing (Установить интервал), а
затем в поле ввода справа задать величину смещения между компонентами.
Кнопки OFF (Выключить) используются для сброса установленных режимов.
370
Глава 8
Push Button
Push Button
Push Button
«JkAlign Objects
Vertical — *■ -
Align off ЧР
Distribute ^3 In-1
St
! Г fiolii'iaarnipij fufAb
Horizontal -
Align
Distribute
OFF
P -ft
IP £P IP
-¾
49
Г Set-ipStingpO ' pixels
■OK - l| '' 'Apply
Cancel
Рис. 8.40. Кнопки после выравнивания по левой границе
Направляющие линии, к которым можно "приклеить" интерфейсные
компоненты, проводятся следующим образом. Наведите курсор на
вертикальную или горизонтальную измерительную линейку, при этом курсор
превратится в двунаправленную стрелку. Если нажать левую кнопку и начать
перемещать мышь, то вслед за ней потянется вертикальная или
горизонтальная прямая синего цвета. Захватив мышью нужный интерфейсный
компонент, его перемешают до контакта с направляющей линией. Несмотря на
режим Snap to Grid (Привязать к сетке), перемещаемые компоненты
"приклеиваются" к направляющей линии, которая не обязана проходить
через узлы сетки (рис. 8.41).
»'
•О
О».
* #
s-
..I.1
0 1
1С 1
"
_
Push Button
I
Push Button
1 1
Push Button
■ 1 1
•
0
Рис. 8.41. Выравнивание по направляющим
Проектирование интерфейса
371
8.3.4. Инспектор свойств
(Property Inspector)
Инспектор свойств вызывается по команде View | Property Inspector (Вид |
Инспектор свойств) или с помощью соответствующей кнопки на панели
инструментов. В левой половине раскрывающегося окна находится список
свойств выделенного объекта, а в правой половине — их значения (рис. 8.42).
При отсутствии выделенной фигуры в окне инспектора отображаются
свойства фигуры.
if untitled.
Eile Edit Mlew
fig
Layout. Iools
gj Property Inspector ЕЮЕЭ1
I И uloontiolCl>ltsM>uHon14"Push Button")
d csa! * ъ.е. i^|*ifi
| ^ Select
CD Push Button
ш» Slider
® Radio Button
Й Check Box
№EdilText
m- Static Text
ЕЭ Pop-up Menu
MLIstbex
ES Toggle Button
fc^Axes
®j Panel
lra Button Group
!=Jf ActiveX Control
id'
3"
to '
ex-
V
ft-
j
ш
0 1
'I
_
Push Button
■
-
-
*- BackgroundColor <5|| 1 *
— BelngDeleted jff
— BusyActlor j»j queue
— ButtonDownFcn
-CDala Щ,
— Callback «.automatic
— Clipping _~j on
-- CreateFcn
— DeleteFcn
— Enable j»J on
4-Extent 10 0 10.857 11
-FontAngle *\ normal
— FontName MS Sans Serif
— FontSire 8.0
— FontUnits ^j points
- FontWeight vj normal
f- ForegroundColor ®] |^Щ^Ц
f- HanaieVlslblllly _V| on
|—HilTesl _vjon
1— HorlzontalAllanment -w\ center jd
<l 1 >"l
Рис. 8.42. Инспектор свойств (выделена кнопка типа Push Button)
Если левее названия свойства виден небольшой квадратик, то значением
свойства является вектор, и доступ к его отдельным компонентам возможен
только тогда, когда свойство "раскрывается". Раскрытому свойству
соответствует знак — в квадратике. Знаки + и — сменяют друг друга при
последовательных щелчках по квадратику. Наличие кнопки с черным треугольником в
правой половине позволяет выбрать значение свойства из раскрывающегося
списка. Кнопка, содержащая кружок с тремя цветными секторами, вызывает
стандартное окно выбора цвета из предлагаемой палитры. На поле значений
свойств можно обнаружить еще одну кнопку, на поверхность которой нане-
372
Глава 8
сен квадратик размером 3x3 с желтыми точками. Значение
соответствующего свойства представлено .матрицей той или иной размерности.
Основное назначение Property Inspector (Инспеюор свойств) — выполнять
на стадии проектирования приложения в среде GUIDE те же самые
действия, которые реализуют функции get и set во время работы приложения,
т. е. просматривать текущие значения интересующих нас свойств или
заменять их новыми значениями.
8.3.5. Просмотр объектов
(Object Browser)
Вызов браузера объектов (рис. S.43), расположенных на форме,
осуществляется командой View | Object Browser (Вид | Просмотр объектов) или щелчком
по соответствующей кнопке на панели инструментов.
Гя Object Browser
НПО
Push Button
*~ Radio Button
Fl ¢3 figure (Untitled)
—И uicontrol (pushbutton^ "Push Button")
<•) uicontrol (radiobuttonl "Radio Button")
Рис. 8.43. Браузер объектов
В окне браузера отображается дерево объектов в порядке их размещения на
форме. Подчиненность ветвей дерева соответствует взаимоотношениям
между объектами-родителями (parent) и объектами-потомками (chidren).
Такого рода просмотр может представить интерес при изучении чужой
программы.
8.3.6. Создание меню (Menu Editor)
Редактор меню (рис. 8.44) имеет две вкладки в нижней части, переключая
которые, можно создавать либо главное (Menu Ваг (Панель меню)), либо
всплывающие (Context Menus (Контекстные меню)) меню. Работа по
созданию меню начинается со щелчка по одной из кнопок: New Menu (Новое
меню) или New Context Menu (Новое контекстное меню).
Предположим, что мы решили создать нестандартное главное меню для
программы решения квадратного уравнения. Пусть первый пункт меню
Подготовка содержит три команды — Ввод а. Ввод b и Ввод с. Во втором
пункте меню Решение разместим четыре команды — Найти корни,
Построить график, Разделительная черта и Выход.
Проектирование интерфейса
373
New Menu
New Menu Item
New
Context
Menu
Move Backward
Selected Item
Move Forward , Move Down
Selected Item ^ Selected Item
Move Up
"Selected
Item
*ДМ«гш Editor
glift -fe 1; ♦—=* i
Delete Selected Item
Menu Bar 1 Context Menus
Properties
i
INoihlnoselectea.
ъ
Help
Рис. 8.44. Кнопки управления редактором меню
Выберем вкладку Menu Ваг (Панель меню) и щелкнем по кнопке New Menu
(Новое меню). Содержимое окна редактора мгновенно изменится (рис. 8.45).
В левой части появился пока безымянный раздел untitled 1, а в правой —
основные свойства этого объекта (UIMenu Properties (Свойства объекта меню)):
□ поле Label (Метка), содержащее название раздела (пока untitled 1);
□ поле Tag (Ярлык), в котором отображается имя указателя на объект;
П раскрывающийся список Accelerator: Ctrl + (Клавиша быстрого вызова),
с помощью такого сочетания клавиш можно быстро вызвать меню или
команду меню;
П флажок Separator above this item (Разделитель перед командой),
позволяющий включить в меню строку-разделитель перед формируемой
командой;
□ флажок Check mark this item (Пометить команду), позволяющий
поставить галочку перед названием команды;
П флажок Enable this item (Разрешить этот пункт), сброс флажка меняет его
окраску и блокирует выполнение соответствующих команд;
□ поле Callback (Реакция на событие), предназначенное для связи
формируемой команды с callback-функцией обработки щелчка по
наименованию команды.
374
Глава 8
«•Л Menu Editor НПО
В •*« Ш ■:;♦*• -* t 1 i 9 -
-ШпИЯПИП
i-
i
i
i"
Menu Bar Context Menus | -y
Label: |unfflled 1
Tag; (UntitledJ
Accelerator: Ctrl +j None J^j
Г" Separator above this Sem
Г Check mark this Hem
17 Enable this Item
.CaHback:|%eutomatic View |
■
■
OK 1 Help |
Рис. 8.45. Начало формирования главного меню
Заменим содержимое поля Label (Метка) на название нашего раздела и
содержимое поля Tag (Ярлык) на более осмысленное имя указателя — input
(рис. 8.46).
*„ifeMenu Editor
Б >=* Ш | ♦- т+ t J. | О
-в
Menu Bar Context Menus
-UIMenu Properties—т •——■
Label: (Подготовка
Tag: |lnput|
Accelerator: Ctrl +1 None
Г* Separator above this Sem
Г" Check mark this item
Г? Enable this Bern
Callback: r&autornatic
.. OK |
d
1
View |:
Help
Рис. 8.46. Формирование первой команды
Проектирование интерфейса
375
Теперь займемся формированием первой команды первого раздела:
1. Щелкнем по кнопке New Menu Item (Новая команда меню), и в окне
появится первая, пока неименованная, команда (untitled 2).
2. Выделим щелчком первую команду.
3. Заменим ее название на "Ввод а", а значение свойства Tag (Ярлык) на
Input_a.
Для формирования следующей команды первого раздела сначала выделим
раздел Подготовка и только потом щелкнем на кнопке New Menu Item
(Новая команда меню). В противном случае вновь создаваемая команда
окажется подкомандой первой команды (т. е. командой меню следующего
уровня). Выделим вторую команду и заменим значения ее свойств Label
(Метка) и Tag (Ярлык).
Снова выделим раздел Подготовка и щелкнем по кнопке New Menu Item
(Новая команда меню). Выделим третью команду и заменим значения ее
свойств Label (Метка) и Tag (Ярлык).
Для формирования меню Решение щелкнем на кнопке New Menu (Новое
меню), выделим новый раздел и сформируем значения его свойств Label
(Метка) и Tag (Ярлык). По описанной ранее схеме создадим команды
второго раздела. Единственная особенность формирования команды Выход
заключается в том, что перед ней необходимо вставить разделительную черту
(рис. 8.47).
«■ДМетш Editor
й *-■ ti I«• ■ ► :
НПО
f- Ц] Подготовка
*** Ввод а
** Ввод b
"— ►=! Ввод С
Э- Ц] Решение
М Найти корни
ия Построить график
Menu Bar | Context Menus
■UIMenu Properties -
(Label: |Выхоя
| Tag: |Exit
Accelerator: Ctrl +| None
I*7 isB§^sr_Ste!SU!!£Jteffil
Г" Check mark this Item;
W Enable this Item
.Callback: %automatic
~3
OK
View
..- Help
Рис. 8.47. Формирование последней команды меню Решение
11 Зак. S99
376
Глава 8
Прежде чем привязывать к командам меню функции — обработчики
события callback, убедимся в том, что сформированное нами меню
соответствует замыслу. Для этого попробуем выполнить созданное приложение, нажав
кнопку Run (Запуск). Система тут же предложит запомнить файлы с
описанием приложения (т- и fig-файлы), выдав окно, представленное на рис. 8.48.
Если файлы с такими именами уже присутствуют в рабочем каталоге, то
будет выдано еще одно предупреждение (рис. 8.49). Оно предлагает на выбор
две возможности — либо заменить предыдущие описания новыми (кнопка
Replace (Заменить)), либо объединить их в одно (кнопка Append (Добавить)).
После ответа на предложения системы на экране появляется приложение с
нашим меню, проверка разделов которого подтверждает правильность
наших действий (рис. 8.50).
[ЗШЗЗ
Q
в
? у Activating will save changes to yourfigure and M-flle.
Do you wish to continue? -^-
F Do not show this dialog again.
I ¥?s._
" ho ■
Рис. 8.48. Предложение сохранить файлы
GUIDE ЕЗ
А
File:
H:\MATLAB7\wortountitled.rri
already exists, Do you want to replace It or append to it?
[„.Replace
Append | Cancel |
Рис. 8.49. Предложение заменить или добавить файлы
|-> roots4
| Подготовка
Ввода
ВвбдЬ
Вводе
Решение
|лА roots4
Подготовка j
Решение
Найти корни
Построить график
' Выход
Рис. 8.50. Внешний вид меню
Проектирование интерфейса
377
При формировании меню возможны ошибки, иногда появляется желание
перекомпоновать последовательность команд, удалить лишние команды.
Для этой цели можно воспользоваться набором кнопок на панели Menu
Editor (Редактор меню) (см. рис. 8.44). Их действие распространяется только
на выделенную команду или выделенный раздел. Четыре кнопки-стрелки
позволяют переместить выделенный элемент (Move Forward Selected Item
(Переместить выделенный элемент вперед), Move Backward Selected Item
(Переместить выделенный элемент назад), Move Up Selected Item
(Переместить выделенный элемент вверх), Move Down Selected Item (Переместить
выделенный элемент вниз)). Последняя кнопка на панели редактора меню
(Delete Selected Item) удаляет выделенный элемент.
Проектирование всплывающего меню имеет небольшие особенности. Во-
первых, у него отсутствует явное название раздела, и поэтому в начальной
заставке (рис. 8.51) нет поля значения для свойства Label. Во-вторых,
всплывающее меню должно быть привязано к конкретному объекту.
Поэтому после создания всплывающего меню его указатель (значение свойства
Tag) должен быть занесен в значение свойства uicontextMenu
ассоциированного объекта.
Создание всплывающего меню начинается с выбора вкладки Context Menus
(Контекстные меню). После щелчка по кнопке New Context Menu (Новое
контекстное меню) -в левой части окна редактора меню появляется указатель
контекстного меню с очередным системным именем untitied_jc. Перед
заменой этого указателя более содержательным наименованием необходимо
щелкнуть по системному имени, после чего в правой части окна редактора
появится поле для изменения значения свойства Tag (Ярлык) — рис. 8.51.
Формирование команд всплывающего меню происходит по описанной
выше схеме:
1. Нажимаем кнопку New Menu Item (Новая команда меню).
2. Выделяем указатель (название) очередной команды в левой части окна.
3. Изменяем значения ее свойств Label (Метка) и Tag (Ярлык).
4. Выделяем указатель (название) меню в левой части окна.
5. Повторяем пункты 1—4 для подключения следующей команды.
В качестве примера приведем вид последнего окна редактора (рис. 8.52), в
котором сформировано всплывающее меню с указателем eolorbutton.
После создания всплывающего меню его надо привязать к объекту — кнопке
типа Push Button, которая будет менять цвет фона при щелчках по
командам меню. Для этого необходимо выделить ассоциированный объект,
вызвать окно Property Editor (Инспектор свойств), щелкнуть по стрелке
свойства urcontexuMenu и выбрать указатель на созданное меню (рис. 8.53).
378
Глава 8
«jtMenu Editor НПЕЗ
-:1йИШ13!11
Menu Bar Context Menus
|Tag: |untitled_1
Callbeclcj%automatic View I
More options » |
f
J.
OK | Help
■
I
Рис. 8.51. Начальная заставка для формирования контекстного меню
да&Мегш Editor
f] ~ Ш I - ■ ► ? £
НПО
I color_tsutton
-^ красный
- *и зеленый
Menu Bar context Menus
UIMenu Properties
Label |c
Teg: |blue_button
Г" Separator above this Hem
I- Check mark this item
R Enable this item
Callback: %automalic
View
More options »
OK
•Help
Рис. 8.52. Завершение формирования контекстного меню
Проектирование интерфейса
379
^Property Inspector H|~1F3
H uloontrol (pushbutton! "Pujh Button")
so 10(
Push Bu
>— HltTest
HorizontalAltsnment
Interruptlfcle
KeyPriessFcn
— LlstboxTop
— Max
-Mln
|фг— Position
SelectlonHigtilight
Д- SllderStep
— String
Style
Tas
Tooltip String
UlContexIMenu
Units
UserData
—Value,
Visible
•И center
■«•Ion
1.0
1.0
0.0
(5 28.0516,429 2.6]
▼Jon
(0,01 0,1]
JF| Push Button
▼| pushbutton
pushburlonl
I""" <None>
H
I Ml ^ со|ш-Ьийоп
If
d<
Рис. 8.53. Связывание всплывающего меню с объектом
После выполнения указанных мероприятий запустим приложение, нажав
кнопку Run (Запуск), и удостоверимся, что при щелчке правой кнопкой
мыши на объекте типа Push Button появляется спроектированное меню
(рис. 8.54).
•> untitled7
Push Button
красны?!
зеленый
синий
Рис. 8.54. Всплывающее меню для кнопки типа Push Button
Формируя главное или контекстное меню, мы до сих пор не
связывали щелчки по командам меню с функциями — обработчиками события
380
Глава 8
callback. В следующем разделе рассматриваются стандартные соглашения
MATLAB 7 по поводу организации таких обработчиков.
8.3.7. Анатомия файла,
создаваемого в среде GUIDE
Для того чтобы разобраться в структуре данных и методах, автоматически
формируемых средой GUIDE при создании интерфейсного файла,
реконструируем пример с двумя кнопками типа push Button, описанный в разд. 8.1.1.
Разместим в графическом окне кнопку типа Push Button, подберем
ориентировочно ее размеры и положение. Редактор GUIDE автоматически
формирует у этой кнопки значения свойств Tag, string и Position. Значения
этих свойств для выделенной кнопки можно рассмотреть и, если
понадобится, изменить с помощью Property Editor (Инспектор свойств) —
рис. 8.55. Заменим значение свойства string на строку кнопка!.
Г-"ft.; ШЫ"-
File Edit; \1\ъщ
f i г
UsjJout To:
Di^@;.Ji Ш т <"
| ^ Select
GEO Push Button
«™ Slider
Ф Radio Button
0 Check Box
* EditTexl
™< Static Text
еэ Pop-up Menu
2-
3-
s
" '■"■!
IP
««I « в p j a e
0 1
0 ISO 20
_
Кнопка1
f
Wj£ Property Inspector НВЕЗ
HO ulcontrol (pushbuttonl "KHontjV')
1 - HifTest
— HoiizonlalWIgrment
j - InterrupllDle
1 - KeyFressFcn
-ListbcxTop
J -Max
| -Mln
a- Position
~- SelectionHiglllight
ji- SllderStep
! Slrinti
'"1
ж
»
■w
on
center
on
1.D
1.0
0.0
17 24,6 21,429 2,551
▼Ion
10.01 0,1]
Ш] Кноша1
I
d
■ f>
Рис. 8.55. Смена надписи на кнопке
Создадим копию кнопки и присвоим ее свойству string значение кнопкаг.
Пока мы не предусмотрели никаких действий по обработке событий
callback для использованных интерфейсных элементов. Однако попробуем
выполнить это пока еще незавершенное приложение — нажмем кнопку Run
(Запуск).
Перед запуском приложения нам предложат запомнить файлы,
автоматически построенные конструктором графического интерфейса. Наберем в
появившемся окне имя twobutton, после чего на фоне файла twobutton.m мы
увидим окно нашего приложения с двумя кнопками Если заглянуть в рабо-
Проектирование интерфейса
381
чий каталог, то мы увидим два файла с названиями twobutton.fig и
twobutton.m. Первый из них описывает окно и интерфейсные элементы
нашего приложения в двоичном формате, поэтому разглядеть в нем что-то
содержательное не удастся. Зато второй представляет обычный m-файл
системы MATLAB, и его содержимое следует пристально изучить. В примере 8.23
приведена распечатка этого файла. Номера строк, предшествующие
операторам, не являются элементами программы. Они вставлены только с целью
приведения в соответствие наших комментариев и строк программы. Пусть
вас не пугает длина m-файла, большая часть его строк представляет
подробный комментарий.
{'Пример;8.ж/Ф^^мюЬШопТт ','№•*$^-¾¾^¾ :-, ^W. »^ ^^^^^/Ш. \
1 function varargout = twobutton(varargin)
2 % TWOBUTTON м-file for twobutton.fig
3 % TWOBUTTON, by itself, creates a new TWOBUTTON or raises
4 % the existing singleton*.
5 % H = TWOBUTTON returns the handle to a new TWOBUTTON or
6 % the handle to the existing singleton*.
7 %
8 % TWOBUTTON('CALLBACK',hObject,eventData,handles,...) calls
9 % the- local function named CALLBACK in TWOBUTTON.M with
10. % the given input arguments.
11 %
12 % TWOBUTTON('Property','Value',...) creates a new
13 % TWOBUTTON or- raises the existing singleton*.
14 % Starting from the left, property value pairs are applied
15 % to the GUI before twobutton_OpeningFunction gets called.
16 % An unrecognized property name ox invalid value makes
17 % property application stop. All inputs are passed to
18 % twobutton_OpeningFcn via varargin.
19 S
20 % *See GUI Options on GUIDE'S Tools menu.
21 % Choose "GUI allows only one instance to run {singleton)".
22 %
23 % See also: GUIDE, GUIDATA, GUIHANDLES-
24
25 % Edit the above text to modify the response to help twobutton
26
27 % Last Modified by GUIDE v2.5 09-Apr-2003 21:43:4В
382
Глава 8
28
29 % Begin initialization code - DO NOT EDIT
30 gui_Singleton = 1;
31 gui_State = struct['gui_Name', mfilename, ...
32 'gui_Singleton', gui_Singleton, ...
33 'gui_OpeningFcn', Gtwobutton_OpeningFcn, ...
34 'gui_OutputFcn', Gtwobutton_OutputFcn, ...
35 'guiJ^ayoutFcn', [] , ...
36 'gui_Callback\ []),-
37 if nargin & isstr(varargin!1})
38 gui_State.gui_Callback = str2func(varargin(l});
39 end
40
41 if nargout
42 [varargout(l:nargout}] = guijnainfcn(gui_State, varargin(:});
43 else
44 guijisinfcn(gui_State, varargin{:));
45 -end
46 % End initialization code - DO NOT EDIT
47
49
49% Executes just before twobutton is made visible.
50 function twobutton_OpeningFcn(hObject, eventdata,...
51 handles, varargin)
52 %-■ This function has no output args, see DutputFcn.
53 % hObject handle to figure
54 % eventdata reserved - to be defined in a future version of MATLAB
55 %■ handles structure with handles and user data (see .GUIDATA)
56 % varargin command line arguments to twobutton (see VARARGIN)
.57
58 % Choose default command line output for twobutton
59 handles. output = hObject;
60
61 % Update handles structure
62 guidata(hobjeer, handles);
63
64 % UIWAIT makes twobutton wait for user response (see UIRESUME)
65 % uiwait(handles.figurel);
Проектирование интерфейса
383
66
6-7 % Outputs from this function are returned to the command line.
68 function varargout = twobutton_OutputFcn(hObject,...
69 eventdata, handles)
70 % varargout cell array for returning output args (see VARARGOUT};
71 % hObject handle to figure
72 % eventdata reserved - to be defined in a future version of MATLAB
73 % handles structure with handles and user data (see GUIDATA)
74
75 % Get default command line output from handles structure
76 varargout{1J = handles.output;
77
78
79 % Executes on button press in pushbuttonl.
SO function pushbuttonl_Callback(hObject, eventdata, handles)
81 % hObject handle to pushbuctonl (see GCBO)
82 % eventdata reserved - to be defined in a. future version of MATLAB
83 % handles structure with handles and user data (see GUIDATA)
84
85 % Executes on button press in pushbutton2.
86 function pushbutton2_Callback(hObject, eventdata, handles)
87 % hObject handle to pushbutcon2 (see GCBO)
88 % eventdata reserved - to be defined in a future version of MATLAB
89 %. handles structure with handles and user data (see GUIDATA)
Строка 1 — это заголовок нашей функции. У нее предусмотрен один
входной аргумент, представленный массивом ячеек varargin (см. разд. 4.6), и
один выходной аргумент, в роли которого выступает массив ячеек
varargout. Это предоставляет нам возможность вызывать из командной
строки наше приложение разными способами:
» twobutton
» hftpp= "twobutton
» twobutton('Position',[10 10 250 200])
» twobutton(xl,x2,x3)
» [yl у2] = cwobutton(...)
Пока мы не планировали никаких входных и выходных параметров для
нашей функции, но в будущем они могут пригодиться. Второй вариант вызова
возвращает указатель на наше приложение после завершения его работы.
Третий вариант обращения, который содержит допустимое для фигуры
384
Глава 8
свойство Position и его конкретное значение, может заставить окно нашего
приложения появиться в заданной точке экрана и трансформировать свои
размеры до указанных ширины и высоты. Четвертый вариант передаст
нашему приложению значения аргументов xi, х2 и хз как ячейки
varargin{i}, varargin{2) и varargin{3). В пятом варианте вызова
запланирован возврат выходных параметров, в роли которых выступят
сформированные приложением значения ячеек varargout{l} и varargout(2}.
Строки 2—25 представляют собой комментарий, дословный перевод
которого мы приводим ниже:
2 % TWOBUTTON представляет m-файл для twobutton.fig
3 % TWOBUTTON без параметров создает новое приложение или продолжает
4 % выполнение существующего одиночного приложения.
5 1 Н = TWOBUTTON возвращает указатель на новое
6 % или существующее приложение.
7 %
8 % TWOBUTTON('CALLBACK',hObject,eventData,handles,...) вызывает
9- % локальную подфункцию с именем CALLBACK
10 % и передает ей указанный список входных аргументов.
11 %
12 % TWOBUTTON('Property','Value',...) создает новое
13 % приложение или продолжает выполнение существующего приложения.
14 % Перед стартом приложения вызывается функция
twobutton_OpeningFunction,
15 % которой передаются, пары параметров ("свойство — значение").
16 % Если параметр Property не является названием свойства или заданное
значение
17 % Value- недопустимо, то приложение не запускается. Все входные
параметры
18 % функции T:wobucton_OpeningFunction передаются ей через varargin.
19 %
20 % См. GUI Options в меню Tools (Сервис).
21 % Выбрано "GUI допускает выполнение единственного приложения
(singleton)".
2.2 %
23 % См. также GUIDE, GUIDATA, GUIHANDLES
24 %
25 % Отредактируй приведенный выше текст, включив в него информацию для
справки.
В строках 29—46 располагаются команды инициализации приложения, и
менять в этих строках ничего нельзя. Здесь устанавливается монопольный
Проектирование интерфейса
385
режим работы приложения (singieton=i), создается структура состояния
приложения (gui_state) и заполняются ее поля. Если при вызове
приложения были указаны входные параметры (nargin>o), то строка с их списком
переносится в массив ячеек varargin и корректируется соответствующее
поле в структуре gui_state. Затем производится обработка списка выходных
аргументов, если таковой присутствовал в команде вызова приложения.
Строки 49—65 занимает так называемая "открывающая" функция со
стандартным именем xxxOpeningFcn (в каждом конкретном приложении
символы ххх заменяются именем m-файла) и фиксированным списком
аргументов — {hObject, eventdata, handles, varargin). Эта функция
работает один раз перед тем, как окно приложения появится на экране
монитора (аналог обработчика события onCreate в системах ВСВ, Delphi),
однако ей доступны указатели на все интерфейсные элементы, расположенные
на форме. И в этой функции можно произвести изменения тех или иных
свойств фигуры и ее компонентов. Входные аргументы "открывающей"
функции имеют следующий смысл:
П hobject — указатель на фигуру (окно приложения);
О eventdata — пустой аргумент, зарезервированный на будущее;
□ handles — структура, содержащая ноля с указателями на все
интерфейсные элементы, установленные на фигуре (в нашем примере таковыми
являются указатели handles.pushbuttonl И handles.pushbutton2);
□ varargin — массив ячеек, который либо пуст, либо хранит значения
входных аргументов, заданных в командной строке.
Особое внимание следует обратить на структуру handles. Изначально она
создается системой с помощью функции guihandies:
handles = guihandies(hObject);
Эта структура передается всем обработчикам событий (callback-функциям)
и доступна всем подфункциям, включенным в GUI-файл. Любая функция
может добавить к этой структуре новое поле, например, с именем
name_f ield, и сформировать там нужное значение (value):
handles.name_field = value;
Для того чтобы новое поле стало доступным другим функциям или
функции-создателю, когда к ней обратятся повторно, содержимое обновленной
структуры надо сохранить в укромном месте:
% запоминание структуры в "памяти" фигуры
guidata(hObject, handles.) ;
% запоминание структуры- в "памяти" СаНЬаск-объекта
guidata(gebo, handles);
386
Глава 8
Если функция не получает структуру handles в качестве входного аргумента,
то она может ее извлечь с помощью той же функции guidata:
handles = guidata(hObject);
handles = guidata(gcbo);
Итак, "открывающая" функция — единственное место, которое принимает и
обрабатывает входные аргументы командной строки. В этой же функции
имеется возможность произвести динамическую перестройку интерфейсных
элементов и их свойств перед тем, как они появятся на экране. По
умолчанию "открывающая" функция выполняет всего две операции — добавляет к
структуре handles поле output, запоминает в нем указатель hobject
(строка 59), а затем сохраняет модифицированную структуру handles
(строка 62).
Вторая функция, которую условно можно назвать "закрывающей",
срабатывает перед завершением работы приложения (аналог обработчика события
OnCancei в ВСВ и Delphi). Ее вызов осуществляет система, передавая ей
следующие входные и выходные аргументы:
varargout = twobutton_OutputFcn(hObject, eventdata, handles)
Основное назначение этой функции — возвратить значения выходных
параметров, сформированные приложением, в командную строку. По
умолчанию она возвращает через массив ячеек varangout содержимое поля
handles.output, т.е. значение указателя на окно нашего приложения
(строка 76). Однако приложение может сформировать и другие выходные
данные, поместив их в какие-то поля структуры handles. П тогда
пользователь должен расширить набор команд в теле "закрывающей" функции
пересылками выходных результатов в ячейки массива varargout с учетом
фактического количества запрошенных данных (nargout).
Наконец, лва оставшихся фрагмента представляют собой заготовки для
функций обработки события Callback, связанного с первой (строки 79—83)
и второй (строки 86—90) кнопками. На самом деле здесь находятся только
заголовки функций, которые GUIDE строит по стандарту, склеивая
значение свойства Tag со словом Callback:
pushbuttonl_Ca.l.lback (hObject, eventdata, handles)
pushbutton2_Callba.ck (hObject, eventdata, handles)
Список входных параметров нам уже знаком. Для содержательной реакции
на щелчки по кнопкам остается добавить по паре строк в каждый из
обработчиков:
84 set(hObject,'String','Нажата 1')
85 set (handles.pushbuttor.2, 'String', 'Кнопка 2') ;
Проектирование интерфейса
387
91 set(hObject,'String','Нажата 2')
92 set(handles.pushbutton!,'String*,'Кнопка l'J;
И теперь наше приложение нормально фиксирует кнопку, по которой
пользователь щелкнул в последний раз (рис. 8.56).
-/ twobutton
:1
$£ Кнопка!
#*
^%#$С
Нежата 2; -
1
f-m .
Рис. 8.56. GUI-приложение с двумя кнопками
Таким образом, разработка приложения с двумя кнопками, которая в
динамическом режиме потребовала написания порядка 20 команд, в среде
GUIDE обошлась нам всего в четыре строчки. Правда, пришлось
потрудиться на стадии размещения интерфейсных элементов и при установке
нужных значений в Property Editor (Редактор свойств). Конечно, объем т-
файла в GUI-приложении существенно превышает размеры программы,
созданной нами вручную.
8.3.8. Использование контейнеров
В среде MATLAB 7 появились два новых компонента — контейнеры типа
panel и Button Group. Используем их для построения в среде GUIDE
приложения, воспроизводящего на экране график одной из трех функций —
sin (л:), cos(jc) или ехр(х). Ранее аналогичная программа обсуждалась в
разд. 81.3
После вызова конструктора интерфейса (GUIDE) попробуем подобрать
размеры графического окна, подобные использованным в разд. 8.1.3. Это
можно сделать двумя способами. Во-первых, можно зацепиться указателем
мыши за черный квадратик, расположенный в правом нижнем углу, и
изменить размер формы на глазок. Во-вторых, после выделения
графического окна можно вызвать Property Editor (Редактор свойств) и в
развернутом свойстве Position задать width=4 80, height-зео. Предварительно
следует установить пикселы в качестве единиц измерения, ибо по умолчанию
установлено Units-characters.
388
Глава 8
Перенесем на левую часть графического окна Panel, которая будет служить
контейнером для осей. Панель улучшает внешний вид приложения. Кроме
того, в надписи над панелью никаких проблем с русскими символами не
возникает. С помощью Property Editor (Редактор свойств) для панели
следует сформировать значение свойства Title (заголовок), можно поварьировать
свойствами шрифта (Font), ВИДОМ И шириной бордюрной рамки (Border).
Положим на панель поле графика (объект axesl). Так как на координатных
осях при построении графика появится разметка, то поля снизу и слева
следует сделать с небольшим запасом (рис. 8.57).
ИГ sincosexp. fig
Ble Edit View Layout lools belp
НПП
Dg£B *%Й. «г-ЦЦ ^^¾ P-
[ 1^ Select
И Push Button
■ Slider
® Radio Button
0 Check Box
Ш Edit Text
.?» Static Text
ЕЭ Pop-up Menu
HUstbox
EsSToggle Button
JfifAces
Построение графика-
т
-Функция—
г sirtM
г cosM
С expfx)
Рис. 8.57. Вид проектируемого приложения в редакторе GUIDE
Разместим в правой части рамку для переключателей — Button Group, в
свойствах которой изменим заголовок. Кроме группировки радиокнопок
рамка будет следить за их переключением во время работы приложения.
Если мы щелкнем по невыделенному переключателю, то ранее выбранный
должен будет автоматически изменить свое состояние (раньше мы это
поведение программ и ров&ч и сами). Для разнообразия изменим и вид границы
вокруг рамки (BorderType=beveledin).
Для радиокнопок, помещенных в рамку, надо выдержать одинаковые
размеры. Этого можно достичь клонированием компонентов или установкой у
Проектирование интерфейса
389
иих одинаковых свойств в массиве Position. Затем с помощью редактора
Align Objects (Выравнивание объектов) выровнять их по вертикали и задать
одинаковое смещение между объектами.
Теперь можно проконтролировать внешний вид приложения в работе, хотя
ни одной строчки кода мы сами еще не написали. Запустим приложение
(команда Tools | Run (Сервис | Запуск)). Если наше приложение еще ни разу
не запоминалось и сохраняет стандартное название untitled.fig, то система
предложит его сохранить в текущем каталоге. При этом мы увидим поле
редактора кода, в котором конструктор интерфейса сформировал изрядное
количество строк. После запуска на экране появится графическое окно
нашего приложения, и если его внешний вид (рис. 8.58) нас удовлетворяет, то
пора приступать к программированию обработчиков событий. До этого вы
можете убедиться в том, что кнопки переключаются нормально, хотя с
изменением их состояния никаких действий еще не запрограммировано.
*/ sincosexp
1
0.8
0.6
0.4
0.2
•
■) 0.2 0.4 0.6
- -
НПО
0.8 -. 1
"
;
г sinM
<~ cosft)
С ехр(х)
1
Рис. 8.58. Вид полуфабриката приложения после его запуска
Возвращаемся в среду GUIDE и попробуем написать обработчик события
при выборе переключателя sin(x). Выделяем эту радиокнопку и выполняем
команду View | View Callbacks | Callback (Вид | Отобразить Callback-функции |
Callback) — рис. 8.59.
Конструктор интерфейса формирует заготовку для обработки указанного
события и переводит нас в окно редактора кода на позицию, которую
пользователь должен заполнить (пример 8.24).
390
Глава 8
View
Property Inspector
Object Browser
M-file Editor . ..
Vlew Callbacks ►
.Callback |
CreateFcn
DeleteFcn
ButtonDownFcn
KeyPressFcn
Рис. 8.59. Переход в тело Callback-функции
[ Пример 8.24. Функция radiobuttonljCailbacid . .,.^¾.,,.._■•■ Vy? f.^ • »*•
% Executes on button press" in radiobuttonl.
function radiobuttonl_Callback(hObject, even'tdata, handles)
% hObject handle to radiobuttonl (see GCBO)
% evencdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%. Hint: get(hObject,'Value') returns toggle state of radiobuttonl
Комментарий в первой строке свидетельствует о том, что функция
выполняется при щелчке по радиокнопке radiobuttonl. Среди параметров,
передаваемых функции, важны первый и третий. Первый является указателем на
объект, инициировавший событие callback, т. е. на радиокнопку radiobuttonl.
По свойству value этого объекта мы определим, выделена ли данная
радиокнопка (vaiue=i) или нет. В первом случае необходимо построить граФик
функции sin(jc), во втором — почистить поле графика. Однако^и перед
построением графика, и перед очисткой его поля необходимо активизировать
объект axesi. Если этого не сделать, го и в результате выполнения функции
plot, и в результате работы функции cla будет автоматически создан новый
объект, который сведет на. нет все наши дизайнерские труды. Новое поле
графика расположится поверх нашей заготовки и наедет на рамку с
кнопками. Поэтому наша добавка к обработчику события callback выглядит так,
как в примере 8.25.
j Пример 8.25. Добавляемый фрагмент кода ' [ 'Щ" ,е>,*'С^''^']
axes(handles.axes!) % активизация поля графика
if(get(hObject,'Value')==1) % проверка состояния радиокнопки
Проектирование интерфейса
391
x=0:0.1:2*pi;
y=sin (х) ;
plot(х,у);
else cla
end
% построение графика sin (>.)
% очистка поля графика
Обработчики событий от двух остальных радиокнопок строятся по
идентичной схеме. Результаты запуска приложения (рис. 8.60) показывают, что
левое поле с оцифровкой оси у следует немного расширить.
-)■ sincosexp
г _ — Построение графика -
0.5
П
0.5
1
/
/
/
Ч
\
\
\
\
\
\
. \
/ ■
/
ЯПЕЭ
(-функция
"■ sinfx)
(~ cos(x)
С ежрМ
•> sincosexp
„.. Построение графика-
500
№0
300
200
.100
О
0
.
у
^
I
I
1
/
/
ипн
г Функция— г
С sinfx)
Г соеМ
Р ехрМ
Рис. В.60. Результаты работы приложения sincosexp
Глава 9
Стандартные диалоговые окна
Расширению интерфейсных возможностей приложения способствуют
многочисленные диалоговые окна, реализованные в системе MATLAB. Их
перечень приведен в табл. -9.1.
Таблица 9.1
Наименование
Назначение диалогового окна
dialog Создание и отображение диалогового окна общего назначения
errordlg Создание и отображение диалогового окна с сообщением об
ошибке
helpdlg Создание и отображение диалогового окна помощи
inputdlg Создание и отображение диалогового окна ввода
listdlg Создание и отображение диалогового окна со списком для
выбора
msgbox Создание и отображение диалогового окна с сообщением
pagedlg Отображение диалогового окна для настройки параметров
страницы
printdlg Отображение диалогового окна для настройки параметров
печати
questdlg Создание и отображение диалогового окна с запросом
uigetf ile. Отображение диалогового окна для извлечения имени файла
для чтения
uiputf ile Отображение диалогового окна для извлечения имени файла
для записи
uisetcolor Отображение диалогового окна для установки цвета
uisetf ont Отображение диалогового окна для установки параметров
шрифта
warndlg Создание и отображение диалогового окна с предупреждением
394
Глава 9
9.1. Диалоговое окно
общего назначения (dialog)
Функция dialog создает и отображает диалоговое окно общего назначения,
которое отличается от стандартного окна типа figure отсутствием меню и
панели инструментов, неизменяемыми размерами, свойством модальности
и др. Формат вызова функции таков:
h = dialog (' Свойство_1', Значекие_1, . . .)
Функция создает специализированное графическое окно (фигуру),
устанавливает свойства, рекомендуемые для диалогового окна, и возвращает
указатель на созданный объект. Перечень рекомендуемых свойств и
соответствующие значения по умолчанию приведены в табл. 9.2. Кроме них могут
быть использованы любые лругие свойства, характерные для объектов типа
figure.
Таблица 9.2
Свойство
Значение
Пояснение
BackingStore
BuLiionDownFcn
Colormap
Color
HandleVisibility
IntegerHandle
InvertHardcopy
off
if iserapty(allchild
(gcbf)>, close(gcbf),
end
[]
DefaultUicontrol
BackgroundColor
callback
off
off
MenuBar
NumborTitle
PaperPosi tion
Mode
Resize
Visible
WindowStyle
none
off
auto
dff
on
modal
ОС Windows не запоминает
окно для восстановления
при перекрытии
Реакция на нажатие
клавиши
Рисунок отсутствует
Цвет фона — серый
Указатель — вещественное
число
Не инвертировать цвет при
печати
Меню отсутствует
Заголовок отсутствует
Размещение на листе при
печати
Запрещена возможность
изменять размеры
Видимое окно
Модальный стиль
Стандартные диалоговые окна
395
9.2. Окно с сообщением
об ошибке (error dig)
Окно с сообщением об ошибке является частным случаем диалогового окна
общего назначения. Оно создается и отображается в результате вызова
функции errordlg, которой может быть передано до трех параметров:
errordlg
errordlg('сообщение') i
errordlg('сообщение','заголовок')
errordlg('сообщение','заголовок','on')
h = errordlg(...)
В первом случае создается и отображается диалоговое окно с характерным
знаком (рис. 9.1). По умолчанию заголовком окна является текст Error
Dialog, а В поле окна находится текст "This is the default error string".
Пользоваться таким окном смысла не имеет, т. к. оно никакой
содержательной информации не несет.
Во втором случае текст сообщения об ошибке воспроизводится как заданная
строка, однако заголовком окна является текст по умолчанию — Error
Dialog.
Наиболее употребительным является третий вариант, когда и текст
сообщения об ошибке, и заголовок окна задаются пользователем. Например:
>>errordlg('Деление на 0','Ошибка')
Окно, появляющееся в результате выполнения этой команды, приведено на
рис. 9.1.
•> Ошибка
f- 'Л Деление на 0
OK
Н9ЕЗ
Рис. 9.1. Окно с сообщением об ошибке
Четвёртый вариант вызова функции errordlg имеет смысл, если окно с
таким же заголовком выдавалось ранее и было свернуто пользователем. В этом
случае текст сообщения об ошибке подменяется на новый, а само окно
раскрывается, выходя на передний план. Если окна с указанным заголовком не
существовало или предыдущее окно было закрыто пользователем, то
создается новое окно.
396
Глава 9
Модальный стиль диалогового окна с сообщением об ошибке означает, что
пользователь обязан щелкнуть либо на кнопке ОК (эквивалент — нажатие
клавиши <Eiuer>), либо свернуть, либо закрыть окно (т. е. произвести одно
из перечисленных обязательных действий для продолжения работы
программы). Щелчок на кнопке ОК приводит к исчезновению окна.
Размер окна подбирается системой автоматически таким образом, чтобы
текст сообщения поместился в окне. Если в текст сообщения включены
управляющие символы (перевод строки, возврат каретки), то в диалоговом
окне появится многострочный текст.
При любом варианте обращения функция errordig возвращает указатель на
созданное окно, однако это значение обычно никому не нужно.
9.3. Окно со справочной
информацией (heipdig)
Диалоговое окно со справочной информацией создается и отображается в
результате вызова функции heipdig, которой может быть передано до двух
параметров:
heipdig
heipdig{'справка')
heipdig('справка','заголовок')
h = heipdig(...)
Единственное отличие окна помощи or окна с сообщением об ошибке
заключается в характерной картинке, сопровождающей текст. Если не задай
текст справки или заголовок окна, то им присваиваются значения по
умолчанию — "This is the default help string." И Help Dialog. В наиболее
употребительном варианте вызова пользователь задает оба параметра;
>> heipdig('По умолчанию eps=2.220446049250313e-016','Помощь')
Результат выполнения такой команды приведен на рис. 9.2.
•> Помощь ННЕЭ
По умолчанию eps=2,2204<1604925031
ОК
Рис. 9.2. Окно со справочной информацией
Стандартные диалоговые окна
397
9.4. Стандартное окно
для ввода строк (inputdlg)
Если в приложении не предусмотрены интерфейсные компоненты типа
Edit Text, то наиболее удобным средством ввода текстовой информации во
время выполнения программы являются стандартные диалоговые окна типа
inputdlg. Они создаются и отображаются в результате обращения к
функции inputdlg, которой может быть передано до пяти параметров:
res = inputdlg({подсказка))
res = inputdlg((подсказка},'заголовок *)
res = inputdlg!{подсказка},■заголовок',iineNo)
res = inputdlg({подсказка},'заголовок',IineNo,def_res)
res = inputdlg({подсказка},'заголовок',IineNo, def_res,'on')
res = inputdlg({подсказка},'заголовок',IineNo,def_res,'off')
Первый аргумент представляет собой массив ячеек, значения строк которых
отображаются над полями ввода. Количество полей ввода, одновременно
отображаемых в ди&чоговом окне, определяется количеством элементов в
массиве подсказка. Например:
» ху = inputdlg({'к of center','у of center'},'Задайте координаты
центра')
Выполнение этой команды приводит к появлению диалогового окна с двумя
полями ввода (рис. 9.3). Возвращаемое функцией значение в этом случае
также представлено массивом ячеек, содержащим две строки,
присваиваемые соответственно переменным ху(1) и ху(2). Главной неприятностью
для отечественных пользователей является то, что подсказка, появляющаяся
над строкой ввода, должна набираться латинскими буквами.
Задайте
х of center
координаты
.-■ ea
|10D
у of center
(120
OK
Cancel
Рис. 9.3. Диалоговое окно с двумя полями ввода
Дополнительное неудобство диалогового окна ввода заключается в том, что
текстовый курсор для набора вводимых строк не появляется автоматически
398
Глава 9
в одном из полей ввода, и пользователь должен лишний раз щелкнуть,
прежде чем начать набор запрашиваемых данных. После завершения набора
строки не имеет смысла нажимать клавишу <Enter>, т. к. она не переводит
курсор в следующее поле ввода, а возврашает его в первую позицию
текущего поля. В очередное поле курсор набора переводится вручную —
щелчком мыши по области ввода или нажатием клавиши <Tab> (<Shift>+<Tab>).
По завершению набора вводимых данных необходимо щелкнуть на кнопке
ОК, и только тогда набранные строки будут возвращены функцией, а
диалоговое окно исчезнет:
х-у =
400'
420'
Перевод в числовой формат программа должна сделать сама, используя,
например, функцию str2num.
Щелчок на кнопке Cancel (Отмена) или закрытие окна приводят к тому, что
функция возвращает пустой массив ячеек.
Параметр lineNo определяет количество строк, допустимых в каждом из
полей ввода. Он может быть задан скалярным значением, и тогда указанное
число относится ко всем полям ввода, присутствующим в диалоговом окне.
Если этот параметр задан вектором-столбцом, то каждый его элемент
определяет количество строк в соответствующем поле ввода. Параметр lineNo
может быть задан и матрицей размерности тхг. Первый столбец этой
матрицы определяет этажность полей ввода, а второй столбец — ширину
каждого ноля ввода в символах. Если в поле ввода разрешено набрать более чем
одну строку, то соответствующий результат будет представлен массивом
ячеек, в котором значением каждого элемента является очередная строка из
поля ввода.
Параметр def_Ans определяет значение по умолчанию, которое
воспринимается как результат ввода, если пользователь ничего не набирает в том или
ином окне ввода. Если диалоговое окно содержит несколько полей ввода, то
параметр defAns должен быть задан массивом ячеек соответствующей
размерности.
Последний параметр, принимающий одно из двух значений (on или off),
определяет, может ли окно изменять свои размеры или нет. Значение on
означает, что диалоговое окно может изменять свои размеры и не является
модальным.
Приведем пример 9.1.
Стандартные диалоговые окна
399
;; Пример 9.1. Ввод данных с помощью диалогового окна *-- -'■ •?&■& ,.*;
prompt = {'Dimension- of matrix:','Name of colormap:'};
title = 'Параметры для функции peaks';
lines = 1;
def = {'20','hsv.'};
answer = inputdlg(prompt,title,lines,def);
В этом примере создается диалоговое окно с двумя полями ввода, первое из
которых предназначено для задания размерности области определения
функции peaks (по умолчанию будет принято значение 'го'), а второе — для
выбора названия палитры (по умолчанию будет принято значение 'hsv')
9.5. Окно выбора из списка (listdlg)
Стандартное диалоговое окно listdlg по своему функциональному
назначению мало чем отличается от интерфейсного элемента типа List box. Оно
создается в результате обращения к функции listdlg, которой передается
список строк iist_str (значение свойства Liststring) и набор харакгери-
стик окна в виде пар "свойство — значение":
[sel_str, ok] = listdlg('Liststring',list_str,...
' Свойсггбо_1 ', Значение_1, . ..
'Свойство_2',Значение_2,...
'Свойство_к',Значение_к)
Последовательность задания пар "свойство — значение" может быть любой,
и список строк не обязательно указывается первым. Список строк liststr
обычно представлен массивом ячеек, каждым элементом которого может
быть строка переменной длины.
Рассмотрим пример 9.2.
I Пример 9.2. Выбор файла - - , ., , "
» d = dir;
» str = {d.name};
» [ind,ok] = listdlg('Liststring',str,...
'FromptString','Выбор файла',...
'SelectionMode','single')
400
Глава 9
В приведенном примере список строк представлен именами файлов
текущего каталога, и в результате выполнения указанных команд появляется
окно, представленное на рис. 9.4.
Задание значения свойства stringList в этом примере очень упростила
команда dir, которая извлекает список полных спецификаций всех файлов
текущего каталога (в приведенном примере текущим каталогом оказался
рабочий каталог MATLAB — с:\МАТЬАВД№огк). Дополнительно заданные
значения свойств определили подсказку над списком (свойство
Promptstring) и режим выбора (свойство SelectionMode) единственной
строки (значение — single).
ННИ^Ш^^А^]
Выбор файла
ж
GUI 3.fig
GUI_3.m
Un'itlecQ.m
a.txt
sbc.m
aero.jpg
array2vec.asv
array2vec.m
bultonqroup.asv
buttcrijioupl.asv
buttongroupt.m
buttongroup2.m
cbl.asv
cbl.m
cb2. asv
Г.1Й 3P.V !
OK
Cancel
[
Рис. 9.4. Диалоговое окно
для выбора единственного файла
Для выбора нужной строки можно щелкну!ь по ней (цвет этой строки
изменится), а затем нажать кнопку ОК или клавишу <Enler>. В упрощенном
варианте достаточно выполнить двойной щелчок па выбираемой строке.
В любом из перечисленных случаев функция возвратит два целочисленных
значения. Первое из них, присваиваемое в нашем примере переменной ind,
определяет индекс выделенной строки. Второе значение, присваиваемое
переменной ok, может быть равно г, если пользователь сделал выбор, или о,
если он от выбора отказался. Последнее происходит, если нажимается
Стандартные диалоговые окна
401
кнопка Cancel (Отмена) или принудительно закрывается окно. Отказ от
выбора приводит к возврату пустого множества (ind=n). Результат выбора
файла buttongroup.m в приведенном выше примере выдает на экран
результаты, нуждающиеся в пояснении:
ind
ok
12
Строка с указанным именем действительно находится в двенадцатой
позиции отображаемого списка. Первая и вторая строки в соответствии с
правилами Windows заняты точкой (признаком наличия корневого каталога) и
двумя точками (признаком наличия каталога предыдущего уровня).
Конечно, числовой индекс — еще не само значение выбранной строки, но с
его помощью нетрудно получить имя. выделенного файла:
» str(12)
ans =
'buttongroup.m'
Выбор файла
GUIJ.fig
GUI 3.m
Urititled2.m
a.trt
abc.m
aerd.'
array2vec. asv
array2vec.m
buttcngroup.asy
мШшдПТцШШшМ!
buttDngroupl.asv
bultonqrougl.m
итыЖ
cbl.asv
bl.m
cb2.asv
cb2.rn
r_h3 asv
Select all
_J
OK
Cancel
Рис. 9.5. Множественный выбор
402
Глава 9
Значение свойства seieetionMode по умолчанию равно multiple, что
позволяет сделать множественный выбор. В этом случае в диалоговом окне
появляется третья кнопка с надписью Select all, обеспечиваюшая выбор всех
строк отображаемого списка (рис. 9.5).
В случае множественного выбора первое возвращаемое значение представлено
вектором, компоненты которого совпадают с индексами отмеченных строк
(технология выделения нескольких строк подробно обсуждалась в гл. 8).
Список свойств, значения которых так или иначе влияют на внешний вид и
функционирование окна listdig, приведен в табл. 9.3.
Таблица 9.3
Свойство
ListSize
Select i.onMcde
InitialValue
Name'
PromptString
OKString
CancelString
uh
.fus
Описание
Ширина и высота списка в пикселах
задается в векторе [width height]
Режим выбора — единичный (single)
или множественный (multiple)
Вектор, определяющий начальное
выделение
Заголовок диалогового окна
Массив строк или массив ячеек строк,
который появляется над списком в
качестве пояснительного текста
Строка с надписью кнопки ОК
Строка с надписью кнопки Cancel
(Отмена)
Высота кнопок в пикселах
Зазор между рамкой и списком в
Значение
по умолчанию
[160 300]
multiple
1, что соответствует
первой строке списка
Пустая строка
]) — пустой массив
ОК
Cancel
18
В
ffs
пикселах (Frame/uicontrol
spacing)
Зазор между рамкой и границей окна
в пикселах (Frame/figure spacing)
9.6. Диалоговое окно
с сообщением (msgbox)
Функция msgbox создает и отображает диалоговое окно, в котором текст
сообщения может сопровождаться значком, характерным для окон типа
Стандартные диалоговые окна
403
errordlg, helpdig, warndig. По желанию пользователя в окне может быть
отображена произвольная картинка.
Существует несколько форматов обращения к функции msgbox:
msgbox (сообщение)
msgbox(сообщение,'заголовок')
msgbox(сообщение,'заголовок', 'значок')
msgbox(сообщение,'заголовок','cusrom',icon_data,icon_color_map)
msgbox (...,' регеим')
h = msgbox(...)
Текст сообщения задается вектором-строкой, массивом строк равной длины
или массивом ячеек со строками разной длины. При необходимости
длинный текст автоматически разбивается на строки так, чтобы поместиться по
ширине окна.
Текст заголовка переносится в заголовок окна.
В качестве параметра значок может выступать одна из строк: none', 'error',
'help', 'warn' или 'custom'. По умолчанию создается диалоговое окно без
картинки, что эквивалентно заданию параметра "попе". Для создания окна с
картинкой по выбору пользователя после параметра custom должны быть
указаны данные (icondata — графический образ) и цвет (icon_map_coior).
В качестве необязательного параметра режим может быть задана одна из
строк: modal', 'non-modal' ИЛИ 'replace'. В первом случае окно будет
модальным, во втором — немодальным, а в третьем оно заменит
предшествующее окно с таким же заголовком.
9.7. Интерактивная настройка
параметров страницы (pagedlg)
Функция pagedlg предназначена для установки параметров страницы, на
которой предполагается напечатать текущую или указанную фигуру-
В системе MATLAB 7 она считается устаревшей, вместо нее предлагается
более современная версия pagesetupdlg. Однако вы можете обратиться как
к новой, так и к устаревшей функции. Последняя допускает вызов без
параметров, если речь идет о текущем графическом окне, или с единственным
аргументом — указателем на другое графическое окно.
pagedlg(hFig)
После вызова функции pagedlg появляется окно, представленное на
рис. 9.6. Некоторые поля этого окна содержат неизменяемую информацию.
404
Глава 9
например, габариты листа бумаги, заправленной в принтер (Paper Size
(Размер листа)). Указанный на рисунке формат слегка отличается от
принятого у нас стандарта А4 (210x297 мм). Единицы измерения длины (Paper
Units) можно сменить на более привычные. В зависимости от соотношения
ширины к высоте можно выбрать либо портретную, либо альбомную
ориентацию изображения на странице (Paper Orientation (Ориентация листа)).
В правой области автоматически воспроизводится силуэт фигуры, которую
предполагается отпечатать.
-> Page Position: Figure 1
Paper Size: [2D.S84 29.677J
Paper Units. jcentirTIBters J
Paper Onentalion: | po[1ra|| J
С Malch Paper Area to Figure Area
f Set Paper Position Explicitly
• Paper Position
Default Paper Settings
Center
Help
Print...
г ■*
BHQ
' llCL.63452 6.3452 20.305 15.228]
Fill
FillfFixed Aspect Ratio)
Cancel
Done
Рис. 9.6. Окно настройки параметров страницы
При печати фигуры имеется возможность произвести ее масштабирование
под размер бумаги (Match Paper Area to Figure Area (Согласовать размеры
листа и рисунка)) или потребовать точного соблюдения размеров
выводимого изображения (Set Paper Position Explicitly (Установить положение
рисунка па листе)). Поле Paper Position (Положение листа) позволяет задать
прямоугольную область на странице, в которую должна быть вписана
выводимая фигура. Кнопка Default Paper Settings (Установки листа по
умолчанию) позволяет восстановить значения параметров страницы, заданные по
умолчанию. С помощью кнопки Fill (Заполнить) можно растянуть
выводимое изображение на всю страницу. При этом масштабирование по ширине
и высоте производится с разными коэффициентами, что может привести к
не очень удачным пропорциям (для преобразований такого рода используют
Стандартные диалоговые окна
405
термин анизотропное). В отличие от этого, кнопка FiII(Fixed Aspect Ratio)
(Заполнить с сохранением масштаба) осуществляет изотропное
преобразование, при котором производится изменение масштаба с сохранением
исходных пропорций. Кнопка Center (По центру) перемещает выводимое
изображение в центр листа бумаги. Кнопка Print (Печать) вызывает диалоговое
окно печати, в котором можно выбрать принтер, установить его свойства,
отпечатать заданное количество копий или направить образ выводимой
страницы в файл.
9.8. Диалоговая страница
(pagesetupdlg)
Новое диалоговое окно для выбора параметров страницы встроено в главное
меню File | Page Setup (Файл | Параметры страницы). При вызове функции
pagesetupdlg появляется окно, приведенное на рис. 9.7.
Достаточно подробно характеристики этого окна и всех его вкладок
рассматривались в разд. 2.6.5.
Page Setup - Figure 1 Q
Size and Position | Paper ) Lines and Text ) Axes and Figure )
Mode
С Use screen size, centered on pagel
P Use manual size and position
Manual size and position -
Top: |ё~ш |J
Left: |oJ5 g •
Width: |го.зо |["
Use defaults
FIN page
Fix aspect ratio
HeiBhl |йя Ц
Unitsj centimeters -^] '
Center
Help..
OK
Cancel
Рис. 9.7. Диалоговое окно pagedialogsetup
406
Глава 9
9.9. Окно настройки параметров печати
(printdlg)
Диалоговое окно, предназначенное для установки параметров печати,
появляется в результате обращения к функции printdlg (рис. 9.8).
Она допускает несколько форматов вызова:
printdlg
printdlg(hFig)
printdlg('-crossplatfoim1, hFig)
printdlg!'-setup',hFig)
Печать
- Принтер
Имя.
[Symantec Fax Starter Edition
Состояние- Готов
Тип: OLFAXDRV
Место: OLFModem
-г I Свойс
Комментарий; Отправка факса выполняется путем печати р~ Печать в файл
Диепазон печати
<• Есе
Г L'Tqjfc-V-ui &'
С Виде,ic-iiHHp Фрй|'-itn;
-Копии-
Число копий: |1 ^fj
OK j Отмена
Рис. 9.8. Стандартное окно установки параметров печати
(принтер на данном компьютере не установлен)
Указатель hFig задается в том случае, если предполагаемые установки
относятся к графическому окну, которое не является текущим. Параметр
-crossplatform отображает диалоговое окно для подготовки печати на
кросс-платформах Microsoft Windows и Macintosh. При его задании
появляется окно, представленное на рис. 9.9. Основная особенность этого окна
заключается в большом количестве доступных, драйверов прингеров, вывод
на которые возможен либо с использованием сетевых устройств печати,
либо путем подготовки файлов и переноса их на другие компьютеры.
Раскрывающийся список Driver (Драйвер) включает более 30 позиций, полный пе-
Стандартные диалоговые окна
407
речень которых приведен в табл. 9.4. Не менее впечатляет список
возможностей, открывающихся по кнопке Options (Опции) — рис. 9.10.
Print:
-Destination
"■ printer;
(~ File:
Driver:
i
Figure 1
E3
OLFNufteni
■
Windows j»j
г Figure Size on Printed Page
! f~ Same size as screen
1 С 20,3 by 15,2 cm
Help..
~— - ■-
Brof'sc-
Options...
f Same as onscreen.
6 Allow MATUB to select
OK
Cancel 1
Рис. 9.9. Окно настроек для кроссплатформного вывода
Таблица 9.4
№
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Драйвер принтера
Windows
Color Windows
Postscript
Postscript Color
Postscript Level 2
Postscript Level 2 Color
HPGL
HP LaserJet
HP LaserJet Plus
HP LaserJet Ild/llp
HP LaserJet III
HP LaserJet 4/5L/5P
HP LaserJet 5/6
HPDeskJet 500C 24 bitcolor
HPDeskJet 500C b+w
HPDeskJet / HPDeskJet Plus
№
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Драйвер принтера
HP DeskJet
550C/560C/660C/660Cse
HP DeskJet 500C/540C
HP DeskJet 500C
HP PaintJet
HP PaintJet XL
HP PaintJet XL (alternate)
HP PaintJet XL 300
HP DesignJet 650C
Cannon BubbleJet 10c
Cannon BubbleJet 200
Cannon BubbleJet 600/4000/700
Cannon BubbleJet 800
Epson
Epson LQ-2550
Epson 9-pin
IBM Proprinter
I4 3ok 899
408
Глава 9
Printing Options
Select optional Input arguments for PRINT command.
See on-Iine.help of PRINT command for mora Information.
Q
Г |Jse loose bounding box for PB and Ghostscrlpt drivers! -
Г Use CMYK colors In PS and Ghostscrlpt drivers Instead of RGB
Г Use Adobe PS default character set encoding
I~ Suppress printing of user Interface controls
Handle Graphics Renderer —
<♦ Have MATLAB select based on complexity of graph
<~ Render using painter's algorithm
С Render using Z-buffer
<~ Render using OpenGL
Printing Resolution -
& Have MATLAB select based on renderer and driver
<"* Use same resolullon as the screen
<~ Specify resolution In dols per inch: I
OK
Cancel
9.10. Окно дополнительных настроек режима печати
Обращение printdig {' -setup', fig) вынуждает диалоговое окно появиться
в режиме установки.
9.10. Диалоговое окно
с запросом (questdlg)
Диалоговое окно, содержащее запрос, создается и отображается с помощью
функции questdlg, которой передаются от одного до шести параметров:
btn = questdlg('запрос')
btn = questdlg('запрос','заголовок')
btn = questdlg('запрос','заголовок','default')
btn = questdlg('запрос','заголовок','btnl','btn2','default')
btn = questdlg('запрос','заголовок','btnl','btn2','btn3','default')
Первый аргумент представлен строкой, содержащей текст запроса. Второй
аргумент, если он задан, воспринимается как заголовок окна.
Стандартные диалоговые окна
409
По умолчанию окно является модальным и содержит три кнопки: Yes (Да),
No (Нет), и Cancel (Отмена). Граница кнопки Yes (Да) выглядит немного
жирнее, и щелчок на ней эквивалентен нажатию клавиши <Enter>.
В третьем варианте обращения параметр default может быть одной из
строк вида 'yes', W или 'cancel'. Его значение определяет кнопку, которой
ставится в соответствие нажатие клавиши <Enter>.
Четвертый и пятый варианты предоставляют пользователю возможность
задавать на двух или трех кнопках надписи по своему усмотрению. В этих
случаях строки 'btnl', 'btn2' и 'btn3' задают нестандартные надписи.
Параметр default, если он задан, должен совпадать с одной этих строк. Его
значение определяет, какой из кнопок соответствует нажатие клавиши <Enter>.
Если пользователь закроет окно, не нажав ни одной кнопки, то значением
функции является пустая строка.
В любом случае функция questdig возвращает строку с надписью нажатой
кнопки. Анализируя значение переменной btn, программа может узнать,
как ответил пользователь на выставленный запрос.
» a = questdig('Продолжить ?','Ваш выбор');
» if a=='Yes'...
В результате вызова функции questdig на экране появляется окно
(рис. 9.11).
Ваш выбор
\У J Продолжить
. 1 Yes | No |
?
Cancel
□
1
Рис. 9.11. Интерактивный запрос
9.11. Выбор имени файла
для чтения (uigetfile)
Диалоговое окно, обеспечивающее возможность выбора имени файла из
текущего каталога (рис. 9.12), появляется в результате вызова функции
uigetfile:
[file_name,file_path]=uigetfile('*.m','Выберите файл')
410
Глава 9
Выберите файл
НО
Папке: |'—' work
£j.abc
Earray2vec
fibuttongroup
Bbuttongroupl
£]buttongroup2
Qcbl
Ecb2
«I
Ucb3
Srb4
Scheckl
fDedit textl
fifed
■Ejfern
"EjGUI 3
d-
yiistl
■Elist2
■Elpstal
■Ejpolyline
fipopup_menu
"tDpcipup_menul
fipcpup menu2
I
Ec* m-
fipr8_26
Qpushbtn
fipushbtni
Cjpuahbtri5
Sradiol
firoots2
&oots3
e
£
4
Имя файла |
Тип файлов: |M-filesC".m)
Открыть
"3
Отмена
Рис. 9.12. Интерактивный выбор файла дли чтения
Первый аргумент играет роль фильтра, ограничивающего список имен
файлов, отображаемых в диалоговом окне. Второй аргумент воспринимается как
заголовок окна. Выбор файла может быть сделан либо щелчком по имени,
либо путем набора имени файла с клавиатуры. После выбора имени файла
пользователь может нажать кнопку Открыть (Done), отказаться от выбора
щелчком по кнопке Отмена (Cancel) или путем закрытия окна. Если файл
выбран и нажата кнопка Открыть (Done), то функция возвращает две
строки с именем файла и полным путем к файлу. В приведенном выше примере
строка с вызовом функции не завершается точкой с запятой, поэтому после
выбора файла возвращаемые значения выводятся в командное окно:
file_name =
Animl.m
£ile_path =
C:\MZYTLAB7\work\
Если пользователь отказывается or выбора, то функция возвращает два нуля:
file_name =
б
file_path =
О
Набор имени несуществующего файла приводит к появлению окна с
сообщением об ошибке (рис. 9.13). После нажатия кнопки ОК вы можете
набрать имя другого файла или отказаться от выбора.
Стандартные диалоговые окна
411
Выберите файл
целка: | LJ work
ВЕЗ
~^~1 <- Eg с* ШЬ-
fiabc
Qarray2vec
Bbuttongroup
fibjttongroupl
fibuttongroup2
tlcbl
ficb2
4 |
ficb3
■ВсЫ
ficheckl
Oedit textl
Qfed
fifern
€lGUI_3
-fcjlisti
fillst2
fipetal
fipolyllne
fipopup menu
fipopup menul
fipopup menu2
1
*jpr8 26
fipushbtn
fipushbtnl
fipushbtn5
firadiol
■&oots2
firaots3
Я
fi
fi
fi
fi
«
fi
►J
Имя файла'
Выберите файл
ЕЗ
.Тип файлов: M-files
Cm; j\
ebcd
Этот файл не найден.
Проверьте правильность имени файла.
ОК
Рис. 9.13. Реакция на ошибку в наборе имени файла
MATLAB предусматривает возможность позиционирования окна по выбору
файла:
uigetfile('*. *','ВыБор файла',20,20)
Однако Windows на задание координат не реагирует и располагает окно по
своему усмотрению.
Выберите файл
ВЕЗ
Полно: |_)work
Ыа
fiabc
йаегб
Ш array 2vec
Barray2vec
Sbuttonqroup
Ebuttongrsup
4 |
Mbuttongroupl
flbuttongroup 1
fibuttondroup2
Scbl
flcbl
&ЭсЬ2
•Qch2
1
ЫсЬЗ
тЗсЬЗ
йсЬ4
ficheckl
M data 1
Sdata2
Sdata3
z]
*• ED ИМИ--
4 dim
fiedit textl
fifed
afern
fifern
fiGUI 3
fiGUl 3
ti
fi
ф
ti
из
fi
g
.►J
Имя файла: Г
1ип файлов: | • I Files .*)
Открыть
~Б
Отмена
Рис. 9.14. Фильтр отбора * . *■
412
Глава 9
На наш взгляд, в реализации диалогового окна uigetfile авторы MATLAB
напрасно опустили вывод расширений файла. Дело в том, что в каталоге
могут присутствовать файлы с одним и тем же именем, имеющие разные
расширения. Пример тому— задание фильтра отбора *.*. Результат
представлен на рис. 9.14. И сделать выбор файла в такой ситуации не так-то и
просто — надо ориентироваться не только на название файла, но и на
сопровождающий его значок.
Название кнопки Открыть не совсем точно передает англоязычный
эквивалент Done (дословно — выполнить). Может создаться впечатление, что
выбранный файл открыт. На самом деле программа только узнала имя файла,
которое еще предстоит открыть с помощью функции fopen.
9.12. Выбор имени файла
для записи (uiputfile)
Выбор файла для записи с помощью функции uiputfile несколько
отличается от выбора имени файла, содержащего входные данные. Если файл с
входными данными должен обязательно существовать, то в качестве файла с
выходными данными можно использовать как существующий, так и
несуществующий файл. В первом случае система должна запросить
подтверждение на уничтожение имеющихся данных, чтобы пользователь по ошибке не
удалил полезный файл.
Для вызова функции uiputfile разумно использовать один из двух
следующих форматов:
[fiie_name,file_path]=uiputfile('*.m','Заголовок')
[file_name,file_path]-uiputfile!'fname','Заголовок')
Первый вариант, более распространенный, позволяет увидеть, какие файлы
с заданным расширением уже присутствуют в текущем каталоге. Здесь
имеется возможность набрать новое имя или выбрать уже существующий файл.
Во втором случае первый аргумент сразу задает имя файла для выходных
данных, которое появится в поле ввода диалогового окна. Конечно, от этого
имени можно отказаться, набрав или выбрав другое имя.
Если выбираемый пользователем файл существует, то появляется
дополнительное окно с целью предупреждения опрометчивого действия (рис. 9.15).
Вектор значений, возвращаемых функцией uiputdlg, таков же, как и при
выборе файла ввода — имя файла и путь к файлу. В случае отказа от выбора
функция возвращает нулевые значения.
Стандартные диалоговые окна
413
Выберите файл для вывода
Попка: | О work
ИВ
■^1«- э гЗ ешн
Babe
fiarray2vec
Hbuttongroup
fibuttongroupl
Bbuttongroup2
Qcbi
Dcb2
<l '
ficb3
ficW
Qcheckl
•Eledit textl
fifed
fifem
fiGUI 3
■V7j
•fcJlistl &pr8 26
Ciist2 ■BpusJibm
fipetal fipushbtnl
fipolyllne ■Bpushbtn5
fipopup menu firadlol
■Bpopup menui £lroots2
fipopup_menu2 firoobs3
"' ; 1 -:b ~
ti
Q
У
fi
fi
ti
«
>i
Имя файла: p
1ип файла: |M-filas(*.m) f\
■Select File To Write
E
H:\fy1AJLASAwo(;k\abc.m already exists,"
Do you want to replaee.lt?
Да
Вет
Рис. 9.15. Запрос на замену существующего файла
9.13. Диалоговое окно
для выбора цвета (uisetcolor)
Диалоговое окно по выбору цвета предлагает две возможности. Во-первых,
по красочной мозаике, представленной в основном окне, можно получить
тройку RGB-компонентов, соответствующую выбранному цвету. Делается
это следующим образом:
» с = uisetcolor([1 0 0],'Выбор цвета')
В результате выполнения этой команды появляется диалоговое окно
(рис. 9.16) с красочной мозаикой, в которой пунктирным прямоугольником
выделен элемент, цвет которого совпадает с RGB-вектором, заданным в
первом аргументе (вектор цвета [1 о 0] соответствует красному цвету).
Обратите внимание на первый элемент во втором ряду.
После появления окна с палитрой из 48 цветов пользователь может
щелкнуть по любой клеточке и нажать кнопку ОК. Тройка чисел,
соответствующая выбранному цвету, возвращается в качестве результата и засылается в
переменную с. Если палитра основных цветов покажется пользователю
слишком бедной, то можно нажать кнопку Определить цвет » (Define
color »). Тогда окно по выбору цвета пополнится новыми средствами
формирования цветовых оттенков (рис. 9.17). Понравившиеся пользователю
цвета могут быть перенесены в таблицу дополнительных цветов.
414
Глава 9
Выбор цвета
Основные цвета
Г5П
ПИ
ВЕЗ
'EB-I
Дополнительные цвета:
гггггггг
гггггггг
Определить цввт »
ок
Отмене
Рис. 9.16. Окно выбора цвета
Выбор цвета
Основные цвета-
г"г~г~г~г"(агтгт
~l—I—I—ЕГГТ
5Г"=.- ИГИГ
Дополнительные цвета:
ГГГГГГГГ
г-
ВЕЗ
"B»'.fe
ип1ял|чч"ьце- | »
ок
Отмена
Щ~'С ! Оттенок:(() Красный: |255
раод К,онтраст:рЧС1 Зеленый: |0
Цвет|Звпивко Яркйсть:|120 Синий: [5
Добавить в набор
Рис. 9.17. Расширенная палитра для выбора цветовых оттенков
Второй вариант использования цветового окна связан с выбором окраски
объекта, чей указатель задается в качестве первого аргумента функции
uisetcolor:
» hBtn = uicontrol('Style','pushbutton','String', 'Кнопка');...
uisetcolor(hBtn,'Задайте цвет кнопки');
Стандартные диалоговые окна
415
Кнопка типа pushbutton обладает свойством color, задающим цвет
символов надписи. Поэтому после выбора цветового элемента и нажатия кнопки
ОК надпись Кнопка (Button) окрасится в выбранный цвет.
9.14. Диалог по выбору
параметров шрифта (uisetfont)
Шрифт Обладает РЯДОМ СВОЙСТВ — FontName (ИМЯ Шрифта), FontUnits
(единицы измерения), Fontsize (размер символов), Fontweight (толщина
линий контура), FontAngie (угол наклона символов). Эти же свойства
присущи различным графическим и интерфейсным объектам. Диалоговое окно
по выбору параметров шрифта позволяет визуально оценить качество
назначаемых вами значений. В простейшем случае отображение этого окна
происходит при вызове функции uisetfont без параметров:
» ш setfont
Окно, появляющееся при выполнении этой команды, приведено на рис. 9.18.
Шрифт
Шрифт:
Начертание
Ariel
>Г ©SimSun
'*Г Academy Engraved LET-
'jt' Amaze
I p Arial Black
IО Arial Narrow.
I 7r Arial Unicode MS
Еезмер:
|!Я?ИИ!ЯЗ
zJ
курсив
жирный
жирный курсив
Образец™—-
1« -Z.
АаВЬБбФф
На£ор символов;
[Кириллический
"3
12
8 л
9 —
10
ОК
Отмене
Рис. 9.18. Окно выбора параметров шрифта
После установки нужных значений и щелчка по кнопке ОК функция
возвращает структуру следующего вида:
ans =
FontName: 'Arial'
416
Глава 9
FontUnits: 'points'
FontSize: 12
FontWeight: 'normal'
FontAngle: 'normal'
Сформированная структура может быть присвоена любой переменной,
например s, или приписана любому графическому или интерфейсному
объекту, если его указатель hobj приведен в качестве параметра функции:
» S = uisetfont;
» uisetfont(hObj);
Если вы объявили структуру s с указанными выше полями и присвоили им
соответствующие значения, то эта структура может быть задана в качестве
первого аргумента функции uisetfont. При этом в диалоговом окне все
параметры шрифта будут установлены по значениям соответствующих полей
структуры.
Вторым аргументом функции uisetfont является строка, играющая роль
заголовка диалогового окна по выбору шрифта:
uisetfont(h,'заголовок')
uisetfont(S,'заголовок'>
Заголовок окна может быть и первым аргументом, если среди параметров
функции отсутствуют указатель на.объект или структура с начальными
установками:
uisetfont('заголовок')
Если пользователь отказывается от выбора параметров шрифта и нажимает
кнопку Отмена (Cancel) или закрывает окно, то значения всех
возвращаемых свойств равны о.
9.15. Диалоговое окно
с предупреждением (warndlg)
Для формирования и отображения диалогового окна с предупреждением
используется функция warndlg, которой передаются до двух аргументов:
warndlg
warndlg('предупреждение')
warndlg ('предупреждение', ' заголовок,')
h=warndlg(...)
Стандартные диалоговые окна
417
Без параметров эта функция не употребляется, т. к. отображает диалоговое
окно с заголовком Warning Dialog и строкой предупреждения "This is the
default warning string". Пользы от такого окна, конечно, нет. Более
содержательное обращение:
» warndlgfBbi забыли изменить eps',' Предупреждение')
вызывает появление диалогового окна, приведенного на рис. 9.19.
-> Предупреждение ВВЕЗ
Вы забыли изменить eps
OK I
Рис. 9.19. Окно предупреждения
9.16. Полоса прогресса
С помощью командной строки
» hWB=waitbar(0,'Wait please...');for i=l:10000,waitbar(i/10000,hWB), end
создается окно с полосой прогресса (рис. 9.20).
Рис. 9.20. Бегущая полоса
Из приведенного примера следует, что первое обращение к функции
waitbar с нулевым аргументом создает окно, в котором полоса ожидания
прижата к начальной позиции и практически не видна. Функция
возвращает указатель hWB на созданный компонент, который используется в
последующих обращениях. При повторных обращениях к функции waitbar с
постепенно увеличивающимся значением первого аргумента бегущая
полоска продвигается к правой границе, достигая ее, когда первый аргумент
418
Глава 9
становится равным 1. Так, например, можно отображать процесс
копирования длинного файла, вычисляя долю уже переписанных байтов
относительно длины файла. При повторных вызовах функции waitbar можно
задавать дополнительный аргумент в виде символьной строки, который
заменит застывшее Wait please..., например, на процент от объема
выполненной работы.
В программе из примера 9.3 внутренний никл по j имитирует некоторый
процесс. В зависимости от скорости вашего компьютера количество
повторений внутреннего цикла, возможно, придется уменьшить. На рис. 9.21
показан промежуточный вид полосы прогресса.
• ■ v "г^"^т"5Ч".и:"""'?" .■ •"-ргжщтр^щгхщ жщг'~*щ ■
; Пример 9.3. Отображение полосы ожидания ■ '.-п.- ^ .;. ■*•,.'._
h=waitbar(0); % создание начального объекта
tor i=l:100
s=int2str(i);
s=strcat(s,'%');
for j=l:10000000
end
waitbar(i/100,h,s) % модификация шкалы прогресса
end
Рис. 9.21. Индикация выполняемого процесса
Из любопытства после формирования окна индикации (h=waitbar;) можно
обратиться к функции get(h) п проанализировать свойства этого
необычного объекта. Самое интересное, что свойство style имеет значение figure,
(т. е. графическое окно специального типа). Во-вторых, свойству Tag,
которому функции uicontrol не присваивали никакого значения, здесь
присвоена строка 'TMFWaitbar'. По умолчанию функция waitbar (0) формирует
окно с полосой, над которой находится текст 'waitbar'. Отметим еше одну
особенность этого объекта — он может существовать только в единственном
экземпляре. Попытка создать еще одно окно такого же типа не удается
(пример 9.4).
Стандартные диалоговые окна
419
j Пример 9.4. Попытка создания двух полос одновременно
» hl=waitbar(0)
hi =
3.0043
» h2=waitbar(0)
h2 =
3.0043
Оба указателя имеют одно и то же значение, т. о. в обоих случаях речь идет
об одном и том же объекте.
г
Глава 10
Визуализация
трехмерных объектов
Технология визуализации трехмерных объектов использует довольно много
специ&чьных терминов, характерных для большинства систем машинной
графики. С наиболее важными из них, влияющими на свойства
отображаемых фигур, мы познакомимся в начале этой главы. Появлению изображения
на экране предшествует довольно много процедур, связанных с
вычислением цветности каждого пиксела изображения — учет положения и специфики
источников света, определение видимых участков объекта и учет влияния их
физических характеристик (отражение, преломление, диффузия). Все это
вместе взятое составляет суть рендеринга — процесса визуализации
компьютерной модели на экране.
10.1. Некоторые задачи и алгоритмы
трехмерной визуализации
10.1.1. Аффинные преобразования
и однородные координаты
Одну из составных процедур рендеринга представляют различные линейные
преобразования координат характерных точек отображаемого объекта,
обычно вершин граней, — сдвиги, повороты, растяжения/сжатия,
параллельное или центральное проектирование на ту или иную плоскость.
Перечисленные преобразования образуют группу аффинных преобразований и в
общем виде описываются следующими линейными уравнениями:
Хноб = a-n*xCT + ai?*yCT + ai3*Zcr +bi",
Уноа = a2i*xCT + а22*Уст + a2j*zCT +bz;
zHcb = а31*Хст + аз2*Уст + a33*zCT +bj.
Для того чтобы записать указанные равенства в матричной форме phdd=a*pc,. ,
используют следующий прием.
422
Глава 10
XHt!li
У HOD
ZH(U-
1
"а11
a21
a31
0
ai2
a22
a22
0
ai3
aZ3
взз
0
h,"
b2
b3
1
*
Ч.Т
Ус*
ZCT
1
Расширим вектор координат, добавив к его трем естественным координатам
четвертую, всегда равную 1:
[ х; у; z ] -» [ х; у; z; 1 ].
Тогда описанное в формате (10.1) аффинное преобразование приобретает
следующий вид:
(10.2)
Четверка расширенных таким образом координат известна под названием
однородных координат. На плоскости однородные координаты точки
представлены тройкой [х; у; ]].
Может показаться, что введение однородных координат увеличивает объем
исходных данных. Но это не так — на самом деле искусственно
добавляемую единицу можно хранить не в оперативной памяти, а "в уме", используя
ее только в момент выполнения преобразований.
Тогда в чем же преимущество формы (10.2) по сравнению с формой (10.1)'.'
Во-первых, для каждого ■элементарного аффинного преобразования можно
довольно просто сформировать соответствующую матрицу. Например, при
сдвиге объекта на заданные смещения по каждой из координат (хнаР=хс..т+с1х,
Унзб=у-,т+с1у, zHUE=zCT+dz) эта матрица имеет вид:
"1 0 0 dx~
О 1 0 ау
О 0 1 dz
0 0 11
Для сжатия/растяжения по каждой координате (хНоз=хСт*кх, у,!0в=уст*к..-,
z.uoB=zCTkk.z) используется матрица:
ку б О О'
0 ку О О
О 0 к, О
0 0 0 1
Познакомиться с матрицами, описывающими различные аффинные
преобразования, можно, например, в книге В. Н. Порсва "Компьютерная
графика"1.
Порев В. Н. Компьютерная графика. — СПб.: БХВ-Печербург, 2002.
Визуализация трехмерных объектов
423
Второй аргумент в пользу однородных координат и формата (10.2)
аффинных преобразований появляется, как только над объектом нужно выполнить
цепочку из двух или более преобразований с матрицами Аь Аг, ..., аГ1. Вместо
того чтобы производить пересчет координат на каждом шаге, можно
вычислить матрицу итогового аффинного преобразования и только один раз
пересчитать все координаты:
A=Ar.*An-i* . . . *Ai_
Р»в=АгЛ (An-i* . . . (Ai*PCT> = А*РСТ
Умножение матриц 4-го порядка требует гораздо меньше операций, чем
многократный пересчет всех вершин отображаемого многогранника.
Именно это преимущество в объеме вычислений оправдывает использование
однородных координат в любой системе машинной графики.
Немаловажным аргументом в пользу этой технологии является и
стереотипность выполнения аффинных преобразований — использование типовых
шаблонов для формирования матриц каждого элементарного
преобразования, умножение матриц 4-го порядка.
10.1.2. Растеризация векторных изображений
Такие устройства отображения, как дисплеи и принтеры, обычно
используют растровую технологию воспроизведения графических объектов. При этом
изображение состоит из большого количества отдельных цветных точек —
пикселов. Однако информацию об отображаемом объекте гораздо выгоднее
хранить в векторном формате — коэффициентов соответствующих
аналитических уравнений, координат концов отрезков, координат вершин
многоугольников и т. п. Во-первых, так экономится объем оперативной памяти.
Во-вторых, такие операции, как масштабирование и повороты фигур, в
векторном формате осуществляются без потери качества.
Поэтому одна из первых задач в системах отображения — растеризация —
связана с преобразованием векторных данных в растровый формат. Она
использует довольно простой математический аппарат, но ее лобовое решение
приводит к большому объему вычислений, в которых значительная доля
операций приходится на умножение (деление) вещественных чисел. Одним
из первых исследователей, предложивших эффективный алгоритм
вычисления координат точек растрового отрезка, проходящего через две заданные
точки, с использованием только целочисленных операций сравнения и
сложения (вычитания) был Брезенхейм (Bresenham J. Е., 1965 г.). Позднее
(1977 г.) он же распространил подобную схему на вычисление растровых
координат точек на дуге окружности. Существенно позже аналогичная схема
была предложена и для растеризации дуг эллипсов. Перечисленные
алгоритмы оказались настолько удачными, что их имплантируют в аппаратуру
современных графических ускорителей.
424
Глава 10
10.1.3. Воспроизведение утолщенных линий
Задача воспроизведения утолщенных линий на растровой сетке не такая уж
и тривиальная, как может показаться. Лобовое ее решение путем
построения семейства симметричных эквидистант относительно осевой линии
приводит к появлению семейства мелких точек, сквозь которые просвечивают
фоновые пикселы.
На вид толстых линий оказывает ачияние и форма пишущего узла (апертура
пера), из-за которой на стыках прямоугольных отрезков могут наблюдаться
различного рода зазубрины — выступы, впадины. Чтобы построить
качественную прямоугольную рамку с толщиной линии w, приходится строить
отрезки, концы которых выступают на w/z относительно координат осевой
линии. Многие графические системы, включая и Windows GDI,
предоставляют пользователю возможность задать такие характеристики пера, как
стиль сочленения смежных отрезков (joint style) и тип окончания отрезка
(end cap) — закругленный, перпендикулярный осевой, параллельный одной
из осей координат в зависимости от наклона отрезка.
10.1.4. Устранение невидимых
частей изображения
Существует довольно много разных по сложности и быстродействию
алгоритмов удаления невидимых точек, линий и поверхностей. Среди них
можно указать методы прямой (от источника освещения) и обратной (от
позиции наблюдателя) трассировки лучей (ray tracing), излучательности
(radiosity), сортировки по глубине, Z-буфера и др.
Наиболее простая идея, которая нашла свое воплощение и в аппаратуре,
заножена в алгоритмах Z-буфера. Название этих методов с выбором
направления оси z, которая из картинной плоскости (т. е. плоскости экрана)
направлена на наблюдателя. Считается, что его позиция достаточно удалена от
экрана, так что лучи, направленные от картинной плоскости в сторону
наблюдателя, можно рассматривать как пучок прямых, параллельных оси z.
Для каждой точки объекта, расположенного перед картинной плоскостью,
ее г-координата совпадает с расстоянием от этой точки до плоскости
экрана. Поэтому, если на одном и том же луче находятся две или более точки
объекта, то видимой окажется та, которая расположена ближе к
наблюдателю, т. е. та, которая имеет большую г-координату. Поэтому сравнение z-
координат пикселов, проектируемых в одну и ту же точку на картинной
плоскости, решает проблему видимости изображения.
На практике простейший алгоритм г-буфера реализуется с помощью двух
буферов одинакового размера. Один из них предназначен для хранения
двумерной матрицы цветностей пикселов картинной плоскости. При использо-
Визуализация трехмерных объектов 425
вании 24-битовой кодировки RGB-компонентов и разрешении экрана
1024x768 для такой матрицы потребуется порядка 4 Мбайт. Второй буфер
служит для хранения 32-разрядных целочисленных значений г-координат
точек отображаемого объекта. В начальный момент буфер цветности
заполняется кодом фонового цвета, а буфер г-координат — нулями. При анализе
очередного пиксела изображения его г-координата сравнивается с
соответствующим расстоянием ранее обработанного пиксела, уже записанного в Z-
буфер. Если новое расстояние больше, то код цветности пиксела заносится
в соответствующую позицию буфера цветности, а аппликата подменяет
предыдущее Z-значение. В противном случае обрабатываемая точка считается
невидимой. *
10.1.5. Окрашивание граней
полигональных моделей
В волновой теории света считается, что свет представляет собой поток
фотонов, испускаемых источником и несущих электромагнитные колебания
разной частоты. Для человеческого глаза видимый поток света принадлежит
диапазону от 380 нм (нижняя граница фиолетового излучения) до 780 нм
(верхняя граница красного излучения).
Под интенсивностью I падающего луча понимают отношение энергии
светового потока к площади освещаемой им поверхности. Часть падающих
лучей отражается от поверхности, часть поглощается ею, часть проходит через
поверхность и преломляется. Благодаря отраженным лучам мы видим
освещаемые предметы.
Отражение световых лучей представляет собой довольно сложный процесс,
на одной из границ которого находится абсолютное зеркальное отражение
(specular reflection), а на другой — полное диффузное рассеяние (diffuse
reflection). Зеркальное отражение имеет место при падении светового луча на
идеально гладкую поверхность (помните из школьной физики — "угол
падения равен углу отражения"?). К очень гладким поверхностям мы относим
такие, у которых шероховатость, образуемая впадинками и выпуклостями,
имеет размеры меньшие, чем длина световой волны. Для таких
поверхностей угол отражения можно считать равным углу падения, а интенсивность
отраженного луча iOTp прямо пропорциональной интенсивности падающего
луча i:
При встрече луча со слабо шероховатой поверхностью имеет место
отклонение отраженного луча от идеального направления на угол ее. В этом случае
зависимость интенсивности iQ4J от интенсивности падающего луча i
существенно нелинейна и должна учитывать степень шероховатости освешаемой
поверхности. В системах машинной графики с целью уменьшения объема
426
Глава 10
вычислений используют более простые эмпирические формулы. Одной из
них является формула Фонга (Phong):
10тр = ks * I * cospcc.
Показатель степени p (Фонг называл его коэффициентом резкости бликов
(shininess coefficient)) подбирается эмпирическим путем. Для идеального
зеркала р = 8, для металлических поверхностей коэффициент резкости
бликов находится в интервале от юо до 500, для обычных материалов его
значение не превышает юо.
При очень большой шероховатости (такие поверхности называют матовыми)
отражение лучей осуществляется равномерно во все стороны — происходит так
называемое диффузное рассеяние. Если обозначить через <р угол падения луча
(угол между направлением светового потока и вектором нормали к освещаемой
поверхности), то интенсивность отраженного луча, достигающего позиции
наблюдателя, в случае диффузного рассеяния подчиняется закону Ламберта:
1циф = I * kd * coscp.
В интенсивность наблюдаемого излучения, кроме перечисленных выше двух
составляющих i0.rp и iBl,4„ вносит свой вклад и фоновая подсветка (ambient
light), создаваемая рассеянным светом, отраженным от других предметов, —
1фон-
В описанных выше физических явлениях и приведенных формулах явно или
неявно присутствует вектор нормали к освещаемой поверхности,
построенный в точке падения луча. В машинной графике поверхности трехмерных
тел заменяются полигональными моделями, сформированными, как
правило, из треугольных или четырехугольных граней (Patches). Так как каждая из
таких граней принадлежит плоскости, описываемой уравнением Ах + By +
+ cz = о с известными коэффициентами, то построение вектора нормали
для внутренних точек грани и определение косинуса угла между парами
векторов (нормаль, вектор падающего луча) или (нормаль, вектор в позицию
наблюдателя) выполняется по довольно простым вычислительным схемам.
Они достаточно хорошо согласуются с операциями над векторами,
реализованными в MATLAB (см. гл. 12).
Самый примитивный алгоритм однотонного окрашивания граней,
известный под названием flat, базируется на предположении, что все точки ipa-
ни освещены одинаково. Это более или менее допустимо при бесконечно
удаленном источнике света, когда лучи в световом потоке параллельны, а
размеры граней достаточно малы. Обычно выбирается некоторая
характерная точка на грани, например, аналог центра масс вершин, в ней
вычисляется освещенность, приписываемая всем остальным точкам. Так как при
переходе на соседнюю грань освещенность терпит разрыв, то на
отображаемом объекте четко прорисовываются ребра и отчетливо видна фасеточная
структура поверхности.
Визуализация трехмерных объектов
427
Для создания более реалистичного изображения полигональной
поверхности Гуро (Н. Gouraud — сотрудник компании Autodesk, один из
разработчиков 3D Studio) предложил алгоритм неравномерной закраски граней,
основанный на применении билинейной интерполяции освещенности. В его
схеме по сложным или упрошенным эмпирическим формулам вычисляют
освещенность каждой вершины. Затем на отрезках, соединяющих две
смежные вершины, для полсчета освещенности каждой точки ребра используют
линейную интерполяцию. Обозначим через г* освещенность вершины с
координатами (х1:, у1:, z1:), а через i^i освещенность соседней вершины с
координатами (к):.ц, yktl, zk*j)- Тогда параметрические уравнения ребра,
соединяющего эти вершины, имеют вид:
х = хк +■ (хк+1 - хк) * t;
у = у* + (у-,;+1 - х1:> * t; О < t < 1.
z = zt. + (zk+i - jk) * t.
Для внутренней точки м ребра, определяемой параметром tm, интенсивность
освещенности вычисляется по формуле:
1н= Ik+ dk+i - Ik) * U, ■
Аналогичный расчет производится и для всех точек смежного ребра этой же
грани. Затем пара точек смежных ребер с одинаковым значением параметра
t соединяется внутренней хордой и на каждой точке хорды повторно
производится линейная интерполяция освещенности.
Если по алгоритму Гуро произвести расчет интенсивности отраженных
лучей на смежной грани, то на стыке граней в точках общего ребра
освещенность сохраняет свою непрерывность, однако ее первая производная терпит
разрыв. Для избежания этого разрыва и создания более плавных цветовых
переходов Фонг предложил интерполировать нормали к поверхности.
Теперь они уже не образуют строго параллельные пучки на каждой грани, а
рассыпаются в стороны наподобие иголок ежа, образуя плавный переход
через ребра и вершины. Этот алгоритм связан с большими
вычислительными затратами, но изображение поверхности при этом становится более
реалистичным.
10.2. Создание и отображение
криволинейных поверхностей
10.2.1. Объект типа Surface и его свойства
Графические объекты типа surface представляют собой криволинейные
поверхности, заданные таблично, — узлами сетки размерности mxn,
заполняющей на плоскости ху прямоугольную область, и массивом z той же раз-
428
Глава 10
мерности, представляющим значения функции в узлах этой сетки. Если
сетка па плоскости ху имеет регулярный шаг вдоль каждой из осей, то она
может быть задана двумя векторами: х размерности п и у размерности т. В
общем случае узлы сетки могут быть нерегулярными и тогда ее могут
представлять двумерные массивы х и y с количеством элементов гоХп.
Даже в случае регулярного задания узлов сетки бывает выгодно отказаться
от векторов и воспользоваться двумерными массивами х и y, т. к. это может
облегчить и ускорить процедуру формирования значений элементов массива
z. Пусть, например, на оси хзаданы значения [-2, о, 2], а на оси у —
значения [о, 1, 2, з]. Тогда для формирования двумерных массивов,
представляющих сетку, можно воспользоваться функцией meshgrid (пример 10.]).
I Пример 10.1. Формирование двумерного массива с помощью , "* "" '' ;** I
| функции meshgrid ; .. „ ■■*?"' "" !
» u=[-2f 0, 2] ,-
» v=[0,1,2,3],•
» [X,Y)=meshgrid(u,v)
X =
-2 0 2
-2 0 2
-2 0 2
-2 0 2
У =
0 0 0
1 1 1
2 2 2
3 3 3
» Z = Х.*ехр(-Х.Л2 -У.Л2)
Z =
-0.0366 0 0.0366
-0.01-35 0 0.0135
-0.0007 0 0.0007
-0.0000 0 0.0000
Проигрыш в памяти из-за повторяющихся строк в массиве х и
повторяющихся столбцов в массиве у компенсируется простотой и эффективностью
вычисления значений функции z=-x*exp(x~2+y~2) в узлах сетки. Этот
подход гарантирует и правильность сочетания координат х и у в узлах сетки.
Визуализация трехмерных объектов
429
Если массивы х, y и z сформированы тем или иным способом, то для
создания и одновременного отображения объекта типа surface можно
прибегнуть к услугам одной из функций — surf или mesh:
» h_Surf = surf(X,Y,Z>;
» h_Surf = mesh(X,Y,Z);
Каждая из этих функций допускает много разных вариантов вызова,
отличающихся наборами входных параметров, и возвращает указатель на
созданный объект. Владельцем созданного объекта являются оси координат
(объект типа Axes). Способ отображения созданной поверхности у каждой
из перечисленных функций тоже разный, но эти детали более подробно
обсуждаются в следующих разделах. На рис. 10.1 представлен вариант
отображения, Построенный С ПОМОЩЬЮ ФУНКЦИИ mesh.
0.04
002-
0-
-0.02.
-0.04,
3
_,_. -Г""'"'"'.
Ось Y 0-2
V-.
■—~"0
Ось 7
""2
Рис. 10.1. Маркировка осей по значениям координат
Вообще говоря, в простейшем случае каждой из этих функций достаточно
передать только массив г. Но тогда вместо маркировки осей х и у
значениями соответствующих координат будут использованы их индексы от 1 до m по
оси х и от 1 до п по оси у (рис. 10.2).
» h_Surf = mesh(Z);
» ХЪаЬеМ'Ось X' >, YLabel ('Ось Y')
По рис. 10.1 и 10.2 заметно, что элементы отображаемой поверхности
окрашиваются в разные цвета. По умолчанию действует следующий алгоритм
выбора цвета для вершин, ребер или граней поверхности. Все отображаемые
элементы упорядочиваются по возрастанию координаты z характерной точ-
430
Глава 10
ки (для вершины — это табличная точка, для ребра — аппликата середины,
для грани — аппликата точки пересечения диагоналей). Затем им
присваиваются индексы цвета (одинаковым значениям z присваивается один и тот
же индекс) и по этому индексу выбираются компоненты цвета из массива
coiormap, установленного в данный момент для графического окна (объекта
типа Figure). Если нас не устраивает выбор цвета по высоте аппликаты, мы
можем при создании поверхности добавить в список аргументов еще один
массив с размерности mxn, который сформирует значение свойства cnata-
(более подробно свойство CData описано в разд. 7.7) и изменит способ
окраски элементов поверхности:
» h_Surf = surf(X,Y,Z,C);
Рис. 10.2. Маркировка осей с использованием индексов координат
Среди многочисленных параметров функций, создающих и отображающих
поверхности, могут присутствовать пары "свойство — значение",
инициализирующие значения соответствующих свойств. В примере 10.2 приводится
полный перечень свойств объекта типа Surface.
» get(h_Surf)
» get(h_Surf)
Визуализация трехмерных объектов
431
AlphaData: 1
AlphaDataMapping: 'scaled'
CData: [4x3 double]
CDataMapping: 'scaled'
EdgeAlpha: 1
EdgeColor: "flat1
EraseMode: 'normal'
FaceAlpha: 1
FaceColor: [111]
LineStyle: '-'
LineWidth: 0.500.0
Marker: 'none'
MarkerEdgeColor: 'auto'
MarkerFaceColor: 'none'
MarkerSize: 6
MeshStyle: * both'
XData: [1 2 3]
YData: [4x1 double]
ZData: [4x3 double]
FaceLighting: 'none'
EdgeLighting: 'flat'
EackFaceLighting: 'reverselit'
AmbientStrength: 0.3000
DiffuseStrength: 0.6000
SpecularStrength: 0.9000
SpecularExponent: 10
SpecularColorReflectance: 1
VertexNormals: [4-x3x3 double]
NormaIMode: 'auto'
BeingDeleted: 'off
But tonDownFcn: []
Children: [0x1 double]
Clipping: 'on'
CreateFcn: [ ]
DeleteFcn: []
BusyAetion: "queue1
HandleVi s ibi1i ty: 'on'
HitTest: 'on'
Interruptible: 'on'
432
Глава 10
Selected: 'off
SelectionHighlight: 'on'
Tag: "
Type: 'surface'
UIContextMenu: [J
UserData: [J
Visible: 'on'
Parent: 151.0018
DisplayName: ''
XDataMode: 'auto'
XDataSource: ''
YDataMode: 'auto'
YDataSource: ''
CDataMode: 'auto'
CDataSource:.''
ZDataSource: ''
Кроме знакомых по гл. 7 свойств, появилось несколько групп
специфических свойств, большинство из которых будет описано ниже.
10.2.2. Отображение проволочного
каркаса поверхности
Проволочный каркас (wire frame) поверхности образуется путем соединения
точек поверхности с ближайшими соседями отрезками прямых. Для
отображения каркасной поверхности используется одна из функций: mesh, meshc
или meshz, допускающих различные варианты вызова. Программа,
приведенная в примере 10.3, строит каркас функции на квадратной сетке с шагом
о.?з. Этот шаг достаточно велик для получения качественного изображения,
но он позволяет рассмотреть некоторые детали, связанные с удалением
невидимых линий. Обращение к функции meshgrid с одним аргументом
эквивалентно обращению с заданием двух одинаковых диапазонов. Команда
coiorbar строит рядом с полем графика столбик с цветовой гаммой,
соответствующей текущему состоянию массива coiormap. Маркировка столбика
демонстрирует привязку цвета к значениям аппликат z.
) Пример 10.3. Построение каркаса функции и*?-х*ехр (хА2+уА2)^■ri^^'i^l
» [X,Y] = meshgrid([-2:.25:21);
» Z = Х.*ехр(-Х.л2 -У.л2);
» mesh(X,Y,Z)
Визуализация трехмерных объектов
433
>> co.lormap(coo.l), colorbar
» XLabeK'Ocb X') , YLabel ('Ось V),ZLabel('Ось Z']
0.5.
N
js 0.
и
О
-0.5,
2
<*>.&£% h
OcbY "2 "2
-r-^"^ 0
-1
ОсьХ
4
2
iy •
0.4
0 3
0.2
0.1
0
-0.1
-0.2
-0.3
-0.4
Рис. 10.3. Проволочный каркас поверхности
Рис. 10.4. Каркас с невидимыми линиями
434
Глава 10
Результат работы приведенной программы показан на рис. 10.3. По
умолчанию функция mesh удаляет невидимые линии. Но если по какой-то
причине удаленные линии необходимо восстановить, то достаточно выполнить
команду hidden off. Соответствующий каркас показан на рис. 10.4.
Возможно, что при отображении очень простых фигур типа пирамид или
параллелограммов невидимые линии могут оказаться полезными. Но на
насыщенном изображении их присутствие затрудняет восприятие.
С помощью функции meshc строится каркас поверхности, дополненный
линиями уровня z (х, y)=const, спроектированными на плоскость ху (рис. 10.5).
Рис. 10.5. Каркас поверхности с линиями уровня
Дополнительные детали, связанные с воспроизведением линий уровня,
рассматриваются в разд. 10.2.4.
Функция raeshz опускает из каждой граничной точки каркаса
перпендикуляр на плоскость ху (рис. 10.6). При достаточно мелком шаге сетки создается
впечатление занавеса, опущенного по краям изображения.
Воспользуемся возможностью задания параметров в виде пар "свойство —
значение" для принудительной окраски ребер:
» rp.esh(X,Y,Z, 'EdgeColor', 'black')
Результат такого воздействия на каркас приведен на рис. 10.7.
Визуализация трехмерных объектов
435
-'~~*~' ! ""*■■*
--"!*"" ' '*"•*
0.5^.-—""'•
0-
-0.5S
--'■■""Vir -
г
i
j _
"
L-J J !
2 --ОЧ
: : : ---.
: : : т>.
i : *7^_ '• '• ''-
_:;-^г\ ч 7-.-' ,-- "Г -V-r^- ^i
T.~:-" "'L'-.<r , ^'" .v-;~- .".""" --~\' 1
*bi"—v . . .' i ■ ?Л~Л*><>'" i
f-*4^ ,. ■■■.'--'-^■i—W'"^
; -,<%^<.j>,
l !Г
г
1^-' И I'M
>^yj
'
:.* ': l
....
!
l
i
i^r
1
I
f
!
1
:
i
!
X I 1.:
-"""o
-1 N<---" -1
-2 -2
Рис. 10.6. Каркас поверхности на "постаменте"
0.5^
С
-0.5>
2
-к
,---.
....-:-—
_.--*'* ; •
■-^
i "■--.,.
?"5^J
^^^^Ж
""•'
VVv
• ..-""" "_^^^¾?^?s=½5^s¾^^^'"''^ ^""Sv^
-2 -2
-..._
2
Рис. 10.7. Монохромный каркас
436
Глава 10
10.2.3. Отображение
закрашенных поверхностей
Закрашивание каждой четырехугольной чешуйки поверхности
осуществляется с помощью функций surf и surfc. Это позволяет значительно
улучшить восприятие поверхности (рис. 10.8). По умолчанию каждая грань
закрашивается одинаковым цветом в соответствии с высотой ее характерной
точки, а ребра между гранями остаются черными.
Рис. 10.8. Закрашенная поверхность
С помощью команды shading способ закраски может .быть изменен. Эта
команда допускает задание одного из трех режимов — faceted, interp или
flat. По умолчанию считается установленным shading faceted. Это
приводит к закрашиванию каждого участка поверхности, ограниченного
четырьмя точками, своим цветом и отображением между ними черных ребер
(если иное не задано в свойствах объекта при вызове функции surf). В
режиме flat ребра не отображаются, а в режиме interp выполняется еще и
сглаживание цветов между соседними участками поверхности.
Режим imierp соответствует применению алгоритма закраски Гуро, при
котором осуществляется билинейная интерполяция цветов внутри каждой
грани и между соседними гранями (рис. Ю.9). Ребра при этом не рисуются, и
создается видимость сплошной поверхности. В режиме fiat, грани тоже не
Визуализация трехмерных объектов
437
воспроизводятся, но цвета граней сохраняются. За счет этого смежные грани
одного цвета объединяются в более крупные образования.
Рис. 10.9. Закрашенная поверхность
(после команды shading interp)
10.2.4. Управление точкой зрения
Позиция наблюдателя, из которой мы рассматриваем изображение
поверхности, в системе MATLAB носит название позиции камеры (camera posiiion)
или точки зрения (view point). Если с позицией камеры и другими ее
характеристиками связано довольно много свойств, то точка зрения
характеризуется всего двумя углами — азимутом (Azimuth) и углом возвышения
(Elevation). Первый из них определяет угол поворота вокруг оси г и
отчитывается от отрицательного направления оси у против часовой стрелки.
Второй угол образован отрезком прямой, соединяющей точку зрения с
началом координат, и плоскостью ху (рис. 10.10). Удаление от предмета
наблюдения в расчет не принимается.
По умолчанию для этих углов установлены следующие значения:
Azimuth = -37.5Q
Elevation = 30°
438
Глава 10
С помощью функции view можно управлять точкой зрения и. тем самым,
менять внешний вид изображения (пример 10.4).
Пример 10.4; Управление точкой зрения fpj* - ■»■"'. - >■
» view(az,el)
» view![az, el])
» view([x,y,z])
» [az,el] = view;
» view (2 J
» view(3>
Точка зрения
-У
Рис. 10.10. Положение точки зрения
Первые два варианта эквивалентны. Их аргументами являются азимут и угол
возвышения. Обращение view и, у, z) задает декартовы координаты точки
зрения. Вызов функции view без параметров позволяет опросить параметры
текущей точки зрения. Сокращенные варианты вызова функций view(2) и
yiew(3) устанавливают значения азимута и угла возвышения по умолчанию
для плоских (az=o, el=so°) и объемных (az=-37.5°, е1=зо°) изображений.
10.2.5. Выбор алгоритма визуализации
На рис. 10.11 изображены несколько объектов типа сфера. Верхний ряд
построен при локальном освещении, нижний — при бесконечно удапенном
Визуализация трехмерных объектов
439
источнике света. Чем дальше от объекта находится источник света, тем
меньше размер зеркального пятна, наблюдаемого в месте встречи с более
короткими лучами. Однако на последнее гораздо большее влияние
оказывают свойства, управляющие отражающими характеристиками поверхности
(specular-Strength, SpecularExponent, SpecularColorReflectance).
Сфера относится к группе объектов типа surface. Таблица каркасных
координат сферы создается с помощью функции sphere:
[х,у,z]=sphere;
[х#у,z3=sphere{N);
Здесь м — количество узлов по каждой из координат (по умолчанию N=20).
В построениях на рис. 10.11 использованы три варианта окраски граней:
П FaceLighting=gourand — окраска точек каждой грани интерполирована
по схеме Гуро (сферы 1,4);
П cac.eLighting=fiat — окраска всех точек каждой грани фиксирована
(сферы 2, 5);
П FaceLighting=none — все грани поверхности окрашены в один и тот же
цвет (сферы 3, 6).
rap;. -* -
■ -ft '■?*.
1
J№
if- . 1-1.
4
-
Oi
2
5
*Щ&
1,.
,f „ .
•"--■■- „X0S
■'.-: 1]
I.
3
л
" ?
6
Рис. 10.11. Использование различных алгоритмов закраски
с разными источниками света
Четвертый возможный вариант FaceLighting=phong (интерполяция
окраски по схеме Фонга) здесь не приведен, т. к. даже в цветном варианте на
примере этой сферы он дает результаты, почти не отличающиеся от
алгоритма Гуро.
I 5 Зак. 849
440
Глава 10
10.2.6. Освещение поверхностей
Источник света — объект типа Light — оказывает влияние на отображение
трехмерных поверхностей и тел, представленных объектами типа Surface и
Patch. Создается он с помощью функции light:
hL=li ght('Свойство_1',Значение_1,'Свойство_2',Значение_2,...);
К числу наиболее важных свойств источника света относятся:
П color. — определяет цвет источника путём задания удельного веса RGB-
составляющих в каждом луче, исходящем из источника;
П style — определяет тип источника и может принимать одно из двух
значений:
• styie=inf inity (бесконечно удаленный источник);
• styie=iocai (локальный источник);
П Position — задает координаты положения локального источника света
([х; у; г]) или вектора, направленного в сторону бесконечно
удаленного источника.
С помощью функции lightangie можно установить, изменить или опросить
значения углов азимута и возвышения источника света (пример 10.5).
; Пример 10.5. Установка и проверка/значении углов^азимута г||*; «*- •■-Ф '?$Щ$^Д
i и возвышения источника света V, -. ^¾¾¾^¾3^ .*.- .жйл*™ ^C^s»*-^i
» hL=lightangie(О,30);
» lightangie(hL,90,30);
» [az,el]=lightangle(hL)
az =
90
el =
30.0000
Источник света приписывается объекту типа Axes и оказывает влияние
только на дочерние объекты этих осей. Бесконечно удаленный источник
света излучает пучок параллельно направленных лучей, обладающих
одинаковой интенсивностью освещенности. От локального источника лучи
равномерно распространяются во все стороны. У объекта типа Axes может быть
несколько источников света. По умолчанию оси снабжаются бесконечно
удаленным источником белого света. Его угол возвышения совпадает с
углом возвышения позиции наблюдателя, а азимут на 45° больше азимута
наблюдателя.
Визуализация трехмерных объектов
441
Существует также полезная функция camiight, создающая источник света с
координатами, совпадающими с координатами точки зрения, или
находящийся рядом с ней:
□ camiight headlight — создает источник, совпадающий с точкой зрения;
П camiight right — создает источник правее и выше точки зрения;
П camiight left — создает источник левее и выше точки зрения;
П camiight — эквивалентно camiight right;
П camiight(az,el) — азимут и угол возвышения по отношению к точке
зрения;
П camiight(... 'style') — дает возможность задать тип источника (local
ИЛИ infinite);
П camiight (iight_handie, ...) — использует источник с заданным
указателем;
П lighthandie = camiight (...) — возвращает указатель на источник.
Отображение поверхности, освещенной источником света, во многом зависит
от свойств "материала" поверхности. Обратите внимание, что эти свойства
начинают работать только после создания в текущих осях источника света. Для
задания этих параметров используются уже упомянутые выше свойства
поверхности, управляющие отражающей способностью, — specuiarstrength,
SpecularExponent, SpecularColorReflectance. Кроме ТОГО, существуют И
другие свойства:
П Ambientstrength — интенсивность влияния рассеянного света. Цвет
рассеянного света Задается В свойстве AmbientLightColor объекта Axes.
Принимает значение от о до 1;
П Diffusestrength — степень диффузного рассеивания света от источника.
Принимает значение от о до i;
О Specuiarstrength — интенсивность отражения света от источника.
Принимает значение от о до 1;
П SpecularExponent — параметр, управляющий размером светового блика.
Должен всегда превышать 1. Для большинства встречающихся в природе
материалов значение попадает в диапазон от 5 до 20;
П SpecularColorReflectance — степень влияния цвета поверхности на цвет
блика. Принимает значение от о до 1. При о цвет блика является
смешанным цветом источника света и поверхности. При 1 цвет блика
определяется исключительно цветом источника света.
442
Глава 10
Типичные отражающие параметры поверхностей могут быть заданы
командой material, управляющей описанными выше свойствами:
П material shiny — блестящая поверхность;
П material dull — матовая поверхность;
П material metal — "металлическая" поверхность;
П material ([ka kd ks]) — устанавливает всем объектам одинаковые
значения СВОЙСТВ AmbientStrength(ka), DiffuseStrength(kd),
SpecularStrength(ks);
П material ( [ka kd ks n]) —TO же Самое, ПЛЮС SpecularExponent (n);
П material ([ka kd ks n sc] ) — то же, что предыдущее, плюс свойство
SpecularColorReflectance(sc);
П material default — возврат к значениям по умолчанию.
Следует отметить, что лучше всего разница видна при использовании
алгоритма визуализации Фонга (FaceLighting=phong). К тому же материал
поверхности в этом случае выглядит более правдоподобно.
10.2.7. Построение линий уровня
Под линиями уровня, или изолиниями, понимают кривые, получающиеся в
результате пересечения поверхности г(х,у) с плоскостями z=const. Эги
линии можно спроектировать на одну плоскость и получить 20-изображение,
а можно воспроизвести как пространственные кривые и построить 3D-
изображение. Наглядным примером 20-изображения изолиний являются
линии рельефа поверхности на топографических картах. По ним можно
легко локализовать вершины и впадины, оценить их высоты и глубины,
особенно, если в разрывах изолиний проставлены числовые значения
соответствующих уровней.
К числу наиболее употребительных функций, связанных с отображением
ЛИНИЙ уровня, ОТНОСЯТСЯ contour, contourf, contourc, contour3 И clabel.
Функция contour используется для построения проекций линий уровня на
плоскость ху и допускает несколько вариантов вызова:
contour (Z)
contour(Z,k)
contour(Z, v)
contour(X,Y,Z)
contour(X,Y,Z,k)
contour (X, Y, Z, v)
contour(...,'Свойство_1',Значение_1, ...)
Визуализация трехмерных объектов
443
В любом случае двумерный массив z размерности mXn представляет
аппликаты точек поверхности, по которым формируются и воспроизводятся
контуры линий уровня. Массивы х и y могут быть векторами размерности п и га
соответственно или матрицами той же размерности, что и г. Они задают
координаты узлов сетки, в которых определены аппликаты поверхности.
Если область определения поверхности квадратная и шаги по осям х и у
совпадают, то вместо пары аргументов (х, y) может быть задан только один
массив. Если задание координатной сетки отсутствует, то считается, что
абсцисса х пробегает значения от 1 до п, а ордината у — от 1 до ш.
Скалярная величина к залает количество уровней (т. е. количество высот по
оси г), для которых должны быть построены изолинии (количество самих
изолиний при этом может не совпадать с к, т. к. соответствующая плоскость
может дать несколько разных линий пересечения с поверхностью). Если
значение параметра к не задано, то количество уровней выбирается
автоматически из интервала [zmin, zmax]. Обычно оно не превышает 20 и делится
на 2 или 5.
Вектор v определяет набор уровней, для которых должны быть построены
изолинии. Если какие-либо его компоненты не принадлежат диапазону
[zmin, zitiax], то соответствующих изолиний не существует.
Функция contour, создающая графические объекты, наряду с описанными
выше аргументами, допускает задание парных аргументов ("свойство —
значение").
При любом варианте вызова функция contour может вернуть два массива:
[С h]=contour(...);
Массив с представляет матрицу с информацией о каждой изолинии. Его
можно рассматривать как длинную таблицу, состоящую из двух строк.
Первая колонка задает значение уровня изолинии и число содержащихся в ней
точек, следом располагается указанное количество пар (х=, ул) с
координатами точек изолинии. Вслед за первой изолинией в таком же формате
располагается информация о второй изолинии и т. д. Этот массив понадобится
в том случае, когда придется оцифровывать изолинии — включать в разрыв
линии значение ее уровня. Вектор h представляет собой набор указателей на
созданные графические массивы. Он тоже понадобится в качестве параметра
для оцифровки изолиний.
В примере 10.6 и на рис. 10.12 представлены проекции изолиний
поверхности, которую мы рассматривали в разд. 10.2.3.
444
Глава 10
fПример 10.6: Создание проекций изолиниигпо'веркн6стй ^^¾¾^^¾.¾^^¾
» [X,Y] = meshgridt[-2:.25:2]);
» Z = Х.*ехр{-Х.Л2 -У.л2);
» colormap(cool)
» contour(X,Y,Z, 20)
1.5
1
0.5
0
-0.5
-1
-1.5
-2
/' ... "'".. - Z ■ \
■ S , _- " у ,
• / "'" "'_' A\\
/' ■«■■ . Ш
■Un- /i
~*'" "-■■..—v. „_-=""'"
III v,—■^--..--o-.x - \
Щ5ЩУ
2-1.5-1-05 0 0.5 1 15 :
2
Рис. 10.12. Проекции изолиний поверхности
С помощью функции contourf можно закрасить в разные цвета области,
расположенные между смежными линиями уровня (пример 10.7, рис. 10.13).
: Пример 10.7. Создание разноцветных областей мёад fc;yfy^Jp|;:]
» colormap jet
» contourf(X,Y,Z,10)
Для оцифровки изолиний предназначена функция ciatoei, которой
передаются два входных параметра — матрица изолиний и вектор указателей на
линии уровня (пример 10.8).
"Т"Т?
1 Пример 10.8. Автоматическая оцифровка изолиний
» [C,h] = contour(X,Y,Z, 6) ;
» colormap gray
» clabel(C,h)
Иг у.., :Л .*• <л -Г :
Визуализация трехмерных объектов
445
Рис. 10.13. Заливка областей между изолиниями
В этом фрагменте использована серая полутоновая матрица цветности
(colormap gray), а результат работы кода представлен на рис. 10.14.
1.5
1
0.5
0
-0 5
-1
-1.6
-2
■ /-^% / '
ft % £gtf
о
rr &
-°-o^er--
2 -15 -1 -0.5 0 0.5
"""■--,... .^
"% 1 -
^
C^
1 1.5 :
?
Рис. 10.14. Автоматическая оцифровка изолиний
Автоматически выполненная оцифровка линий уровня выглядит не очень
привлекательно, особенно в районе концентрации изолиний. Довольно
трудно придумать алгоритм правильного выбора места размещения
цифровой отметки.
446
Глава 10
Поэтому функция clabel предусматривает ручной режим оцифровки, на
который можно выйти, задав дополнительный параметр (пример 10.9).
Пример 10.9. Ручная оцифровка изолиний |||>;
™ЕГ
ш
«-•■
» [C,h] = contour (X,Y,Z, 6) ;
» colormap gray
» clabel(С,h,'manual')
В этом случае на экране появляется графическое окно с неоцифрованными
изолиниями. Однако с помощью мыши вы можете переместить перекрестье,
направив его в точку выбранной изолинии, и после щелчка левой кнопкой в
заданной точке появится соответствующая оцифровка. Ее центр совпадает с
выбранной точкой. Пример ручной оцифровки показан на рис. 10.15. К
сожалению, качество ручной оцифровки тоже оставляет желать лучшего —
линии наезжают на оцифровку, угол наклона надписи иногда не совпадает с
изгибами кривой, количеством отображаемых цифр управлять нельзя.
2
1.5
1
0.5
0
-0 5
и
-1.5
I
-
I £
-
I
I
\
N
2 -1.5
^
) I
VJ I
/"
J
""■^__^ тт'~
-1 -0.5 0
'
—~~
05
1 1
-
\
1
• 1'.
-trf
с#'
1 1.5
2
Рис. 10.15. Ручная оцифровка изолиний
Функция contourc относится к категории низкоуровневых, к которой
пользователь напрямую не обращается. Ее вызывают функции contour, contourf
Визуализация трехмерных объектов
447
и contour3. Функция строит матрицу с параметрами изолиний, которую
возвращает в качестве результата своей работы:
С = contourс(Z) ;
С = contourc(X,Y,Z);
Изолинии в пространственном исполнении отображаются функцией contour-з.
Перечень ее входных параметров такой же, как и у функции contour.
Результат работы команды contour3 (x,y, z, 20) приведен на рис. 10.16.
Рис. 10.16. Изолинии в пространстве
Для изменения свойств изолиний можно воспользоваться массивом
указателей, который возвращает функция contour.3 (пример 10.10).
! Пример 10г10. Изменение толщины изолиний Т.?: --.,^-1 %' ^%.^--., ,J
» [X,Y] = meshgrid([-2:.25:2]);
>> 2 = Х.*ехр(-Х.А2 -У.Л2).;
>> colormap copper
» [C,h]=contour3(XfY,Z,6);
» set(hr'LineWidth',2) % изменение толщины изолиний
448
Глава 10
Результат работы этого фрагмента, в котором толщина изолиний увеличена
до 2 пунктов, приведен на рис. 10.17.
Рис. 10.17. Утолщенные пространственные изолинии
10.3. Формирование
и отображение полигональных тел
10.3.1. Объект типа Patch и его свойства
Для построения полигональных тел (многофанников) используется функция
patch. Считается, что многофанники состоят из офаниченного числа вершин
(vertex) и фаней (Face). Каждая фань включает в себя 3 или более вершин.
При различных способах задания вершин и фаней можно добиться того,
чтобы вершины соединялись или не соединялись ребрами (Edge), входили в одну
или несколько фаней или вовсе не использовались при построении.
Существуют два основных способа построения фигур типа Patch:
П путем задания координат вершин каждой грани, соединяя которые,
MATLAB строит фигуру;
П путем задания координат всех вершин многогранника и указания, какие
из них следует объединить в грани с заданными номерами.
Визуализация трехмерных объектов
449
В первом случае формат вызова функции выглядит следующим образом:
h_P = patch(X,Y,C)
h_P = patch(X,Y,Z,C)
Здесь x, y, z — это векторы значений х-, у- и ^-координат вершин
многогранника (или многоугольника в случае отсутствия г-координат), а с —
задает цвет в формате coiorspec. Аргументы х, y и z могут быть матрицами,
тогда для каждого столбца строится свой многоугольник. В любом случае
функция patch возвращает указатель на сформированный объект.
Для того чтобы построить правильный восьмиугольник, можно
воспользоваться фрагментом программы из примера 10.11.
Г'Прийер 1^^^ •; т^'";^ ^1¾¾^¾ ./_*■£
» t=0:pi/4:2*pi;
» X=sin(t);
» Y=cos(t);
» h_P = patch (X,Y, [1 0 0])
» axis equal
В этом случае в векторах х и у мы получаем восемь пар координат (на
самом деле 9, но первая и последняя точки совпадают) точек* равномерно
расположенных на окружности единичного радиуса. Функция patch
соединяет их и закрашивает полученный восьмиугольник красным цветом
(рис. 10.18). Последняя строка делает масштаб по обеим осям одинаковым,
чтобы многоугольник не казался сплющенным.
1
0.5
0
-0.5
-1
•
-1
-0.5
0
0.5
1
Рис. 10.18. Плоский восьмиугольный Patch
450
Глава 10
В примере 10.12 приведены свойства построенного объекта.
I Пример 10.12. Свойства восьмиугольника '\*Щ$ -¾ *■ "■'' ^""Ь^рВЩкт.
» get(h_P)
AlphaDataMapping = scaled
CData = []
CDataMapping = scaled
FaceVertexAIphaData = []
FaceVertexCData = []
EdgeAlpha = [1]
EdgeColor = [0 0 0]
EraseMode = normal
FaceAlpha = [1]
FaceColor = [1 0 0]
Faces = [ (1 by 9) double array]
LineStyle = -
LineWidLh. = [0.5]
Marker = none'
MarkerEdgeColor = auto
MarkerFaceColor = none
MarkerSize = [6]
Vertices = [ (9 by 2) double array]
XData = [ (9 by 1) double array]
YData = [ (9 by 1) double array]
ZData = []
FaceLighting = flat
EdgeLighting = none
BackFaceLighting = reverselit
AmbientStrength = [0.3]
DiffuseStrength = [0.6]
SpecularStrength = [0.9]
SpecularExponent = [10]
SpecularColorReflecuar.ee = [1]
VertexNormals = [ (9 by 3) double array]
Norma IMode- = auto
BeingDeleted = off
ButtonDownFcn =
Визуализация трехмерных объектов
451
Children = [3
Clipping = on
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [lOl'.OOl]
Selected = off
SelectionHighlight = on
Tag =
Type = patch
UIContextMenu = []
UserData = []
Visible = on
Задавая достаточно большое количество точек, можно получать на экране
плавные кривые, окружности, эллипсы. Приведенный пример 10.13 строит
на экране изображение круга, окрашенного плавно изменяющимися
цветами (рис. 10.19).
! Пример 10.13. Построение круга с плавной заливкой
» t=D:0.01:2*pi;
» X=sin[t);
» Y=cos(t>;
» patch (X,Y, [1 0 0])
» axis equal
» patch(X,Y,1: length(t))
Координаты вершин можно задавать не только как позиционные аргументы
функции patch, но и с помощью свойств xdata, Ydata, zdata Создаваемого
объекта:
h_P = patch('Xdata',X,'Ydata',Y)
В простых случаях координаты точек многоугольника можно задавать
непосредственно в цифровом виде. Пример 10.14 строит на экране желтый
прямоугольный треугольник с катетами, лежащими на осях координат ('у' —
константа, задающая желтый цвет — от англ. yellow).
452
Глава 10
1
0.8
0.6
0.4
0.2
0
-0.2
-0.4
-0.6
-0.8
.
*■
ий^'1'
&**■
'Р-! '
т#&. ■
1 ■ т£ -
■ К
\ jT л- •■
\ '""
\
\
i i ^~~——
-1 -0.5
;-.
:?„-:■ ■
>■ S4*
■'• ЩУ^
^¾¾
■ '/* :Vf
,*t >
-^#,-,
v4#
.. W
;f\X
0 0.5
1
1
Рис. 10.19. Плоский 628-гранный Patch
^Пример 10.14..Построение желтого треугольника ,-.¾ | - * :j'fti,""*w4^ >,.^*дай§£я
» X = [0 1 0J;
» Y = [0 0 1] ;
» patch(X,Y,'у')
Для того чтобы построить таким же способом многогранник, придется
задавать х, y и z в виде матриц, в которых для каждого столбца будет построен
свой многоугольник. Рассмотрим это на примере одного из простейших
случаев — попробуем нарисовать куб (рис. 10.20). Так как куб состоит из
6 фаней, то матрицы будут содержать 6 столбцов. Каждая фань состоит из
четырех вершин, поэтому в каждой матрице будет 4 строки. Попробуем
непосредственно записать значения (х, у, z) для вершин куба и построить
необходимые матрицы.
В табл. 10.1 зафиксированы значения координат вершин, образующих все
6 фаней куба. Рассмотрим заполнение таблицы на примере лицевой фани,
лежащей в плоскости xz. Грань образована вершинами со следующими
координатами: (0, 0, 0), (1, 0, 0), (1, 0, 1), (0, 0, I). Соответственно вектор значений
х-координат для построения этой грани будет иметь вид (0, 1, 1, 0). Он соста-
Визуализация трехмерных объектов
453
вит первый столбец матрицы х-координат. Аналогично для ^-координат:
(О, 0, 0, 0), для г-координат: (0, 0, 1, I). Проделав такую же работу для
остальных граней, заполняем все матрицы. Теперь каждый столбец соответствует
своей грани.
(о, о, 1)
(0, о, 0)
(1,1.1)
(1.0,0)
Рис. 10.20. Цциничный куб с координатами вершин
Матрица х-координат
0
1
1
0
1
1
1
1
0
1
1
0
0
0
0
0
0
1
1
0
0
1
1
0
Матрица у-координат
0
0
0
0
0
1
1
0
0
0
1
1
0
0
1
1
0
0
1
1
1
1
1
1
Таблица
10.1
Матрица г-координат
0
0
1
1
0
0
1
1
1
1
1
1
0
1
1
0
0
0
0
0
о
0
1
1
Проверяем результат (пример 10.15).
! Пример 10.15. Проверкаi содержимого ма^ртц^Ч^й^ ^ч.^;
» Х=[0 10 0 0 0; 111011; 111011; 010000];
» Y=[0 00001; 010001; 0 11111; 001111];
» Z=[0 010 0 0; 00 110 0; 1 1110 1; 111001];
» patch(X-,Y,Z, [0.5 0.5 0.5])
» axis equal
» view(3)
*ш*
454
Глава 10
Последняя команда устанавливает проекцию, используемую по умолчанию
для визуализации трехмерных объектов. Если этой команды не будет, то мьг
увидим только одну грань куба, лежащую в плоскости ху, — команда patch
по умолчанию устанавливает двумерный вид в создаваемых при своем
вызове осях. Результат работы программы — на рис. 10.21.
Рис. 10.21. Единичный куб
Теперь попробуем построить тот же куб вторым способом — задав матрицу
координат вершин и указав, какие из них необходимо объединить в грани.
В этом случае матрицы будут выглядеть следующим образом. Матрица
вершин v имеет три столбца — для х-, у- и z-координат вершим соответственно.
Поскольку у нас 8 вершин, то в матрице v окажется 8 строк и она будет
иметь следующий вид:
» V= [0 0 0;1 0 0;1 0 1;0 0 1;0 1 0;1 1 0;1 1 1;0 1 11;
Теперь необходимо построить матрицу F, в каждой строке которой будут
перечислены вершины, образующие соответствующую грань. Вершина
задается как номер строки матрицы v, содержащей координаты этой вершины.
Так как граней всего 6, то в матрице f появятся 6 строк, а поскольку каждая
грань включает в себя 4 вершины, то в ней будет 4 столбца:
» F=[l 2 3 4;1 2 6 5;2 3 7 6;1 6 8 5;3 4 8 7;5 6 1 S];
Визуализация трехмерных объектов
455
Проверяем:
»" patch! 'Vertices' ,V, 'Faces', F, 'FaceColor', [0,5 0.5 0.5])
»■ axis equal
>> view (3)
Результат работы программы полностью эквивалентен предыдущему способу
построения многогранников. Однако в последнем случае для построения
куба нам потребовался значительно меньший объем данных. В первом
случае нам пришлось сформировать три массива размерностью 4x6, т. с. по
24 элемента. Во втором случае таких массивов потребовалось всего два.
К тому же построение фигур вторым способом более наглядно.
10.3.2. Закрашивание объектов типа Patch
Для того чтобы окрасить многоугольник или многогранник, построенный с
помощью функции patch, можно кроме описанных выше способов
использовать свойства, приведенные в табл. 10.2. Объекты Patch в отличие от
объектов Surface не могут автоматически генерировать значение цвета в
зависимости от значения ^-координаты каждой вершины. Цвет граней можно
задать одним из трех следующих способов:
П одинаковый цвет для всех граней;
□ свой цвет для каждой грани;
П свой цвет для каждой вершины, используемый для плавных переходов
цвета.
В процедуре закрашивания объектов типа Patch могут принимать участие и
ребра — линии, соединяющие смежные вершины многогранника и
отделяющие грани одну от другой. Их окраска может быть задана одним из трех
аналогичных вариантов:
П одинаковый цвет" для всех ребер;
□ свой цвет для каждого ребра, определяемый цветом соответствующей
вершины;
П плавный переход цвета между точками ребра, определяемый цветом
соответствующей пары вершин.
Таблица 10.2
Свойство Значение
CData Определяет свой цвет для каждом грани или вершины на
основании данных о координатах вершин
CDataMapping Определяет, каким образом масштабируются цветовые
данные
456
Глава 10
Таблица 10.2 (окончание)
Свойство Значение
FaceVertexCDa.ta Определяет свой цвет для каждом грани или вершины на
основании данных о вершинах и гранях
EdgeColor Задает общий цвет для всех ребер или способ их
отображения: видимые, невидимые, с плавными переходами цвета
FaceColor Задает общий цвет для всех граней или способ их
отображения: видимые, невидимые, с плавными переходами цвета
MarkerEdgeColor Определяет цвет маркеров или цвет контура у
закрашенных маркеров
MarkerFaceColor Определяет цвет закраски маркеров
Рассмотрим некоторые свойства подробнее.
П Свойство CData. С помощью свойства CData можно задавать цвета для
каждой вершины, каждой грани или определить цвет для фигуры в
целом. Требуемое действие MATLAB производит в зависимости от типа
данных. Цвет может быть задан в виде индекса цвета в цветовой палитре,
. либо в виде цветовых составляющих RGB в формате truecolor. Цветовую
палитру можно отобразить рядом с рисунком с помощью команды
coiorbar. Более подробно задание цвета с помощью свойства CData
обсуждалось в разд. 7.7.
Рассмотрим случай с индексами цветов. Если значением CData является
число, то вся фигура будет закрашена цветом, соответствующим
заданному индексу. Для того чтобы каждой грани присвоить свой цвет,
потребуется матрица с единственной строкой, в которой каждое значение
будет определять цвет соответствующей грани. Рассмотрим пример 10.16.
! Пример 10.16. Монотонное.закрашивание граней куба .-: .,; .::J^~4^ui;i**^^#
» Х=[0 1000 0; 111011; 111011; 01000 0];
» Y= [0 0 0 0 0 1; О 1 0 0 0 1; 0 1 1 1 1 1; 0 0 1 1 1 1] ;
» Z=[0 0 1 0 0 0; 0 0 1100; 111101; 111001];
» С=[1 2 3 4 5 6];
» h=patch (X, Y, Z, ' у ■) ;
» set(h,'CData',С,'FaceColor','flat')
» coiorbar
» axis equal
» view(3)
Визуализация трехмерных объектов 457
Результат работы этого фрагмента представлен на рис. 10.22.
Рис. 10.22. Куб с разноцветными гранями
Для того чтобы закрасить разными цветами каждую вершину, придется
задать матрицу размерностью, соответствующей матрицам х-, у- и z-
значений (для куба 4x6). Тогда каждой вершине будет поставлен в
соответствие свой цвет. Поскольку в нашем случае вершины участвуют в
образовании нескольких граней одновременно, то и данные в матрице
CData для них должны совпадать. В случае задания цветов в формате
RGB приходится вместо одного значения указывать три и в последнем
случае (для задания цвета каждой вершины) нужно формировать
трехмерный массив 4x6x3, где в трех матрицах размерностью 4x6 хранятся
значения цветовых составляющих R, G и В для каждой вершины.
П Свойство FacevertexCData. Более наглядно выглядит способ задания
цветовых данных с помощью свойства FacevertexCData. В зависимости от
типа данных, используемых для задания значения свойства, применяются
различные способы закрашивания. В случае если матрица содержит один
столбец, то ее значения рассматриваются как индекс цвета в цветовой
палитре. Если значением является число, то вся фигура будет закрашена
одним цветом.
Когда матрица значений FacevertexCData содержит три столбца, то ее
значения интерпретируются как цветовые компоненты RGB в формате
truecolor. Количество строк в матрице может соответствовать либо коли-
458
Глава 10
честву вершин, либо количеству граней. Если в матрице всего одна
строка, то вся фигура будет закрашена одним цветом.
С случае, когда число строк равно числу граней в многограннике, каждая
грань будет окрашена в цвет, закодированной в строке матрицы
FaceVertexCData с номером, соответствующим номеру грани.
Рассмотрим окрашивание куба (пример 10.17).
Пример 10.17. Окрашивание куба ' "... ^¾¾¾^.¾¾^ %S;'' "'".:!
» V=[0 0 0; 1 0 0; 1 0 1; 0 0 1; 0 1 0; 110; 111; 0 11];
» F=[l 2 3 4; 1 2 6 5; 2 3 1 6; 1 4 8 5; 3 4 8 7; 5 6 7 8];
» FVCD=|1 0 0; 0 1 0; 0 0 1; 1 1 0; 1 0 1; 0 1 1| ;
»
patch('Vertices',V,'Faces',F,'FaceVertexCData', FVCD,'FaceColor','flat')
» axis equal
» view(3)
В случае, когда количество строк в матрице fvcd совпадает с
количеством вершин, цветовые значения будут присвоены вершинам. Если при
этом значение свойства FaceColor как и в предыдущем случае окажется
flat, то каждой грани будет присвоен цвет вершины, с которой
начинается ее построение. Поэтому после работы следующего примера
некоторые грани будут окрашены одинаково:
» V=[0 0 0; 1 0 0; 1 0 1; 0 0. 1; 0 10; 110; 11]; 0 11];
» F=[l 2 3 -5; 1 2 б 5; 2 3 7 6; 1 4 8 5; 3 4 В 7; 5 б 7 8] ;
» FVCD=[1 0 0; 0 1 0; 0 0 1; 1 1 0; 1 0 1; 0 1 1; 0.5 0.5 0; 0.5 0
0.51;
»
patch('Vertices',V,'Faces',F,'FaceVertexCData', EVCD, 'FaceColor', 'flat')
» axis equal
» view(3)
Кстати, свойство FaceColor лучше всегда задавать, чтобы избежать
неожиданных результатов на экране (например, грани не отображаются).
Чтобы избавиться от одноцветных граней, придется изменить порядок
указания вершин в матрице f так, чтобы все грани начинались с разных
вершин:
» F=[l 2. 3 4; 6 5 1 2; 2 3 7 б,- 4 8 5 1; 3 4 8 7; 5 6 7 8];
Теперь у нас получится такой же разноцветный кубик, как и на рис. 10.23,
только порядок цветов слегка будет отличаться. Однако способ задания
цветов для каждой вершины позволяет добиться некоторых
дополнительных возможностей при закрашивании.
Визуализация трехмерных объектов
459
К
0 8-
0.6-
04-
0.2-
о>
1 \^\
0.5^-
0
- *"
0
0.5
1
Рис. 10.23. Куб с окрашенными гранями
1
0.8
0.6
0.4
0.2
0
1
£■"■.)"
■"%■
-¾
.С*й<
0.5
^«■.1* "| . ^л. ^
, -^-^5^^.:.--- -
->tf- .. i
- ? Iff
. ■&, ■
1¾^ ■
3
ж.
?-i
,. ai
iff
о" e
■ ^^.
•^ 1
0.5
Рис. 10.24. Куб с плавными переходами цвета и видимыми ребрами
460
Глава 10
Замена значения свойства FaceCoior на interp позволяет добиться
плавного перехода цветов на гранях:
patch('Vertices',V,'Faces',F,'FaceVertexCData', FVCD,'FaceCoior','interp')
Если одновременно значением свойства EdgeCoior будет flat, то на
фоне плавных переходов цветов граней будут видны разноцветные ребра
(рис. 10.24).
10.4. Специальные способы закраски.
Прозрачность
10.4.1. Нанесение изображения на поверхность
Задачи трехмерной графики часто требуют нанесения на поверхность
сложного узора или графического изображения. Сформировать в таком случае с
помощью ручного ввода или математических методов содержание для
свойства CData представляется слишком трудоемкой задачей. Гораздо удобнее
воспользоваться графическим объектом типа image. И MATLAB
представляет для этого простые и удобные средства.
Попробуем с ними познакомиться на примере задачи "натягивания"
графического изображения на сферу. Построим сферу, получим на нее указатель
и загрузим графическое изображение из файла (пример 10.18).
! Пример 10.18. Построение сферы ч ■ ' * --."'"-' '■"■''' ^1^^]¾¾^1^^^
» sphere
» h=findobj['Type','surface');
» a=imread('с:\Downloads\mask.jpg');
» whos
Name Size Bytes Class
a 272x272x3 221952 uint8 array
h lxl 8. double array
Grand total is 221953 elements using 221960 bytes
Как видно, объект тина image содержит изображение в формате truecolor
размером 272x272 пиксела. Для "натягивания" изображения на сферу
достаточно установить следующие свойства:
» set(h,'CData',a,'FaceCoior','texturemap')
» view ([-85 40])
Визуализация трехмерных объектов
461
К сожалению, изображение получилось перевернутым вверх ногами (кстати,
MATLAB всегда переворачивает изображение). Так что повернем сферу
вокруг оси х на 180° (рис. 10.25):
» rotate(h,[1 0 0],180)
Заметим, что в данном случае не действует привычное правило о том, что
каждой вершине или грани соответствует одно значение свойства cData. Мы
специально оставили видимыми ребра сферы, чтобы легче было заметить,
что каждый пиксел изображения (т. е. каждое значение свойства CData)
соответствует пикселу визуализированного изображения сферы. В системах
трехмерного моделирования такой способ задания цвета носит название
texture mapping. В результате изображение масштабируется и подстраивается
под реальный размер трехмерного объекта на экране.
Рис. 10.25. Изображение, "натянутое" на сферу
Обратите внимание, что такой способ закраски действует только в
отношении поверхностей, т. е. объектов типа surface. К объектам типа Patch такая
схема неприменима.
462
Глава 10
10.4.2. Прозрачные поверхности
В общем случае прозрачность всех объектов в текущих осях можно
регулировать функцией alpha. Формат обращения к ней следующий:
alpha (tace_alpha)
alpha(alpha_data)
alpha(alpha_data_mapping)
alpha(object_handle,...)
В первом случае при задании значения face_aipha можно задать степень
прозрачности всех объектов типа image, Patch и surface. Значения могут
быть следующими:
П число — устанавливает степень прозрачности в диапазоне от о до i;
П 'flat' — каждая грань имеет одинаковую степень прозрачности;
П 'interp' — каждая грань имеет изменяющуюся степень прозрачности;
□ 'texture' — прозрачность каждой грани задается набором данных типа
Image;
П 'opaque' — все объекты полностью непрозрачные;
П 'clear' — все объекты полностью прозрачные.
В случае установки параметров 'fiat', 'interp' и "texture" потребуется также
определить у объектов свойство AlphaData, размер которого должен
совпадать с размером ZData.
Аргумент aipha_data может принимать следующие значения:
П матрица — непосредственно устанавливает значение свойства AlphaData;
П 'х' — устанавливает значение AlphaData совпадающим с XData;
П 'у' — устанавливает значение AlphaData совпадающим с YData;
О V — устанавливает значение AlphaData совпадающим с ZData;
П 'color' — устанавливает значение AlphaData совпадающим с cData;
Р 'rand' — устанавливает случайные значения для прозрачности.
Пример сферы, построенной по умолчанию после команды alpha {'г,'),
приведен на рис. 10.26.
Свойства прозрачности имеют много общего со свойствами цвета. Можно
оперировать как с непосредственными значениями прозрачности,
заданными в форматах double или uinte, так и пользоваться индексами в шкале
прозрачности alphamap, являющейся аналогом eolormap.
Визуализация трехмерных объектов
463
С помощью функции alpha можно управлять значением свойства
AlphaDataMapping у всех объектов в текущих осях:
П 'попе' — в этом случае значения массива AlphaData используются как
значения прозрачности;
П 'direct' — в этом случае значения массива AlphaData выступают как
индексы в текущей шкале прозрачности alphamap;
П 'scaled' — в этом случае элементы массива AlphaData масштабируются от
минимального до максимального значения свойства аьш текущих осей.
Значение 'scaled' у AlphaDataMapping всех объектов устанавливается по
умолчанию.
Рис. 10.26. Сфера с изменяющейся по оси z прозрачностью
Используя формат alpha (objectjnandle, значение), можно устанавливать
параметры прозрачности для отдельного объекта. Но для этого можно
воспользоваться и функцией set. Чтобы получить изображенную на рис. 10.26
сферу с плавно изменяющейся по оси z прозрачностью, достаточно
выполнить следующие команды:
» sphere
» axis equal
» h=findobj('Type','surface');
464
Глава 10
» a=get (h, ' ZData') ,-
» set(h,'AlphaData',a,'FaceAlpha','interp')
При работе со свойствами объектов существуют некоторые изменения. Во-
первых, свойство AlphaData должно быть в нашем случае представлено
матрицей размерности, совпадающей с ZData (XData и YData). Пользоваться
значениями типа У нельзя, поэтому нам и пришлось считать значение
ZData в отдельный массив. Во-вторых, появилось свойство FaceAlpha. Оно
может принимать числовое значение от о до i, fiat, interp и texturemap.
В случае числового значения (по умолчанию устанавливается 1) все грани
объявляются непрозрачными (для 1), прозрачными (для о) или
полупрозрачными со степенью прозрачности, пропорциональной значению.
В случае fiat прозрачность для каждой грани является постоянной
(определяемой массивом AlphaData), в случае interp прозрачность грани
плавно изменяется (значения прозрачности также берутся из AlphaData).
Для того чтобы использовать в качестве карты прозрачности объект типа
image, надо задать свойство FaceAlpha равным texturemap. В случаях
задания flat или interp возникает ограничение, что размерность AlphaData
должна совпадать С размерностью XData, YData И ZData.
Использование графического файла (или иным образом созданного объекта
типа image) оправдано в тех случаях, когда требуется нарисовать
изображение со сложными свойствами прозрачности.
Глава 11
Полиномы
11.1. Представление полиномов
Полиномы от одной переменной имеют в MATLAB два разных
представления — в виде вектора-строки из числовых коэффициентов и символьное,
т. е. почти в "обычном" виде. Например, полиному -2хЗ+х-1 соответствуют:
П вектор коэффициентов [-2 о i -1] или [-2,0,1,-1];
П символьное выражение -2*хЛ3+х-1.
Для преобразования из одного формата представления полинома в другой
(пример 11.1) используются функции poly2sym (для перехода от вектора
коэффициентов к символьному представлению) и sym2poiy (для перехода от
символьного представления к вектору коэффициентов).
^Пример 11.1. Преобразование представления полиномов - - -^.-1
» poly2sym<[-2 0 1-1])
ans =
-2*хЛ3+х-1
» poly2sym([-2,0,l,-l])
ans =
-2*х~3+х-1
» syms х; % объявление символьной переменной х
» sym2poly{-2*x~3+x-l)
ans =
-2 0 1-1
Объявление символьной переменной, которое было сделано в предьщушем
примере с помощью типа данных syms, допускает в одной строке
перечисление нескольких имен, разделенных пробелами:
» syms xl х2 хЗ
» whos
466
Глава 11
Name
xl
x2
x3
Size
lxl
lxl
lxl
Bytes
1.28
128
128
Class
sym object
sym object
syra object
Другая возможность объявления переменной символьного типа
предоставляется функцией sym. Как правило, имя символьной переменной и его
запись в виде строки — аргумента функции sym — должны совпадать
(пример 11.2).
[Пример 11.2. Использование функции sym *■/' '* ■s**( t. ,,'~L'~ ^,:2 ,.. !i-..;
» y=syrti('y') ;
» whos
Name Size Bytes Class
у lxl 126 syra object
Если к функции poly2sym обращаются только с числовым вектором
коэффициентов, то она автоматически создает символьную переменную х и
строит полином с ее использованием. Однако если к этой же функции
обратиться с двумя входными аргументами, то полином будет построен
относительно указанной переменной:
■>> syms у
» poly2sym([-2 0 1 -1],у)
ans =
-2*у'Л3+у-1
Для каждого из двух способов представления полиномов имеется свой
"ассортимент" операций.
11.2. Операции над полиномами,
представленными вектором коэффициентов
11.2.1. Значение полинома
Для вычисления значения полинома (пример П.3) применяется функция
polyval, реализующая схему Горнера:
y^polyval(p,x);
Здесь:
Пр- вектор коэффициентов, расположенных в порядке убывания степени х;
Полиномы
467
П х — значение аргумента;
О у — значение полинома.
Аргумент х может быть вектором или матрицей. Тогда значения полинома
вычисляются отдельно для каждого компонента, а результат у будет иметь
такую же размерность, как и аргумент х.
(Пример 11.3. Вычисление значения полинома "-.. .„ , -rS... - ж
» p=fl,-l];
» х=[1 2;3 4];
» yl=polyva.l (р, х)
У1 -
О 1
2 3
Независимой переменной в полиномах может быть не только скаляр, но и
квадратная матрица. Тогда значением полинома является также квадратная
матрица. Ее можно вычислить с помощью функции poiyvaim (пример 11.4).
; Пример 11А Вычисление полинома от матричного операнда - **'■• • I
» р=[1,-1];
» х=[1 2;3 4];
» y2=polyvalm(p, х)
О 2
.3 3
В этом примере полином имеет вид х-а, поэтому из матрицы х вычитается
единичная матрица.
11.2.2. Сложение и вычитание
Если степени полиномов совпадают, то совпадают и длины представляющих
векторов. В этом случае можно просто сложить или вычесть эти векторы.
В противном случае, когда степени полиномов различны, такой простой
способ не годится — вначале надо выровнять длины представляющих
векторов. Именно так работает функция poiysum, приведенная в [3]:
function s = poiysum(p,q)
% POLYSUM Сложение и вычитание двух полиномов
468
Глава 11
% С = polysum(A,B) вычисляет сумму С = А + В
% С - polysum(A,-B) вычисляет разность С = А - В
% length(С)=max(length(A), length(В)).
%
maxlen = max(length(pj, length(q));
pi = zeros(1, maxlen);
ql = zeros(1, maxlen);
pi (maxlen-length (p) +1 .-maxlen) = p;
ql(maxlen-length(q)+l:maxlen) = q;
s = pi + ql;
11.2.3. Умножение и деление
Для выполнения этих операций используются функции conv (свертка) и
deconvl
с = conv (а, Ь);
[q, г] =deconv (а, Ь) ;
Вектор коэффициентов с — полином, являющийся произведением
полиномов, представленных векторами коэффициентов а и ь. Векторы
коэффициентов q и г — полиномы, являющиеся частным и остатком от деления
полиномов, заданных векторами коэффициентов а и ь:
a=conv(b,q)+r,-
Для получения только частного к функции deconv можно обратиться с
одним выходным аргументом:
q=deconv(a,b);
Проверьте школьным способом результаты работы фрагмента из
примера 11.5.
!:,.Прй'мер!11;'5; Умножение и деление:полиномов'Ъ&£$: g'-./ t&dUid-:*^#'-.->й~
» pl=[1,0,-2];
» р2=[2,1,-1,4);
» plp2=conv(pl,p2)
plp2 =
2 1-5 Z 2-8
» [d,r]=deconv(plp2,[1,-1])
Полиномы
469
d =
2 3-202
г =
0 0 0 0 0-6
11.2.4. Дифференцирование
и интегрирование
Для дифференцирования полипома, представленного вектором
коэффициентов р, используется функция polyder:
d=polyder(р);
Функция возвращает вектор коэффициентов производной d. Если к —
степень ПОЛИНОМа р, TO d(l)=k*p(l), d(2) = (k-l) *р(2> и т. д.
Та же функция при обращении к ней с двумя входными аргументами —
polyder (p,q) — находит либо производную от произведения полиномов
(p*q), либо производную от дробно-рациональной функции (p/q)".
d=polyder(р,q); % d - производная от p*q
[c,d]=polyder(p,q]; % производная от p/q
Значение производной от дробно-рациональной функции формируется
также в виде дробно-рациональной функции c/d, где векторы с и d
представляют полиномы — числитель и знаменатель производной.
Приведем пример 11.6.
;^..,..„;р^.г.„„;..^т.7„.та.г...^
[;Примёр;1.1.6.Вь1Чйслен»1епроизводной:?' '^^S^flJ^ ... ЩШ^ ^■.:%$.г\
» р=[1 -1 0];
» q=tl 1'];
» d=polyder(р, q)
d =
3 0-1
» [a,b]=polyder(p,q)
a =
12-1
b =
12 1
Следует отметить, что функция polyder: не отличается особым интеллектом.
В том случае, когда числитель и знаменатель производной от p/q допускают
сокращение, функция этого не делает (пример 11.7).
470
Глава 11
j Пример 11.7. Недостатки в работе функции poiyder , , „:|
» р=[1,-1,0];
». q=[l,0];
» [a,b)=polyder (р, q)
а -
10 0
ь =
10 0
Очевидно, что х2/х2=1. Поэтому эквивалентный результат мог бы
выражаться и более короткими векторами: a=[i],b=[i].
Для интегрирования полинома р применяется функция poiyint:
q=polyint(р,с);
Вторым аргументом в этой функции является константа интегрирования с
(свободный член первообразной). Если в обращении аргумент с опушен, по
умолчанию принимается с=о. Функция возвращает результат в виде вектора-
полинома q.
11.2.5. Корни полинома
Для вычисления всех корней полинома р используется функция roots:
» r=roots(р) ;
Функция roots возвращает вектор-столбец г, компонентами которого
являются корни полинома р (пример 11.8).
: Пример 11.8. Нахождение корней полинома
» р=[1 2 2 0 0];
» roots(р)
ans =
Р
О
-1.0000 + l.OOOOi
-1.0000 - l.OOOOi
По известным корням xi, х2, ..., хп полинома степени п нетрудно
восстановить коэффициенты приведенного полинома (коэффициент при старшей
степени равен l):
РЯ = (X-Xi) * (х-х2) * . . . " (х-хя)
Полиномы
471
Если вектор х представляет корни полинома, то восстановление вектора р
его коэффициентов осуществляется с помощью функции poly:
р= poly(х) ;
С поиском корней полинома тесно связана задача интегрирования дробно-
рациональной функции p/q, числитель и знаменатель которой являются
полиномами степени п и m соответственно. Если n>m, из дроби p/q можно
выделить частное — полином s степени n-m и "правильный" остаток r=pi/qi.
В свою очередь, остаток г можно представить в виде суммы "простых"
слагаемых вида zi/(x-xi) и (ui^x+vi) / (bi*x2+ci*x+di). Знаменатели этих
дробей можно найти, зная корни полипома qi. В случае кратных корней
вид указанного разложения несколько иной. Но так или иначе, вычисление
интеграла от разложения, найденного таким способом, — задача на порядок
более простая, чем интегрирование исходной функции.
MATLAB предлагает функцию residue, которая помогает найти указанное
разложение дробно-рациональной функции p/q:
» [х,р,s]=residue{p,q); —
Более подробную информацию о возможностях функции residue вы
получите, набрав команду help residue.
11.3. Операции над полиномами,
заданными в символьном виде
11.3.1. Значение полинома
Для вычисления значения символьного полинома р используется функция
subs (подстановка), которая подставляет на место независимой переменной
заданное число или символьное выражение (пример 11.9).
Пример 11:9; Вычисление значения символьного полинома _ .-=¾¾
■» syms х a b % объявление символьных переменных
» Р==хЛ2-х; % объявление полинома Р
» subs(Р,2) % подстановка числа
ans =
2
» subs(Р,a+b) % подстановка символьного выражения
ans =
(а+Ь)Л2-а-Ь
16 За к. 809
472
Глава 11
Если в записи полинома кроме независимой переменной используются
другие символьные параметры, то функция subs разрешает замену и таких
параметров, однако в этом случае нужно задавать три аргумента — имя
полинома, имя замещаемого параметра и подставляемое выражение
(пример НЛО).
[; Пример 11 ;10.Вь1числе»ние полинома с символьными ^рэф^ициентами/'ЗР;^;
» Q=a*x~2-x;
» subs (Q, a,b+l)
ans =
(Ь+1)*хл2-х
» subs[Q,x,1)
ans =
a-1
Если надо произвести подстановку сразу в несколько символьных
параметров, то список замещаемых параметров задается в виде ячейки (т. е. в
фигурных скобках) на месте второго аргумента и точно таким же способом на
месте третьего аргумента задается список замещающих выражений
(пример 11.11).
[Пример 1Д;11. Подстановканескольких символьны^парщ^ров^'^^}^-^!!!''.»^
» subs(С,{х,а}, {3,1})
ans =
6
» subs(Q, (а,х), (Ы-1,2})
ans =
4*b+2
11.3.2. Сложение и вычитание
Полиномы, представленные в аналитическом виде, можно складывать и
вычитать, используя знаки обычных арифметических операций. В
результирующем полиноме автоматически производится приведение подобных
членов, имеющих однотипные коэффициенты (пример 11.12).
[Пример 11.12: Сложение и вычитание полиномов ■ 1Ъ г- ;,,- а\с!
>> syms х а
» Р=хл2-х;
Полиномы
473
» 0=а*хл2-х;
» R=x-1;
» P+Q
ans =
х'л2-2*х+а*хл2
» P-R
ans =
хл2-2*х+1
» P+R
ans =
x"2-l
11.3.3. Умножение и деление
Непосредственное использование операций * и / создает не полиномы, а
выражения, представляющие собой произведение двух полиномов или
дробь, числитель и знаменатель которой являются полиномами
(пример 11.13).
Не производится автоматически и сокращение дроби, когда числитель и
знаменатель имеют общие множители.
|. Примере.1.13..Умножение и деление полиномов Г ..„у, ' ^
:а^;.';г.Лй;-..л.^.Л?л.;^^<№й.;л..;.*&<.Л-.'::..-.: ;.. .'.i rn.i.. ■&:■.'..^.¾¾..^..¾¾.^.. :». . .'.; :.и'.Л5г. лч.'г. .:. ": -.г. Л -■.;
» Р = хЛ2-х;
» S=x;
» P+S
ans =
(хл2-х)*х
» P/S
ans =
(х'2-х)/х
Для "нормализации" полученных выражений MATLAB предлагает две
функции. Первая из них — simplify (упрощать). Хотя она и упрощает заданное
выражение, не всегда возвращаемый ею. результат является полиномом:
» simplify(P*S)
ans=
хЛ2*(х-1);
474
Глава 11
Функция simplify выполняет сокращение дроби, если числитель и
знаменатель заданного выражения имеют одинаковый множитель. При этом
может получиться как полином, так и более простое дробное выражение
(пример 11.14).
; Пример 11.14. Упрощение полиномов ■•= ■■ '• ,!*Л 4^ "J"'^!
» simplify(P/S)
ans =
х-1
» 0=хЛ2+х;
»P/Q
» ans=
(х^2-х)/(хЛ2+х);
» sirrplify(P/Q)
ans = г
(х-1)/(а*х-1)
Вторая функция — expand (раскрывать формулу). Она раскрывает скобки
и в случае произведения полиномов возвращает также полином
(пример 11.15).
» expand(P*S)
ans=
хЛ3-хЛ2;
11.3.4. Дифференцирование
и интегрирование
Для дифференцирования символьного полинома р используется функция
diff (пример 11.J6).
."■■"•■■ r-«:-v7:-T^" ;-™^?г"";™ " ^Т":"Г^"Т^"^^^'Щ^^"'ЩШШ^Щ^
; Пример 11.16. Дифференцирование символьного полинома ^. " ' я* -.iV't'J
» Р=хЛ3-2*хЛ2+5*х-3;
» diff (Р)
ans =
3*хл2-4*х+5
Полиномы
475
Обращение к этой функции со вторым аргументам к позволяет найти к-ю
производную:
» diff (Р, 2)
ans =
б*х-<3
» diff(Р,3)
ans =
6
Коэффициенты полинома могут зависеть от одного или нескольких
параметров. Функция diff допускает не только дифференцирование по любому
такому параметру, но и находит k-ю производную по указанному параметру
(пример 11.17).
[Пример 11.17. Поиск производной по символьному параметру. "•*» ^¾^\р§, ■;?,' "$\
» syms х в
» К=хЛ3-2*а*хЛ2+5*х-3;
» diff(R,а) % первая произведшая по а
ans =
-2*хл2
» diff(R,а,2) % вторая производная no а
ans =
О
Неопределенный интеграл от символьного полинома вычисляется с
помощью функции int, допускающей несколько вариантов обращения. В
простейшем случае у нее единственный аргумент — подынтегральное
выражение (пример 11.18).
I Пример 11.18. Интегрирование символьного полинома ■■■■':. * :,. й-»ай
» Р=хЛ3-'2*хЛ2+1;
» iiit(P)
ans =
1/4*хл4-2/3*хлЗ+х
_il
476
Глава 11
Добавление двух дополнительных аргументов в функции int позволяет
вычислять определенные интегралы с заданными пределами:
» int(E,0,2) % интеграл от 0 до 2
ahs =
2/3
Пределы интегрирования могут быть не только числовыми значениями, но
и символьными выражениями:
» int[P,a,a+2)
ans =
1/4*(а+2)Л4-1/4*аЛ4-2/3*(а+2)А3+2/3*а*3+2
11.3.5. Корни и разложение
полинома на множители
Для нахождения корней полинома, представленного в символьном формате,
необходимо обратиться к функции solve, аргументом которой может быть
имя полинома, строка с аналогичным выражением или явная запись
формулы полинома (пример 11.19).
; Пример 11.19. Поиск корней символьного полинома ?"•.■ «-' -¾¾.. ;,. >;.*<;,,:- ,,v.,,..-M\-rifl
» syms х
» Р = х~3+9*х-26;
» s = solve(Р);
» si = solve(хл3+9*х-26) ;
» s2 = боЬлэ('хлЗ+9*х-26');
Все три обращения дают идентичный результат — вектор-столбец,
компонентами которого являются корни полинома:
» S
S =
[ 2)
[ -l+2*i*3~(l/2)]
[ -l-2*i*3"(1/2)]
С помощью функции solve можно получить, например, известную формулу
для корней квадратного уравнения (пример 11.20).
Полиномы
477
'■■'и''""-"'-'""'' 'л м — — '"'"* - ■'i--, . ■ "■ ."■ " „ V? -'- 1. ""'■"- Yf'"" .*" i ■* -. . " ".Чьим" ,J>'SV.'A ;"ca-jri '- " .* *" ""-
цПример .11.20..Формула для ;корнеи квадратного уравнения ~л> ^р ^:'i
» syms х a b с
» s=solve(a*x"2+b*x+c)
s =
[ 1/2/а*(-Ь+(ЬЛ2-4*а*с)Л(1/2))]
[ 1/2/а*(-Ь-(Ьл2-4*а*с)л(1/2>)]
Примерно так же можно получить аналитические выражения для корней
полиномов третьей и четвертой степеней. Правда длина таких выражений
может достигать 300—400 символов, так что проще искать корни
полиномов, представленных векторами коэффициентов.
Для полиномов выше четвертой степени в общем случае решения в
радикалах не существует, и система MATLAB с этим фактом знакома:
» solve(хЛ5+х-а) ,
??? Error using ==> solve
Error, (in allvalues/rootseq) cannot evaluate with symbolic
coefficients
С помощью функции factor (P) можно разложить полином р на
сомножители (пример 11.21).
^Пример 11.21, Разложение на множители""-"-" '* " 'ьл.' "j-'V .-г^&Г i "''-"'^Ч *{
» Р=хЛ2-х;
» factor(Р)
ans =
х*(х-1)
» Q=x"2-rx;
» factor(P*Q)
ans =
(х-1)*хл2*(х+1)
Если аргументом функции factor является дробь вида p/q, то числитель р и
знаменатель q раскладываются независимо друг от друга, после чего обшие
делители сокращаются (пример 11.22).
[Лритр'^^.Разложэииенамножит^л.и.дроб^...^ -.; -";?^\ _!*,
» factor(P/Q)
ans =
(х-1)/(х+1)
)
Глава 12
Линейная алгебра
Основным типом данных в MATLAB являются матрицы. Вектор-строка,
вектор-столбец и даже скаляр рассматриваются как частные случаи матриц.
Для матриц определены не только стандартные операции, изучаемые в курсе
линейной алгебры, но и ряд дополнительных. В связи с тем, что в материале
этой и последующих глав интенсивно используются матричные операции,
напомним вкратце некоторые детали.
12.1. Основные матричные операции
В табл. 12.1 приведена информация о стандартных операциях, в которых
матричные операнды обозначены через х и у, а скалярный операнд — через п.
Таблица 12.1
Формат Пояснения
операции
X+Y Сложение матриц. Операнды и результат имеют одинаковые
размеры
х+n или п+х Прибавление скаляра к каждому элементу матрицы
x-Y Вычитание матриц. Операнды и результат имеют одинаковые
размеры
х-n или n-Х Вычитание скаляра из каждого элемента матрицы или вычитание
каждого элемента матрицы из скаляра
X*Y Умножение матриц. Если размерность X равна pxq, а
размерность Y равна qxr, то размерность результата — рхг
х*п или п*х Умножение каждого элемента матрицы на скаляр
X' Транспонирование матрицы. Для вещественных матриц строки
становятся столбцами, а столбцы — строками. Для комплексных
матриц после этого все элементы заменяются комплексно-
сопряженными числами
480
Глава 12
Таблица 12.1 (окончание)
Формат Пояснения
операции
X. ' Транспонирование матрицы. Комплексные матрицы
транспонируются без изменения их элементов
inv (X) Обращение квадратной матрицы (вычисление х"!)
x\Y Левое деление матриц — аналог операции X_1*Y
X/Y Правое деление матриц — аналог операции x*Y_1
хлп Возведение квадратной матрицы в степень. Если п — целое, то
это эквивалентно умножению х*Х*... *х (п сомножителей). Для
вещественных или комплексных значений п степень вычисляется
как функция от матрицы с использованием собственных чисел и
собственных векторов. Результат операции — квадратная матрица
плх Возведение скаляра в матричную степень (х — квадратная
матрица). Результат вычисляется как функция от х с использованием
собственных чисел и собственных векторов. Результат операции —
квадратная матрица
kron (X, Y) Произведение Кронекера (тензорное произведение) X®Y.
Каждый элемент Xij матрицы х заменяется блоком xtj*Y. Таким
образом, элементами матрицы-результата являются
всевозможные произведения элементов матриц-сомножителей
MATLAB поддерживает операции покомпонентного умножения (x.*y, п.*у
или х.*п), деления (x./y, п./y, x./n, x.\y, n.\Y или х.\п) и возведения в
степень (х.Лу, п.лу или х.Лп). В отличие от обычных матричных операций
в этом случае перед знаком операции ставится точка. Любой из операндов
может быть скаляром. В противном случае матрицы-операнды должны
иметь одинаковые размеры. Таковы же размеры и матрицы-результата.
В табл. 12.2 приведены сведения о функциях, вычисляющих наиболее
употребительные характеристики матриц и векторов.
Таблица 12.2
Формат Пояснения
вызова
det (X) Определитель или детерминант квадратной матрицы
rank (X) Ранг матрицы — число линейно независимых строк (столбцов).
Ранг равен наибольшему порядку-ненулевого определителя
(минора), полученного вычеркиванием части строк и столбцов
Линейная алгебра
481
Таблица 12.2 (окончание)
Формат Пояснения
вызова
trace (X) След матрицы — сумма значений элементов, расположенных на
главной диагонали
norm (V) Евклидова норма вектора — корень квадратный из суммы
квадратов компонентов
norm(X) Сингулярная норма матрицы: наибольшее сингулярное число
(см. разд. 12.7.6); совпадаете максимальным отношением
norm (X*V) к norm (V) для ненулевого вектора v
norm(X, 'fro') Норма Фробениуса — квадратный корень из trace (Х'*Х)
size (х.) Размер матрицы — вектор из двух компонентов, первый из
которых равен числу строк X, а второй — числу столбцов
Вычисление ранга — довольно деликатная операция, она выполняется с
помощью сингулярного разложения матрицы (см. разд. 12.7.6). Ранг
определяется как количество сингулярных чисел si > s2 > ..., не являющихся
пренебрежимо малыми. Чтобы сделать определение ранга управляемым, следует
пользоваться модификацией функции rar.k(x, toi), где второй параметр
задает порог — сингулярные числа, меньшие его (они все неотрицательны),
считаются нулями. По умолчанию функция rank (X) использует
tol=max(size(X))*norm(X)*eps
где eps — установленная точность вычислений (по умолчанию eps=
=2.220<3е-01б).
12.2. Скалярное
и векторное произведение
Скалярное произведение геометрических векторов а и ь (т. е. направленных
отрезков на плоскости или в пространстве) равно произведению модулей
(длин) этих векторов на косинус угла <р между векторами, приведенными к
общему началу:
(a,b) = |a|*|b|*cos(p
В декартовой системе координат скалярное произведение вычисляется как
сумма произведений соответствующих компонентов обоих векторов:
(a,b)=a(l)*b(l)+a(2)*b(2)
(a,b)=a(l)*b(l)+a(2)*b(2)+a(3)*b{3)
(a,b)=a(l)*b(l)+a(2)*b(2)+...+a(n)*b(n>
482
Глава 12
Количество слагаемых равно размерности пространства. Один из способов
вычисления скалярного произведения заключается в использовании
функции dot (пример 12.1).
^Пример: 1¾¾ Вычисление скапя
» а=[1 -1 2];
» Ь=[2 4 1];
» c=dot{a,b)
с =
О
Функция dot одинаково хорошо работает и в тех случаях, когда оба вектора
представлены в виде столбцов или когда один вектор является строкой, а
другой — столбцом:
» c=dot(a',b')
с =
О
» c=dot(a,b')
с =
О
>> c=dot(a',b)
с =
.0
Вторым способом вычисления скалярного произведения является
использование функции sum (пример 12.2).
^Пр;имер^2.2;.ВМ1чИсл^ние скалярного произведения спонощью функции sum У
» и=-0.5:0.5:2
.и =
-0.5000 О
» v=2:-0.5:-0.5
v =
2.0008 1.5000
» sum(u.*v)
ans =
-1
0.5000 1.0000 1.5000 2.0000
1.0000 0.5000 0 -0.5000
Линейная алгебра
483
Скалярное произведение векторов тесно связано с вычислением нормы
вектора: для любого а имеет место равенство
dot(a,a)=norm(a)Л2
С помощью этих функций можно найти косинус угла между векторами:
cos_ab=dot(a,b)/(norm(a)*norm(b))
Буквальный геометрический смысл эта формула имеет в пространствах R2 и
R3, однако ее применяют и для векторов произвольной размерности,
рассматривая эту формулу как определение (пример 12.3).
; Пример 12.3. Поиск косинуса угла между векторами 1 **ЩЦ$Щ^''" ''"*■ :<; "Л*"*Ц
» cos_uv=dot(u,v)/(norm(и)*norm(v))
cos_uv =
-0.1290
Для рассматривавшихся выше векторов а и ь имеем cos_ab=0, т. е. эти
векторы взаимно перпендикулярны. Рассмотрим два других вектора, первый из
которых идет по биссектрисе между осями х и у.
» al=[l 1 0];
а второй — по биссектрисе между осями yuz.
» Ы=[0 1 1];
Для них косинус угла
» cosl=dot(:al,bl> / (norm(al) *norm(bl))
cosl =
0.5000
Теперь можно найти угол между векторами al и ы (в радианах):
» anglel=acos(cosl)
aiiglel =
1.0472
и перевести его в градусы:
» anglel_deg=anglel*180/pi
anglel_deg =
60.0000
Скалярное произведение векторов с комплексными компонентами,
вычисляемое функцией dot, представляет собой сумму произведений компонентов
484
Глава 12
первого сомножителя на числа, комплексно сопряженные к
соответствующим компонентам второго сомножителя (пример 12.4):
(а,Ь)=а(1)*Ь'(1)+а(2)*Ь'(2)+...+a(n)*b'(п)
^Пример 12.4, Скалярное произведение векторое с комплексными^! ^¾¾¾^
^компонентами. ^¾ .¾. t .• ,' ' -,.. ..,,'. " ЛЬ\',' ''+Щ, i
» p=[l+i -1 2-i];
» q=[2-i 2 1+i];
» r=dot (p, q)
r =
0
Векторное произведение определено лишь для векторов в трехмерном
пространстве. Для векторов а и ь их векторное произведение v=axb
удовлетворяет следующим условиям:
П |v| = |a|* |b|*sin(p, где ф— угол между векторами, отложенными от
одной точки (| v | равен площади параллелограмма, построенного на
векторах а и ь);
П вектор v перпендикулярен векторам а и ь;
П тройка векторов <a,b,v> ориентирована так же, как и координатные оси
<х,у, z>.
В декартовой системе координат векторное произведение v=axb выражается
формулами:
v(l)=a(2)*b(3)-a(3)*b(2)
v(2)=a(3j*b(l)-a(l)*b{3>
v(3)=a(l)*b(2>-a(2)*b(l)
В MATLAB для вычисления векторного произведения используется
функция cross (пример 12.5).
^"■щ^гщ^угу^т^у:;^^^' ™ " ■'■■'•^•■"™";ш"^^раа^^
|;Прийёр;12.5;-Вычисление векторного произведения j,s|||J^ .^-, _ ' Jjp'v "'
» a=[l -1 21;
» b=[2 4 1];
» v=cross (a,b.)
v =
-9 3 6
Линейная алгебра
485
Если один из векторов представлен в виде строки, а другой в виде столбца,
функция cross вычисляет строку:
» v=cross(a,fa')
v =
-9 3 6
» v=cross(а',Ь)
v =
-9 3 6
Если оба вектора представлены в виде столбцов, функция cross также
вычисляет столбец:
» v=cross(a',b')
v =
-9
3
б
Как сказано выше, норма векторного произведения равна площади
параллелограмма, построенного на векторах-сомножителях:
» S=norm(v)
S =
11.2250
Если компоненты векторов являются комплексными числами, функция
cross вычисляет результат по тем же формулам, однако векторное
умножение комплексных векторов не представляет интереса.
Довольно деликатной задачей является вычисление ориентированного угла
между векторами на координатной плоскости ху (пример 12.6).
{Пример 12.6. вычисление ориентированногр угла между векторами у .^ Л. ^. j
» а=[-3 3] ;
» Ь=[ 6 3];
» cos_ab=dot(a,b)I(norm(a)*norm(b))
cos_ab =
-0.3162
Ясно, что угол тупой, но какого знака? Чтобы узнать это, дополним векторы
до трехмерных, задав третью координату, равную о:
» аЗ=[а 0]
аЗ =
-3 3 0
486
Глава 12
» ЬЗ=[Ь 0]
ьз =
.6 3 0
Теперь можно найти векторное произведение:
» v=cross(аЗ,ЬЗ)
v =
О 0 -27
Единственная отличная от нуля координата этого вектора равна
произведению норм векторов аЗ и ьз и синуса угла между ними. Поэтому:
» sin_ab=v(3)/(norm(a3)*гюгт(ЬЗ))
sin_ab =
-0.9487
Знак свидетельствует, что этот угол отрицателен, т. е. поворот отакь
происходит в отрицательном направлении (по часовой стрелке, если система
координат правая). Значение этого угла в радианах можно найти с помощью
функции atan.2:
» alpha=atan2(sin_ab,cos_ab)
alpha =
-1.8925
Переведя этот угол в градусы, получим:
» a.lpha_deg=a.lpha*180/pi
alpha_deg =
-108.4349
Еще одна геометрическая задача, связанная с нахождением объема
параллелепипеда, построенного на векторах а, ь и с, решается с помощью
смешанного произведения векторов, определяемого как скалярное произведение
вектора а на векторное произведение ь*с:
v=a-(b*c)
Собственно объем параллелепипеда равен модулю смешанного
произведения (пример 12.7), и вычислить его можно по одной из формул:
| v | = abs (dot (a, cross (b,c) ) )
| v | = abs (sum (a. 'cross (b, c) ) )
j Пример 12.7. Вычисление объема параллелепипеда
» а = [4,0,0];
» b = [0,6,0.];
» с = [0,0,1];
Линейная алгебра
487
» abs (dot (a, cross (b, с)))
ans =
24
12.3. Стандартные матрицы,
фрагменты и блоки
Довольно часто в линейной алгебре используются единичные матрицы
(элементы главной диагонали равны 1, а все остальные — о), нулевые
матрицы (все элементы равны о), матрицы, все элементы которых равны
ненулевой константе (обычно i). Список функций, предлагаемый в MATLAB для
формирования таких матриц, приведен в табл. 12.3.
Таблица 12.3
Формат вызова Возвращаемое значение
еУе <п) Единичная матрица размерности пхп
eye (m, п) Единичная матрица размерности mxn
zeros (п) Нулевая матрица размерности пхп
zeros (га, п) Нулевая матрица размерности mxn
ones (п) Матрица размерности пХп, заполненная единицами
ones (in, п) Матрица размерности mxn, заполненная единицами
Для выделения элементов матрицы используются индексы, заключенные в
круглые скобки— x(i,j), где i определяет номер строки, a j — номер
столбца. Отсчет индексов ведется от 1. Можно использовать групповое
выделение элементов матриц с помощью обозначений, характерных для
операторов цикла,— beg:step:end (здесь beg— начальное значение индекса,
step — приращение, end — конечное значение индекса). Отсутствие
начального значения воспринимается как отсчет от 1, отсутствие шага
соответствует единичному приращению, отсутствие конечного значения
воспринимается как максимальный индекс. В табл. 12.4 приведены наиболее
характерные выделения.
Таблица 12.4
Формат выражения Пояснение
X (i, :) i-я строка матрицы х
X (il: i2, :) Строки матрицы X, начиная с 11 по х2
х (il:h: i2, :) Строки матрицы х, начиная с il по i2 с шагом h
488
Глава 12
Таблица 12.4 (окончание)
Формат выражения Пояснение
X (:, j ) j -й столбец матрицы X
X (:, j 1: j 2) Столбцы матрицы X, начиная с j 1 по j 2
X(:,jl:h:j2) Столбцы матрицы X, начиная с j 1 по j 2 с шагом h
X(il:i2,jl:j2) Подматрица, ограниченная строками с il по 12 и
столбцами с j 1 по j2. Возможно задание шага по любому
измерению
tr i 1 (X) Верхний треугольник матрицы х (включая главную диагональ)
t г i и (X) Нижний треугольник матрицы х (включая главную диагональ)
diag (X) Вектор-столбец, образованный элементами главной
диагонали матрицы х
diag (v) Квадратная матрица порядка length (v), главная
диагональ которой есть вектор v
diag (v, k) , k>0 Квадратная матрица порядка length (v) +k, k-я наддиаго-
наль которой есть вектор v
diag[v,k), k<0 Квадратная матрица порядка length (v)+abs (k), I k|-я
поддиагональ которой есть вектор v
[XI Х2 . .. ] или Горизонтальный блок, который представляет собой вектор-
[XI, Х2, ... ] строку из матриц xi, Х2,... Все матрицы должны иметь
одинаковое число строк
[XI; Х2; . .. ] Вертикальный блок, который представляет собой вектор-
столбец из матриц xi, Х2,... Все матрицы должны иметь
одинаковое число столбцов
blkdiag Блочно-диагональная матрица с блоками XI, Х2, ...
(XI,Х2,...)
12.4. Простые преобразования матриц
В табл. 12.5 приведены преобразования матриц, включенные в библиотеку
MATLAB.
Таблица 12.5
Формат вызова Выполняемая операция
xot90 (X) Матрица х поворачивается на 90°против часовой стрелки
rot90 (X, к) Матрица X поворачивается к раз
Линейная алгебра
489
Таблица 12.5 (окончание)
Формат вызова Выполняемая операция
flipud (X) Столбцы матрицы х переворачиваются "вверх ногами"
f liplr (X) Строки матрицы х переворачиваются "задом наперед"
f lipdim(X, dim) Переворот относительно размерности с номером dim
flipdim(X,l) Тоже, что flipud (X) (переставляются строки)
f lipdim(X, 2) То же, что f liplr (X) (переставляются столбцы)
reshape (X, m, п) Создает mxn-матрицу, заполненную элементами X. Заполнение
происходит по столбцам. Если X — матрица, ее элементы
выбираются также по столбцам. Если число элементов X не
совпадает с произведением m*n, выдается сообщение об ошибке
В примере 12.8 приведены несколько вариантов использования указанных
функций.
SS-'V...-." "■ ■""" '■-"i-VVrs™ •"""Г; ■■•-■у"-: -г--- -*™sw ) ■•; - _,
[Пример 1?8. Преобразования матриц (| . v«: .'. Л .^-.¾... '-'
» А = [12 3; 4 5 6]
А =
12 3
4 5 6
» ro.t90(A)
ans =
3 6
2 5
1 4
» flipud (А)
ans =
4 5 6
12 3
» f liplr (А)
■ans =
3 2 1
6 5 4
» В = reshape(A,3,2)
В =
1 5
4 3
2 6
490
Глава 12
12.5. Некоторые классы матриц
12.5.1. Симметричные
и кососимметричные матрицы
Квадратные матрицы, у которых Aij = Ац, называются симметричными.
Квадратные матрицы, у которых а15 = -а,ь называются кососимметричньши.
Диагональные элементы кососимметричной матрицы равны нулю.
12.5.2. Эрмитовы и косоэрмитовы матрицы
Квадратные матрицы, у которых Ai:j = а3д , называются эрмитовыми или
самосопряженными. Черта сверху означает здесь комплексное сопряжение.
Для эрмитовой матрицы а = а'. Диагональные элементы эрмитовой
матрицы вещественны.
Квадратные матрицы, у которых А:3 = -ADiI называются косоэрмитовыми.
Для косоэрмитовой матрицы А = -А'. Мнимые части диагональных
элементов косоэрмитовой матрицы равны нулю.
12.5.3. Ортогональные (унитарные) матрицы
Квадратные матрицы, у которых а"1 = А', в вещественном случае
называются ортогональными, а в комплексном — унитарными.
12.6. Специальные матрицы
12.6.1. Матрица Гильберта
и обратная к ней
Матрицей Гильберта называют квадратную матрицу с элементами i/(i+j-i).
Она является знаменитым примером плохо обусловленной матрицы.
Матрица Гильберта создается функцией hilb(n). Определители матриц
Гильберта очень быстро убывают с ростом п. Матрица, обратная к матрице
Гильберта, целомисленна, для ее точного построения можно воспользоваться
функцией invhiib(n) — пример 12.9.
| Пример 12.9. Матрица Гильберта ,; ■ - -&*" iiw ~'Т'х
» H=hi.lb(5)
5ПЗ =
1.0000 0. 50.00 0.3333 0.250.0 .0.2000
Линейная алгебра
491
0.5000 0.3333 0.2500 0.2000
0.3333 0.2500 0.2000 0.1667
0.2500 0.2000 0.1667 0.1429
0.2000 0.1667 0.1429 0.1250
» det(H)
ans =
3.7493G-012
» Hinv=invhilb(5)
Hinv =
25
-300
1050
-1400
630
» det(Hinv)
-300
4800
-18900>
26880
-12600
1050
-18900
79380
-117600
56700
2.6672e+011
12.6.2. Матрица Адамара
Матрицей Адамара называется квадратная матрица н порядка п с
элементами 1 или -1, такая, что н'*н=п*еуе(п). Это означает, что строки матрицы
Адамара попарно ортогональны. Матрица Адамара порождается функцией
hadamard(n) — пример 12.10. Матрица Адамара порядка п существует только
при п, кратных 4. Кроме того, п, п/12 или п/20 должно быть степенью 2.
Гпример;1рр!-№^
» hadamard(4)
ar.s =
1111
1-1 1-1
1 1-1-1
1-1-1 1
12.6.3. Матрица Паскаля
Матрицей Паскаля называется симметричная положительно определенная
матрица порядка п, сформированная из биномиальных коэффициентов.
Матрица Паскаля порождается функцией pascal(п) — пример 12.11.
0.1667
0.1429
0.1250
0.1111
-1400
26880
117600
179200
-88200
630
-12600
56700
-88200
44100
492
Глава 12
[^мер 12.1.1. rj^^m^A J"^... -Й^^Й^^ШЁ J
» pascal(4)
ans =
1111
12 3 4
1 3 6 10
1 - 4 10 20
12.6.4. Матрица Теплица
Каждый элемент матрицы Теплица t,, зависит только от разности индексов
(i-j). Вследствие этого:
tji = tjj - t.33 = - - -
ti2 = ta.> = t« = -. .
t21 = tj? = t«" — ...
Таким образом, теплицева матрица полностью определяется заданием
первого столбца и первой строки, причем первые компоненты этих двух
векторов должны совпадать. Матрица Теплица (пример 12.12) создается
функцией toepiitz (c,R). где с— заданный (первый) столбец, R— заданная
(первая) строка. Более простая команда toepiitz (К) создает симметричную
(в комплексном случае — эрмитову) матрицу Теплица с первой строкой r.
; ■■"■ v ■; ■ к- ■}
I Пример 12.12. Матрица Теплица ...:"' ' ' 1¾).^^^^^¾^^¾¾^.^%¾.¾
» С = [0; 1; 2; 33;
» R = [0 -1 -2] ;
» toepiitz(С,R)
ans =
0 -1 -2
10-1
2 1 0
3 2 1
12.6.5. Матрица Ганкеля
Каждый элемент матрицы Ганкеля ru3 зависит только от суммы индексов
(i+j). Вследствие этого:
Линейная алгебра
493
Таким образом, матрица Ганкеля полностью определяется заданием первого
столбца и последней строки, причем общие компоненты этих двух векторов
должны совпадать. Она формируется с помощью функции hankei(c,R), где
с — заданный (первый) столбец, r — заданная (последняя) строка. Более
простая функция hankei(C) создает симметричную матрицу Ганкеля с
первым столбцом с, причем все элементы ниже вспомогательной диагонали
(сумма индексов i+j > n+i) равны нулю (пример 12.13).
•'' »"■-—! ..,.-...-.....-.--.-...-.. „...„..„.,,....,.,..„..... „......,,,.......„.....,.,...............,.,,.,.,.,...,.. :■ я^д^; тадаиидявк
|}Пример. 12^.3. Матрица^анк^от '^Щ^^ф^ ^^-^у, Щ, > '--^Т:
» С =
» R =
[0;
[3
1;
-2 -
» hankel (С, К]
ans =
0
1
2
3
1
2
3
-2
» hankel(С)
ans =
0
1
2
3
1
2
3
0
2;
-4]
3];
;
2
3
-2
-4
2
3
0
0
3
0
0
0
Матрица Гильберта одновременно является и ганкелевой, тогда как
обратная к ней матрица ганкелевой не является.
12.6.6. Матрица Вандермонда
Элементы матрицы Вандермонда удовлетворяют следующим условиям:
П Vi^tCi)11"1, где с — предпоследний столбец матрицы v;
О Vi,n=l-
Матрица Вандермонда создается функцией vender (О — пример 12.14.
| Пример 12:14. Матрица Вандермонда •■•' ™ ■' ""'Ш> ^"/'." •-,*'"
» С = [2; 3; 51;
» vander(С)
494
Глава 12
ans =
4 2 1
9 3 1
25 5 1
12.6.7. Магический квадрат
Магическим квадратом называется квадратная матрица порядка п,
заполненная числами 1, 2, ..., nz таким образом, что суммы чисел в каждой строке, в
каждом столбце и в обеих диагоналях одинаковы и равны nx(n2+i) /2.
Магические квадраты существуют при всех п>2. Простые преобразования
(транспонирование, переворачивание строк и столбцов, поворот) сохраняют
свойство матрицы быть магическим квадратом.
Магический квадрат порядка п (один из многих возможных) создается
функцией magic (п) —пример 12.15.
! Пример 12.15. Магический квадрат'''^'- О'- ^к-"-^;"й-?
» magic (3)
ans =
8 16
3 5 7
4. 9 2
» magic (4)
ans =
16 2 3 13
5 11 10 8
9 7 6 12
й 14 15 1
12.7. Разложение матриц
Разложением матрицы называется ее представление в виде суммы или
произведения нескольких (чаще всего двух) матриц определенного вида.
12.7.1. Разложение Эрмита
Любую квадратную комплексную матрицу можно представить в виде
А = Hi+I*H2
Линейная алгебра
495
где матрицы Hi и н2 — эрмитовы (пример 12.16). Они определяются
однозначно и могут быть найдены.с помощью формул
Hi = (А+А')/2
Н, = (A-A')/(2i)
Напомним, что А' — матрица, полученная из а транспонированием с
последующей заменой всех элементов комплексно-сопряженными числами.
: .Пример ;Щ6^^лсшени^Зр|^^>^ ,,ti
» А=[3 -3-i; 1 0]
А =
3..0000 -3.0000 - 1.00001
1.0000 о
» Н1={А+А')/2
HI =
3.0000 -1.0000 - 0.5000i
-1.0000 + 0.5000i 0
» Н2=(А-А')/(2i)
Н2 =
0 -0.5000 + 2.0000i
-0.5000 - 2.00001 0
» B=Hl+i*H2
В =
.3.0000 -3.0000 - l.OOOOi
1.0000 о
Эрмитово разложение позволяет оценить собственные числа матрицы: по
теореме Бендиксона вещественные части собственных чисел матрицы А
заключены между наименьшим и наибольшим собственными числами
матрицы нь а мнимые части собственных чисел матрицы а заключены между
наименьшим и наибольшим собственными числами матрицы н2 (напомним,
что собственные числа эрмитовых матриц вещественны).
В приведенном выше примере:
П собственные числа матрицы А равны 2±i;
О собственные числа матрицы hi равны -0.3708 и З.з70в;
О собственные числа матрицы н2 равны ±2.0616.
Любую квадратную вещественную матрицу можно представить в виде
A = S+K
496
Глава 12
где матрица s — симметричная, а к — кососиммётричная. Они
определяются однозначно и могут быть найдены с помощью формул:
S = <А+А')/2
К = (А-А*)/2
iПример 12l 1?. Разложение квадратной •матрицыУ&С^Дт"--'' ^¾¾¾¾ "■ ■ ,1
» A=[4 -1 -2; 2 1 -2; 1-11]
A =
4 -1 -2
2 1-2
1-11
» S=(A+A')/2
S =
4.0000 0.5000
0.5000 1.0000
-0.5000 -1.5000
» K=(A-A')/2
К =
0 -1.5000
1.5000 0
1.5000 0.5000
» B=S+K
В =
4 -1 -2
2. 1 -2
1-11
12.7.2. Скелетное разложение
Пусть а — матрица размерности mxn ранга г. Ее можно представить в виде
произведения
А = В*С
где в — матрица размерности mxr, ас — матрица размерности гхп.
Сомножители скелетного разложения определяются неоднозначно (пример 12.18).
В качестве в можно взять любой базис пространства столбцов матрицы а,
тогда столбцы матрицы с состоят из коэффициентов разложений столбцов
матрицы а по столбцам матрицы в.
-0.5000
-1.5000
1.0000
-1.5000
-0.5000
0
Линейная алгебра
497
Можно предложить два варианта построения матрицы в:
□ применить функцию
[R,jb] = rref(A)
которая вырабатывает R-ступенчатую форму матрицы а и jfc — строку,
содержащую номера столбцов матрицы а, образующих базис. Матрицу в
можно получить, выделив эти столбцы:
В = A(:,jb)
□ применить функцию
В = orth(A)
В этом случае столбцы матрицы в представляют собой ортонормирован-
ный базис пространства столбцов матрицы А. Произведение в'*в в этом
случае дает единичную матрицу (eye (г)).
При любом варианте построения матрицы в второй сомножитель с ищется с
помощью левого матричного деления:
С=В\А
■К'-Чй^да "srv".^":vp 4-'-v •- ;"\i: '.■ ;-ч- ywfwe^vw»^"^^-»».;
I,Пример 12.18. Скелетное разложение . т" .-!- - :" ' -'-'•- "■'-.
» A = [4 2 2; 2 2 0; 2 0 2]
А =
4 2 2
2 2 0
2 0 2
» [R,jb] = rref(A)
R =
10 1
0 1-1
0 0 0
jb =
1 2
» В = A(:,jb)
В =
4 2
2 2
2 0
» С = В\А
С =
1.0000 0.0000 1.0000
-0.0000 1.0000 -1.00.00
498
Глава 12
» D = В*С
D =
4.0000 2.0000 2.0000
2.0000 2.0000 0.0000
2.0000 0.0000 2.0000
i
12.7.3. LU-разложение
При выполнении прямого хода преобразований строк матрицы а по методу
Гаусса матрица приводится к верхнему треугольному виду и (все числа под
диагональю равны нулю). Если при этом не делаются перестановки строк,
то матрица, умножение на которую слева равносильно сделанным
преобразованиям строк, оказывается нижней треугольной l (все числа над
диагональю равны нулю). В результате получаем так называемое LU-разложеиие
матрицы (пример 12.19):
А = L*U
Обозначения матриц L и и происходят от английских слов lower (нижний) и
upper (верхний).
Если при выполнении прямого хода преобразований строки матрицы не
делятся на ведущие элементы, то все числа на диагонали матрицы L равны 1.
Подставив это разложение в систему уравнений Ах=ь, получим LUx=b.
Обозначим их=у, тогда Ly=b. Таким образом, решение системы уравнений Ах=ь
с квадратной матрицей свелось к последовательному решению двух систем с
треугольными матрицами (сначала ъу=ь, потом их=у).
Требование "не переставлять строки матрицы" противоречит общепринятому
способу выбора ведущего элемента (берется максимальный по модулю
элемент в столбце), поэтому реально (т. е. с учетом перестановки строк)
матрица l получается не треугольной, но приводится к треугольной обратной
перестановкой строк.
Такой результат получается, если воспользоваться функцией lu в формате
[L,U]=lu(A).
I Пример 12.19, LU-разложение . ;,-,.,
» А = [1 л 1 3; 0-13 -1; 3 10 2; 1-251]
А =
14 13
0-1 3-1
3 10 2
1-251
» [L,U]=lu(A>
Линейная алгебра
499
L =
0
1
0
3
3333
0
0000
3333
0000
0
0
0
1.0000
-0.2727
0
-0.6364
1.0000
3.6667
0
0
0
1
1
5
0
5806
0
0000
0
0000
6364
0
0
1.0000
0
0
2.0000
2.3333
1.8182
-1.4194
Есть возможность получить "истинно треугольное разложение", а также
матрицу перестановки строк, которая к такому виду приводит (пример 12.20).
Для этого надо выполнить команду [l,u,p]=1u{A), которая кроме нижней
треугольной матрицы l и верхней треугольной матрицы и порождает
матрицу перестановки р. Между матрицами — участниками этой команды имеет
место соотношение p*a=l*u. Для сведения системы уравнений с квадратной
матрицей к двум системам с треугольными матрицами надо ах=ь умножить
слева на матрицу р — в результате получится рах=рь. После этого следует
заменить в левой части ра на ьи — система распадется на две системы с
треугольными матрицами Ly=Pb и их=у (предварительно надо найти
переставленные правые части рь).
>Пример 12.20, Треугольное разложение
Ж
» [L,U,F] =
L =
1.0000
0.3333
0.3333
0
и =
'3.0000
0
0
0
р =
0
1
0
0
=1и (А)
0
0
0
1
0
1.0000
-0.6364
-0.2727
1.0000
3.-6667
0
0
1
0
0
0
1
0
1
5
0
0
1
0
0
0
0000
5806
0
0000
6364
б
0
0
0
1.0000
2.0000
2.3333
1.8182
-1.4194
500
Глава 12
12.7.4. Разложение Холецкого
Это вариант LU-разложения для симметричной положительно
определенной матрицы. Такую матрицу можно представить в виде
A = R'*R
где r — верхняя, а к' — нижняя треугольные матрицы.
Разложение Холецкого (пример 12.21) получается с помощью команды
R=chol(А).
|Прймёр^1;2^ Л-4 -¾1-^ v -": Т •' ;.!л&*?! у*&- *' &W..' '■';"""-J
». А=[5 4 2; 4 4 2; 2 2 2]
А =
5 4 2
4 4 2
2 2 2
» R=chol(A)
R =
2.2361 1.7889 0.8944
0 0.8944 0.4472
0 0 1.0000
12.7.5. QR-разложение
Это разложение естественным образом возникает при ортогонализации
столбцов матрицы методом Грама—Шмидта. В результате получается
разложение данной матрицы
A = Q*R
где матрица q — ортогональная, а матрица r — верхняя треугольная. Это
разложение можно, в частности, применить при решении несовместных систем
уравнений. Большинство современных алгоритмов поиска собственных
значений основано на QR-разложении.
QR-разложение получается с помощью команды [Q,R]=qr(A) —
пример 12.22.
» A=[l 1 3; 2 1 2; 2 -5 8; -1 3 -7]
A =
113
2 12
Линейная алгебра
501
2 -5
-1 3
В
-7
» [Q,RJ=qr(A)
Q =
-0.3162
-6.6325
-0.6325
0.3162
R =
-3.1623
0
0
0
-0.3922
-0.5883
0.5883
-0.3922
3.1623
-5.0990
0
0
0.6325
-0.3162
-0.3162
-0.6325
-9.4868
5.0990
3.1623
0
0
-0
0
0
5883
3922
3922
5883
Если матрица прямоугольная, причем число ее строк га больше, чем число
столбцов п, лучше пользоваться экономной модификацией этой команды
[Q, R]=qr (А, 0). В этом случае вычисляются, только первые п столбцов
матрицы q и первые п строк матрицы r (пример 12.23).
! Пример'12.23. Экономная модиф
» [Q,R]=qr(A
Q =
-0.3162
-0.6325
-0.6325
0.3162
R =
-3.1623
0
0
,0)"
-0.3922 0.6325
-0.58ВЗ -0-.3162
0.5883 -0.3162
-0.3922 -0.6325
3.1623 -9.4868
-5.0990 5.0990
0 3.1623
-.,:- '■■.•. \ т.ч.-, :.- ■ . . ■ -*.
Для экономных представлений матриц q и r остается в силе равенство
A=Q*R.
Другие две модификации команды QR-разложения: [Q, R,P]=qr (А) и
[Q, p., Р] =qr (А, 0). Кроме матриц q и r первая из этих команд создает
матрицу перестановки р (пример 12.24), для которой
А*Р = Q*R
502
Глава 12
причем диагональные элементы матрицы r идут в порядке убывания
абсолютных величин.
I Пример 12.24. ОЯтразложение сматрицей перестановки - -■
» [Q,R,P] =
Q =
-0.2673
-0.1782
-0.7127
0.6236
R =
-11.2250
0
0
0
Р =
О
0
1
-ч?
0
1
о-
(А)
-0.7000
-0.5667
0.4333
0.0333
4.9889
-3.3333
0
0
1
0
0
0.3040
-0.7024
-0.3879
-0.5137
-2.6726
-1.0000
-1.3628
0
0.
-0.
0.
0.
.5883
.3922
.3922
.5883
Вторая модификация создает экономное представление матриц Q и R, а
вместо квадратной матрицы р — записанную в виде строки перестановку
номеров столбцов (пример 12.25).
Ц1рим$|й'£2& Экономное представление матриц о, и r .;
» [Q,R,P] =
Q =
-0.2673
-0.1782
-0.7127
0.6236
R =
-11.2250
0
0
P =
3
=qr
7:
(A,0)
-0.7000
-0.5667
0.4333
0.0333
4.9889
-3.3333
0
1
0.3040
-0.7024
-0.3.879
-0.5137
-2.6726
-1.0000
-1.362S
Линейная алгебра
503
12.7.6. Сингулярное разложение
Это разложение произвольной матрицы порядка mxn в произведение трех
сомножителей (пример 12.26). Сингулярное разложение создается командой
[U, S,V] = svd(A)
где и — ортогональная матрица порядка mxm, s — диагональная матрица
порядка шхп, v — ортогональная матрица порядка пхп, причем
А = U*S*V
В комплексном случае матрицы и и v — унитарные. Числа, идущие по
диагонали матрицы s, — вещественные неотрицательные (даже если матрица
А — комплексная), расположены в порядке не возрастания. Это так
называемые сингулярные числа матрицы д. Их квадраты являются собственными
числами матрицы а'*а.
I; Пример 12;26;
» format
А =
8/3
4/3
2/3
-2/3
» [U,S,V]
и =
-1/2
-1/2
-1/2
-1/2
S =
6
0
0
0
V =
-1/3
-2/3
-2/3
rat
Сикгулярн6е"разложение■"''"£*
11/6 4/3
19/6 2/3
5/6 10/3
13/6 8/3
=svd (А)
1/2 1/2
1/2 -1/2
-1/2 1/2
-1/2 -1/2
0 0
3 0
0 2
0 0
2/3 2/3
1/3 -2/3
-2/3 1/3
*'*$№*
1/2
-1/2
-1/2
1/2
С помощью сингулярного разложения строится псевдообратная матрица.
1.7 Зак. «99
504
Глава 12
Пусть a=u*s*v, где
s =
причем sl>s2>.,. Тогда псевдообратная матрица a+=v*s**u', где
s+ =
Для приведенных выше матриц:
s+ =
1/6 0 0 0
0 1/3 0 о
0 0 1/2 0
о s:
А =
11/36
-11/18
1/36
-1/36
5/18
-5/36
1/12
-1/6
1/4
-1/4
1/6
1/12
12.7.7. Полярное разложение
Любую квадратную матрицу можно представить в виде произведения
ортогональной на симметричную: а=р*н (в комплексном случае р — унитарная,
н — эрмитова). Если известно сингулярное разложение a=u*s*v, полярное
разложение можно построить, положив p=u*V, н=Р'*А.
Существует другая форма полярного разложения квадратной матрицы:
a=g*q, где g — симметричная (эрмитова), q — ортогональная (унитарная).
В этом случае q=u*v (т. е. совпадает с р), g=a*q' (пример 12.27).
и Пример-12:27, Подярно^ра^оагани?^ -¾ -Щ&- у-^Ч ' $Щ
» А=[-1 -7; 1 7J
»
0 =
,-1
1
[и,
-0.
0.
S,V] =
7071
7071
-7
7
=svd (А)
.0
0
7071
7071
Линейная алгебра
505
S =
10.0000 о
о о
V =
0.1414 -0.9899
0.9899 0.1414
» Q=U*V
Q =
-0.8000 -0.6000
-0.6000 0.8000
» G=A*Q'
G =
5.0000 -5.0000
-5.0000 5.0000
» P=Q;
» H=P'*A
H =
0.2000 1.4000
1.4000 9.8000
12.7.8. Разложение Шура
Любую квадратную матрицу можно представить в виде
A = u*T*U'
где и — ортогональная (унитарная), а т — верхняя треугольная матрица. По
диагонали матрицы т идут собственные числа матрицы а. Разложение Шура
получается с помощью команды [u,T]=schur(A) — пример 12.28.
» А=[3 -2 3; 1 2 1; 0 1 1]
А =
3-2 3
12 1
0 ~ 1 1
» [U,T]=schur(A)
U =
-0.5773 -0.7071
0.5774 -0.7071
0.5774 0.0000
0.4082
-0.4082
Q.8165
506
Глава 12
2.0000
0
О
-1.2247
2.0000
0.0000
-2.1213
-3.4641
2.0000
Если среди корней характеристического полинома вещественной матрицы а
имеются комплексные. Матрица т в разложении Шура получается блочно-
треугольной: каждому вещественному корню соответствует один
диагональный элемент, каждой паре комплексно-сопряженных корней соответствует
блок 2X2 — матрица, характеристическое уравнение которой имеет своими
корнями эти комплексно-сопряженные числа.
Для матрицы а, характеристический полином которой Х3-2Х-4 имеет один
вещественный корень Xt=2 и пару комплексно-сопряженных корней Х2,3=
=-l+i, разложение Шура дает результат, представленный в примере 12.29-
!:ПриШр 12.29, Разложение Шура
» А=[0 2 4; 1 0 0; 0 10]
А =
0 2 4
10 0
0 10
» tU,T]=schur(A)
U =
0.8729 0.2611 -0.412-2
0.4364 -0.0399 0.8988
0.2182 -0.9645 -0.1488
Т =
2.0000
0
0
-3.3320
-1.0000
1.8639
1.0659
-0.5365
-1.0000
Т™Ш*ГШШ
Причем характеристическим полиномом 2х2-блока
"-1.0000 -0.5365"
1.8639 - 1.0000
матрицы
является Х2+2Х+2, корни которого -l+i.
Чтобы в этой ситуации получить в разложении Шура "чисто треугольную"
матрицу т, надо обратиться к функции schur с дополнительным входным
аргументом 'complex' (пример 12.30).
Линейная алгебра
507
^0рймер:12.5р.Р!аэлрчвниеШу][)4р получением jp,eyrpfi^^M:rtatpMMbi " . ,'■*
» [U,T]=schur(A,'complex')
и =
0.5173 + 0.703H -0.3759 + 0.0765i 0.3010 + 0.0176i
0.2586 + 0.3515i 0.7881 + 0.0814i -0.3186 + 0.2834i
0.1293 + 0.1758i -0.0724 - 0.4689i -0.5668 - 0.6372i
T =
2.0000 - O.OOOOi -0.4928 - 1.7666i -2.8032 + 1.0083i
0 -1.0000 + l.OOOOi 1.0691 + 0.7867i
0 0 -1.0000 - l.OOOOi
Аналогичного (хотя не обязательно тождественного) результата можно
достичь, применив после [u,T]=schur (А) команду [u,T]=rsf2csf (и,т) —
пример 12.31.
ГП|рй^рЧ£31»;!Й^ 'v:"": -1
» [U,T]=schur(A);
» [U,T]=rsf2csf(U,T)
U =
0.8729 -0.3633 + 0.1234i -0.2301 + 0.1949i
0.4364 0.7921 - 0.0189i 0.0352 - 0.4249i
0.2182 -0.1311 - 0.4560i 0.8499 + 0.0703i
T =
2.0000 0.9393 - 1.5752i 2.9361 - 0.5039i
0 -1.0000 + l.OOOOi -1.3274
0 0 -1.0000 - l.OOOOi
12.7.9. Разложение Хессенберга
Любую квадратную матрицу можно представить в виде
А = U*H*U'
где и — ортогональная (унитарная), а н — "почти треугольная" матрица, у
которой все элементы, лежащие ниже первой субдиагонали, равны о.
Собственные числа матрицы н те же, что у матрицы а. Разложение Хессенберга
осуществляется с помощью функции hess — пример 12.32.
508
Глава 12
d . rt.l
» A=[l 2 0 3; -1-2 0-3; 0 0 2 0; 1203]
A =
1
-1
0
1
2
-2
0
2
» [P,H]=hess
P =
1.0000
0
0
0
H =
1.0000
1.4142
0
0
(A)
-0.
0.
0.
1.
-0.
0
0
2
0
0
7071
0
,7071
,7071
,0000
,0000
0
3
-3
0
3
0
-0.7071
0
-0.7071
-3.5355
-5.0000
0.0000
0
1
0
0
-1.0000
0
0
0
0
2.0000
Если матрица а симметричная (эрмитова), такой же будет и матрица н,
которая в этом случае оказывается трехдиагональной (пример 12.33).
l ПрйЙер:;1;?;33. РэдНоженщ^^ .-' ■
» A=[33 16 1 2; 16 -39 0 1; 1 0 -39 -16; 2 1 -16 33]
A =
33 16 1 2
16 -39 0 1
1 0 -39 -16
2 1 -16 33
» [P,H]=hess(A)
P =■
0.2173 -0.9682 0.1238 0
-0.9755 -0.2110 0.0619 0
-0.0338 -0.1342 -0.9904 0
0 0 0 1.0000
H =
-42.3983 -0.7625 0 0
X. '■
Линейная алгебра
509
-0.7625 35.2949 -9.0647 0
0 -9.0647 -37.8966 16.1555
О 0 16.1555 33.0000
12.7.10. Разложение Жордана
При наличии кратных корней характеристического полинома квадратную
матрицу А не всегда можно привести к диагональному виду, т. е.
представить как произведение
A = VDV""1
где d — диагональная матрица. Однако всегда можно построить несколько
более общее разложение
A = VJV-1
где j — так называемая жорданова (или каноническая) форма матрицы А,
она представляет собой блочно-диагональную матрицу с блоками
специального вида (жордановыми клетками):
~\0 1 0 .
0 Х0 1 .
0 0 х0 .
0 0 0.
0 0 0.
. 0 0 "
. 0 0
. 0 0
• К 1
. о Х0_
где Ко — корень характеристического уравнения. Каждому корню
соответствует одна или несколько таких клеток-блоков, их порядки могут быть
любыми, блок 1X1 представляет собой просто диагональный элемент Х0. Число
блоков, соответствующих конкретному корню Х0, равно геометрической
кратности этого корня, сумма порядков блоков, соответствующих Я0, равна
алгебраической кратности этого корня.
Чаще соотношение между матрицами A, v и J записывают несколько иначе:
J = V_1AV
и называют матрицу J жордановои формой матрицы а, столбцы матрицы v
образуют жорданов базис.
В MATLAB жорданово разложение находится с помощью команды
[V,J]=Jordan(А).
Пусть характеристический полином матрицы а имеет вещественный корень
7, его алгебраическая кратность равна 2, геометрическая кратность равна 1,
поэтому имеется одна жорданова клетка 2x2 (пример 12.34).
510
Глава 12
» A=[li 4; -4 3]
А =
11 4
-4 3
» [V,J]=jordan(A)
V =
4 1
-4 О
J -
7 1
О 7
Пусть характеристический полином матрицы а имеет комплексные корни
+i, алгебраическая кратность каждого из них равна 2, геометрическая
кратность каждого из них равна 1, поэтому для каждого корня имеется одна
жорданова клетка 2X2 (пример 12.35).
I.Яри<£е|р||&^^ в случае кЬмплексных.кррней|;|; ^^¾¾¾
» А=[0 -2 0 -1; 10 0 0; 0100; 0010]
А =
0 -2 0 -1
10 0 0
0 10 0
0 0 10
» [V, J]=jordan(A)
V =
0 + 0.2500i 0.5000 0 - 0.2500i 0.5000
0.2500 0 - 0.2500i 0.2500 0 + 0.2500i
0 - 0.2500i 0 0 + 0.2500i 0
-0.2500 0 - 0.2500i -0.2500 0 + 0.2500i
» Л
J =
0 + l.OOOOi 1.0000 0 0
0 0 + l.OOOOi О О
О 0 0 - l.OOOOi 1.0000
О 0 0 0 - l.OOOOi
Линейная алгебра
511
12.8. Системы линейных уравнений
12.8.1. Основные понятия
Существование и единственность решения
Систему линейных уравнений
&11х1 + . . . + а1пхп = Ъх;
amixi + . . . + апюхп = Ът,
обычно кратко записывают в виде
Ах = b
Ее основными характеристиками, от которых зависит существование и
единственность решения, являются:
□ п — число неизвестных (число столбцов матрицы коэффициентов а);
□ г — ранг матрицы коэффициентов: r=rank (А);
П r — ранг расширенной матрицы: R=rank( [А Ь]).
Имеют место следующие положения:
□ система совместна (имеет решение) тогда и только тогда, когда r=R, в
случае r<R система несовместна (не имеет решения);
П решение системы единственно тогда и только тогда, когда r=R=n, в случае
r=R<n система является неопределенной (имеет бесконечно много
решений);
П очевидно, что число уравнений (число строк матрицы) m>R.
Обратная и псевдообратная матрицы
Для квадратной невырожденной матрицы А (ее определитель det(A)#o)
обратной называется матрица а'1, для которой
АА"1 = А-1А = Е
где е — единичная матрица. В MATLAB матрица, обратная к а, создается
обращением к функции inv(A). Если матрица а вырожденная или
неквадратная, MATLAB при обращении к этой функции выдает соответствующее
сообщение.
Для заданной матрицы а псевдообратная а' имеет такие же размеры, как
транспонированная матрица а', ранги матриц А й а" одинаковы.
Псевдообратная матрица удовлетворяет уравнениям
А*(А*)*А = А
(А*) *А* (А+) = А*
512
Глава 12
причем матрицы а*(ан) и (а*)*а — симметричные (в комплексном случае
эрмитовы). Для квадратной невырожденной матрицы а псевдообратная
совпадает с обратной (ач=ам). Псевдообратная матрица строится на основе
сингулярного разложения. В MATLAB матрица, псевдообратная к а,
создается обращением к функции pinv(A). Наиболее полно о псевдообратной
матрице см. в [47].
12.8.2. Решение совместной системы
Рассмотрим типовые решения системы линейных уравнений.
О Крамеровская система.
Простейшим и наиболее важным с точки зрения приложений случаем
является так называемая квадратная крамеровская система Ах=ь, у
которой r=R=n=m, det(A)*o. Единственное решение такой системы задается
формулой
х = А_1Ь,
что в обозначениях MATLAB записывается как x=inv (а) *ь.
Здесь ь — матрица, содержащая необязательно только один столбец, т. е.
одной матричной операцией можно решить сразу несколько систем
линейных уравнений с одной и той же матрицей коэффициентов, но с
различными наборами правых частей.
Альтернативная запись решения крамеровской системы линейных
уравнений
х = А\Ь.
Здесь \ — левое матричное деление.
О Неопределенная система.
В случае r=R<n система является неопределенной (имеет бесконечно много
решений). Общее решение такой системы может быть записано в виде
х = Хс + у,
где хс, — частное решение неоднородной системы Ах=ь; у — общее
решение однородной системы Ах=о.
Некоторое частное решение неоднородной системы Ах=ь может быть
получено с помошью левого матричного деления:
Хо - А\Ь.
При выполнении операции а\ь MATLAB выдает предупреждение, в
переводе означающее "Матрица близка к сингулярной (вырожденной)
или плохо масштабирована. Результаты могут быть неточными"
(пример 12.36).
Линейная алгебра
513
» А=[2 7 3 1;1 3 5 -2;1 5 -9 8;5 18 4 5]
А =
»
ь =
»
2 7
1 3
1 5
5 18
b=[5;3;l;12]
5
3
1
12
xO=A\b
Warning: Matrix
хО
Results
-5.5000
1.2500
1.7500
2.0000
3
5
-9
4
is
1
-2
8
5
close
may
to
singular or
be inaccurate.
badly
RCOND = 4.
scaled.
,077954e-
-019
Наибольший интерес среди частных решений неоднородной системы
представляет так называемое нормальное решение, (решение с минимальной
евклидовой нормой). В курсах высшей алгебры для его построения
предлагается довольно громоздкий способ, включающий выделение базы строк в
расширенной матрице [Alb]. В MATLAB оно может быть легко
получено с помощью псевдообратной матрицы по формуле х0 = pinv(A) *ь
(пример 12.37).
[Пример 13Ь37,Поиск но^мМ ьного'частногоjj^^^R н^»норо^йи си^^ы ■'
» pA=pinv(A)
pft
0.0045
0.0147
0.0138
-0.0028
» x0=pA*b
0.0030
0.0071
0.0275
-0.0150
0.0001
0.0081
-0.0549
0.0393
0.0105
0.0371
0.0139
0.0066
514
Глава 12
хО -
0.1576
0.5478
0.2636
0.0594
Множество решений однородной системы Ах=о называют ядром матрицы а.
Оно представляет собой линейное пространство размерности к = п - г. Его
базис можно найти с помощью функции null (пример 12.38). Имеются два
способа обращения к ней:
П Y = null (А). Столбцы матрицы y представляют собой ортонормирован-
ный базис пространства решений;
□ Y = null (А, 'г'). Столбцы матрицы y представляют собой некоторый
рациональный базис пространства решений.
В обоих случаях a*y = о.
Вектор нормального решения хс, ортогонален к каждому столбцу (любой)
матрицы y: x0'*y = о.
f.npiiw^:12i38vi^^cK;6ia3Hca пространства'решений Щ^^гЩ^Ш^^' ~'У[°у$ЖЩ
» null (А)
ans =
-0.7798 -0.5721
-0.0057 0.4098
0.3633 -0.3732
0.5098 -0.6045
» null fА, 'г')
ans =
-26 17
7 -5
1 0
0 1
Общее решение однородной системы можно записать в виде
у = Y*t
где t — столбец параметров [ti,-t2;... ;ti:]. Для представления общего
решения взят наиболее простой вариант частного решения и базиса в
пространстве решений:
х = 1-5.50;!.25,-1.75,-2.00] + [-26;7; l;0]*ti+[17,--5;0;l] *t2
Линейная алгебра
515
12.8.3. Псевдорешение несовместной системы
Псевдорешением системы Ах=ь называется такой вектор х, который при
подстановке в систему дает вектор невязки а*х-ь, минимальный по евклидовой
норме (метод наименьших квадратов). Очевидно, что для совместной системы
псевдорешение является обычным решением (вектор невязки равен о).
Одним из способов нахождения псевдорешения является переход к так
называемой нормальной системе, которая получается из Ах=ь умножением
слева на транспонированную матрицу: а'Ах=а'Ь. Матрица этой системы
симметрична (в комплексном случае эрмитова).
Нормальная система всегда совместна и любое ее решение является
псевдорешением исходной системы (пример 12.39).
[!Примёр|2.39;5:Поиск псевдорешения как решения нормальной / "'',J
» А=[2 3;3 17;11 17;13 20]
А =
2 3
3 17
11 17
13 20
» Ь=[0;0;1;3]
b =
0
0
1
3
»■S=A'*A
S =
303 504
504 987
» р=А' *Ь
Р =
50
77
» x=S\p
х =
0.2340
-0.0415
516
Глава 12
Этот метод не рекомендуется применять для больших и плохо
обусловленных матриц (см. разд. 12.9.3), потому что при умножении А'А
обусловленность ухудшается.
Тот же результат в MATLAB можно получить гораздо проще и надежнее с
помощью левого матричного деления х=а\ь или псевдообратной матрицы
x=pinv{A)*b.
Для рассмотренной выше матрицы А псевдообратная матрица имеет вид:
» pA=pinv(A)
РА =
0.0103 -0.1245 0.0508 0.0611
-0.0022 0.0808 -0.0087 -0.0109
Соответствующее псевдорешение совпадает с приведенным выше:
» х=рА*Ь
х =
0.2340
-0.0415
Фактически этот метод основан на использовании сингулярного разложения
матрицы (см. разд. 12.7.6). Он обладает большей устойчивостью к
погрешностям округления и неточности задания коэффициентов и/или правых частей.
Другой метод псевдорешения несовместных систем основан на
использовании QR-разложения матрицы на ортогональный и верхний треугольный
сомножители (см. разд. 12.7.5)— пример 12.40. Этот метод также
обладает достаточной устойчивостью. Если известно разложение матрицы a=qr,
то нормальное уравнение А'Ах=а'ь превращается в R'Rx=R'Q,b, откуда
x=R"1Q'b, или, в обозначениях MATLAB, x=R\(Q'*b).
; Пример-12.40. Поиск псевдорёшения с йспользова
» [Q,R]=qr(A,0)
Q =
-0.1149 0.0268
-0.1723 -0.9850
-0.6319 0.1064
-0.7468 0.1332
R =
-17.4069 -28.9540
0 -12.1928
>> x=R\(Q'*b)
Линейная алгебра
517
х =
0.2340
-0.0415
Если псевдорешение не единственно, обычно ищут нормальное
псевдорешение (псевдорешение с минимальной евклидовой нормой) —
пример 12.41. Оно может быть получено либо путем левого матричного деления
х=А\ь, либо с помощью псевдообратной матрицы x=pinv (а) *ь (в первом
случае возможно сообщение о недостаточном ранге матрицы).
рПример .12.41;. Поиск нормедьного пеёвдорещени - ^ W,'., ,,^,.,,.. .. ■; А
» A=[l 1 1;1 1 1;1 1 1;1 1 2]
A =
111
111
111
112
» b=[l;2;3;4]
b =
1
2
3
4
» x=pinv(A) *b
x =
0.0000
"0
2.0000
12.8.4. Некоторые приложения
Приведем ряд полезных примеров реализации алгоритмов решения
линейных уравнений.
Линейные матричные уравнения
В теории линейных управляемых систем часто встречаются матричные
уравнения, в которых как неизвестное, так и коэффициенты являются
матрицами (чаще всего квадратными). Простейшими являются линейные
матричные уравнения Ляпунова а'*х+х*а+с=о и Сильвестра a*x*g+f*x*b=g.
Пример нелинейного матричного уравнения рассматривается в гл. 15.
518
Глава 12
Для решения уравнения Сильвестра (уравнение Ляпунова является его
частным случаем) предлагается следующий алгоритм [57]:
1. Построить матрицу (сумму кронекеровских произведений) w=a®g'+f®b'.
2. Построчно развернуть матрицу c=(Cij) в вектор-столбец c=(cu, ..., ст>
3. Решить систему линейных уравнений w*x=c. Вектор-столбец х=(хц, ...,
xln, xzi, ..., хпп) построчно свернуть в матрицу х=(хч).
Рассмотрим уравнение
2 1
1 1
X' X - X X
1 -1
1 1
Это частный случай уравнения Сильвестра при матрицах-коэффициентах
(пример 12.42).
|;Лримвр 12,4% Поиск р « ..^^^^^^Щл^г^Л
» А=[2
» В=[-1
» С=[1
» Е=еуе
1;1 2]
l; 1 -
l; 1 -
(2);
» Wl=kron(A,E
Г»71 —
W1 —
2
0
1
0
0
2
0
1
» W2=kron(E,B
W2 =
-1
1
0
0
1
-1
0
0
» W=W1+W2
W .=
1
1
1
0
1
1
0
1
-1
L]
')
')
;
l
0
2
0
0
0
-1
1
1
0
1
1
%
0
1
0
2
0
0
1
-1
%
0
1
1
1
% Построим произведения
% Найдем их сумму
Линейная алгебра
519
» c=reshape (С, 4,1) % Построчно развернем матрицу С в вектор-столбец с
с =
1
1
1
-1
Входная матрица функции reshape предварительно транспонируется, т. к. в
MATLAB преимущественным является развертывание матрицы в вектор (и
свертывание вектора в матрицу — см. ниже) по столбцам, как в Fortran.
В данном конкретном примере матрица с симметрична, так что эта
предосторожность сделана в расчете на общий случай.
Систему линейных уравнений w*x=c решим с помощью команды:
» x=W\c
X =
1.6667
-0.3333
-0.3333
-о.зззз
Полученный вектор-столбец х надо свернуть по строкам в квадратную
матрицу. С учетом особенностей операций свертывания-развертывания для
этого придется выполнить команду, также включающую транспонирование:
» X=reshape(х,2,2)'
X =
1.6667 -0.3333
-0.3333 -0.3333
Подставим найденную матрицу х в левую часть матричного уравнения:
» А*Х+Х*В
ans =
1.0000 1.0000
1.0000 -1.0000
Полученный результат совпал с матрицей правых частей с.
Система уравнений с формируемой матрицей
Рассмотрим пример решения системы линейных уравнений, матрица
которых формируется по определенным правилам. Такие системы естественным
образом возникают при численном решении дифференциальных уравнений.
520
Глава 12
Мы возьмем в качестве примера двумерное уравнение Пуассона
—Г + -Т = «*<У>-
ск1 dx2
Будем искать его приближенное решение в единичном квадрате.
Введем сетку с шагом h по обеим координатам, тогда для уравнения
Пуассона можно написать конечно-разностную аппроксимацию (ич — значение
неизвестной функции в узле, f Ll — значение функции f в том же узле, об
аппроксимации суммы вторых производных см. разд. 14.3):
Это уравнение перепишем в виде:
и,
ui,3-l - 2u15
Ъг
+ Ui.j+1 " 4"4ij
+ u i.:i+1
= h2 ■ fis
= fir
Введем одномерную нумерацию узлов квадратной решетки, считая, что в
каждой строчке и каждом столбце находится L узлов (очевидно (L-l)h=l).
Связь одномерных (к) и двумерных (i, j) индексов выражается простыми
формулами:
k = |i - 1) ■ L + j;
i = l + floor((к - 1)/L);
j = к - (i - l) • l.
Будем считать, что граничные условия, т. е. значения неизвестной функции
ul3 при i=l, i=L, i=i, j~L — нулевые, а правая часть f ,.,-=-1 при всех 2<i<L-l,
2<j<L-l.
Функция Poissonmatrix формирует матрицу А и правую часть b системы
линейных уравнений, а также ее решение — матрицу и (пример 12.43).
Пример 12.43: Функция Poisson^matrikfl? #^ %^^Щ?0%Ж^У#^'р_
function [A,b,Ul = Po.i.sson_matrix (.1,)
A=zeros {L, L) ; LL=L~2; b=zetros (LL, 1) ;
h=l/{L-l); hh=h"2;
for k=l:LL
[i,j]=deconv(k,L);
if i==l I i==L | j==l | j==L
A(k,k)=l.;
else
A{k,k)=-4; b(k)=-hh;
p=convol(i-l,j,L); A(k,p)=l;
Линейная алгебра
521
p=convol(i+1,j,L); A(k,p)=l;
p=convol(i,j-l,L) ; A(k,p)=l;
p=convol(i,j+1, L); A(k,p)=l;
end
end
u=A\b;
U=reshape (u, L, L) ;
Вспомогательные функции convoi и deconv осуществляют свертку и
развертку индексов (npHivrep 12.44).
р*?р'ъж:?-$Ш'''^''^^^^ '-"эдажетда1 ник: ■••
^Пример 12.44. Функций:donvbl M'deoonv' "!*£др; ' ^ "■ ".'l/gv _ ..„ ,? - i
function k=convol(i,j, L)
k = (i-l)*L+j;
function [i,j]=deconv(k,L)
i=l+fix((k-l)/L);.
j=k-(i-l)*L;
В примере 12.45 приведено решение уравнения Пуассона, полученное с
помощью функции Poisson_matrix при L=ll.
Г, Пример 12:45..Решение уравнения Пуассона методом сеток pSft^p. Щ<; ';%,.>■ А
function Poisson_tst
L=ll;
[A,b,U] = Poisson_matrix(L);
h=0.1; Xmin=0; Xraax=l;
XO=Xmin: h: Xmax ;
[X Y]=meshgrid(XO) ;
axes ('Xlim', [Xmin-h Xmax+h],'Ylim',[Xmin-h Xmax+h]);
axis equal; hold on;
V=0:0.01:0.07;
contour (X, Y, U,V) ;
xlabel('xl'); ylabel('x2');
title ('Решение уравнения Пуассона методом сеток',...
' FontName','' Courier')
522
Глава 12
На рис. 12.1 показаны линии уровня этой матрицы для значений v=
=0.01:0.01:0.07.
Рис. 12.1. Решение уравнения Пуассона
12.9. Проблема собственных значений
Вектор х*0 называется собственным вектором квадратной матрицы а, если
Ах=Хх для некоторого числа X, которое называется собственным числом,
соответствующим собственному вектору х. Любой вектор кх также является
собственным вектором для того же собственного числа л.
Задача отыскания собственных чисел и собственных векторов заданной
матрицы называется проблемой собственных значений.
12.9.1. Характеристический полином
Собственные числа матрицы являются корнями характеристического
уравнения det (A-?iE)=6. Его левая часть h(X)=det(A-XE) представляет собой
полином от X, степень которого п равна порядку матрицы а. Он называется
характеристическим полиномом матрицы а.
Линейная алгебра
523
Наличие и количество собственных чисел матрицы зависит от того, над
каким полем она рассматривается — в вещественном случае комплексные
корни характеристического полинома игнорируются.
В общем случае характеристический полином можно представить в виде
*„
ЫХ) = (А. - Хг)кЧХ - Хгр... {X - Хр)
Показатели степени ki, k2, ..., kp называются алгебраическими кратностями
собственных чисел Я.1, Хг, ..., Хр.
Для заданной матрицы А. ее характеристический полином, который равен
h(A.)=det (a-Xz), можно получить с помощью команды ь=ро1у(А),
порождающей строку из п+1 элемента (п — порядок матрицы а). Эта строка
содержит коэффициенты характеристического полинома в порядке убывания
степеней, причем старший коэффициент равен 1.
Корни любого (в частности — характеристического) полинома можно найти
с помощью функции roots: команда r=roots(h) порождает столбец из
п элементов, содержащий корни полинома, коэффициенты которого заданы
в строке h. Заметим, что функции roots и poly являются взаимно
обратными — обращение poiy(r) воспроизводит строку ь.
Иногда бывает интересно построить матрицу с предписанным
характеристическим полиномом h, который должен быть приведенным, т. е. иметь
старший коэффициент, равный 1. Это можно сделать с помощью функции
F=compan(h). Здесь F— так называемая матрица Фробениуса,
-присоединенная к полиному h, — одна из бесконечного (вообще говоря) множества
матриц, имеющих заданный характеристический полином.
На самом деле функция roots ищет корни любого полинома как
собственные числа присоединенной к нему матрицы Фробениуса. Для
характеристического полинома, заданного вектором коэффициентов h=[l 2 4 -5],
присоединенная матрица Фробениуса
'-2 -4 5
1 0 0.
О 10
Ее первая строка заполнена коэффициентами полинома, причем старший
коэффициент (равный i) опущен, а остальные записаны с
противоположным знаком; строки, начиная со 2-й, взяты из единичной матрицы.
Собственные векторы
Имеют место следующие положения, касающиеся собственных векторов:
П собственные векторы, соответствующие различным собственным числам,
линейно независимы;
524
Глава 12'
П количество линейно независимых собственных векторов,
соответствующих одному собственному числу (это количество называется
геометрической кратностью собственного числа), не превосходит алгебраической
кратности этого собственного числа.
Особый интерес представляет базис, состоящий из собственных векторов
(собственный базис матрицы). Приведем два достаточных условия
существования собственного базиса:
□ все собственные числа различны (иначе говоря, алгебраические
кратности всех собственных чисел равны 1);
О матрица а является симметричной (в комплексном случае — эрмитовой).
В этом случае всё корни характеристического уравнения —
вещественные, и даже при наличии кратных корней существует ортогональный
собственный базис.
12.9.2. Вычисление собственных значений
Основная функция MATLAB, решающая проблему собственных
значений, — eig (пример 12.46). Существует несколько способов обращения к
ней, из которых отметим два основных:
О L=eig(A) — столбец l заполняется собственными числами матрицы а;
□ [v,b]=eig(A) — диагональная матрица d содержит собственные числа;
столбцы матрицы v суть соответствующие им собственные векторы
(нормированные). Имеет место соотношение a*v = v*d.
; Пример 12.46. Вычисление собственных значений |Ч '."% й^-.-й*'/-^ -¾ £• ^;'Щ
;...~..:::..л...:>л ;■...:.■.«-„:.; ,;..:.:..; .;..: ........ :;.....:й.:;:.^.<^Х:.^...«...;;Л.Ля.гй:..?й*:;л;1
» а=[4 -1 -2; 2 1 -2; 1 -1 1]
А =
4 -1 -2
2 1-2
1-11
» L=eig(A)
L =
1.0000
3.0000
2.0000
» |V,D]=eig(A)
V =
-0.5774 -0.7071
-0.5774 -0.7071
-0.5774 -0.0000
0.7071
-0.0000
0.7071
Линейная алгебра
525
D =
1.0000 0" о
О 3.0000. о
О 0- 2.0000
Случай кратных корней
Недостатком функции eig является то, что при наличии кратных корней
характеристического уравнения соответствующие столбцы матрицы v могут
оказаться линейно зависимыми (пример 12.47).
[:При^ер:12.47.;.Кратнь1е;корнИ; __._„.. .. ^¾^^1¾^¾^^..^^¾¾¾
лй.;.,„ж,л;.л«л;лй-а.::;в;»к;йК:4;
» А=[3 -10 0; 0 3 0 0; 10 3 1; 0 10 3]
ft =
3
0
1
0
» [V,D].
V =
-1
3
0
1
=eig(A)
0
0
1.0000
D =
3
0
0
0
0
0
3
0
0
0
-1
0
0
3
0
0000
0
0000
0
0
0
3
0
0
0
1
3
0
0
-1.0000
0.0000
0
0
0
3
0.7071
0.0000
0
-0.7071
Невооруженным глазом видно, что первые три столбца матрицы v линейно
зависимы. Чтобы получить только линейно независимые собственные
векторы, можно применить функцию [R, jb]=rref (V), которая вырабатывает r —
так называемую ступенчатую форму матрицы v и jb — строку, содержащую
номера столбцов матрицы v, образующих базу. Матрицу в, столбцы которой
являются линейно независимыми собственными векторами, можно
получить, выделив базовые столбцы из матрицы v (пример 12.48).
526
Глава 12
[Пример :12.48.
» [R,jb
R =
1
0
0
0
jb =
1
» B=V(:
В =
=rre
-1
0
0
0
a
jb)
0
0
i.OGOO
0
Получение j
f (V)
0
0
-0
-1 0
0 1
0 0
0 0
7071
0000
0
7071
ЩШШШ
Признаком линейной зависимости столбцов матрицы v является
неравенство rank(v)<n. Этот критерий является не очень надежным. Чтобы более
уверенно определить ранг, его надо вычислить с помощью команды
rank(V,toi) с различными значениями порога toi. Так, в примере 12.47 на
основании выдачи результатов утверждалось, что первые три столбца
матрицы v линейно зависимы (т. е. ее ранг равен 2). Однако rank(v, 1е-17)=з.
Функция rref(V) имеет модификацию rref{v,toi). Можно также найти
сингулярные числа матрицы si>s2>. ..не учетом предполагаемой точности
исходных данных и/или приближенных вычислений выбрать, какое из
сингулярных чисел не является пренебрежимо малым — его номер и будет
эффективным рангом матрицы.
Случай комплексных корней
Если среди корней вещественной матрицы имеются комплексные, по
команде [v,D]=eig{A) будут созданы комплексные матрицы v и d (пример 12.49).
Пример 12.49. Комплексные корни -. * г - , -¾^^¾¾¾¾¾
» А=[0 2 4; 1 0 0; Q. 1 0]
А =
0 2 4
100
0 10
Линейная алгебра
527
» [V,D]=eig(A)
V =
-0.872? 0.7559 0.7559
-0.4364 -0.3780 - 0.3780i -0.3780 + 0.3780i
-0.2182 -0.0000 + 0.3780i -0.0000 - 0.3780i
D =
2.0000 0 0
о -i.oooo + l.qoooi о
0 0 -1.0000 - l.OOOOi
Можно получить вещественные матрицы v и d, но d будет блочно-
диагональной — каждой паре комплексно-сопряженных корней
соответствует диагональный 2.х2-блок. Для этого после [V, D]-eig(A) надо применить
команду [v,D]=cdf2rdf(v,D):
» [V,D]=cdf2rdf(V,D)
V
D
=
-0.8729
-0.4364
-0.2182
=
2.0000
0
0
0.7559
-6..3780
-0.0000
0
-1.0000
-1.0000
.0
-0.3780
0.3780
0
1.0000
-1.0000
При этом комплексные корни -i±i характеристического полинома матрицы
А являются и корнями характеристического полинома 2х2-блока — матрицы
а Г
12.9.3. Обусловленность матрицы
Метод Гаусса является точным настолько, насколько точно выполняются
входящие в него арифметические операции. Поскольку в MATLAB
используется представление чисел с плавающей запятой, арифметические
операции в большинстве случаев выполняются неточно, так что и решение
систем линейных уравнений на самом деле является приближенным.
Оценить погрешность этого приближения, основываясь на пофешностях
выполнения отдельных арифметических операций, весьма трудно хотя бы
из-за большого их числа (для нахождения обратной матрицы число
операций оценивается 0{п3), где п — порядок матрицы).
528
Глава 12
Проще выяснить, как влияют на решение системы линейных уравнений
небольшие изменения в правых частях и в коэффициентах матрицы. Если
решение меняется также незначительно, можно с некоторой уверенностью
считать, что и погрешности округления не очень повлияют на
окончательное решение.
Основную роль в этом рассмотрении играет понятие нормы вектора |х||
(обычно имеется в виду евклидова норма ||х|| = д|£ у.\, которая в MATLAB
вычисляется с помощью функции попп(х)). Умножение вектора х на
матрицу а можег изменить его норму. Область возможных изменений нормы
определяется двумя числами:
М = max -т—jf- , m = mm .. .. .
**° И **o и
Их отношение cond(A)=M/m называется числом обусловленности матрицы а, в
MATLAB его можно найти с помощью функции cond(A). Имеются и другие
способы описания числа обусловленности:
П отношение наибольшего сингулярного числа матрицы к наименьшему;
П произведение сингулярных норм данной матрицы и обратной к ней
N ' ||А_1| (эта ноРма в MATLAB вычисляется с помощью функции
norm (А)).
Рассмотрим систему уравнений Ах=ь и другую систему, полученную
изменением правой части и с изменившимся решением: А(х+Дх)=ь+ДЬ.
Поскольку А(Дх)=ДЬ, то из определений ниш следуют оценки
И * м|х| и |Atfl > m|H|.
llAbll
Введя относительные изменения нормы правой части 5b = ~^- и нормы
И
IMI
решения 5х= Vr. получим при m*0 5x<cond(A)* 5b, т.е. относительные
И
изменения в правой части ь могут повлечь относительные изменения в
решении х, в худшем случае большие в cond(A) раз. То же самое справедливо
в отношении изменений в коэффициентах матрицы А.
Из определения числа обусловленности видно, что cond{A)>i. Нижняя
оценка достигается, например, для ортогональных (унитарных) матриц. Чем
больше величина cond(A), тем хуже обусловлена матрица; значения порядка
десятков или даже сотен считаются неплохими.
Рассмотрим систему:
X! + 0.99х2 =1.99
0.99Х! + 0.98х2 =1.97
Линейная алгебра
529
Решение этой системы с помощью формулы х=а\ь дает x,=i.oooo,
x2=l.oooo (легко видеть, что этот результат является точным).
Немного изменим свободные члены:
х, + 0.99х2 = 1.9899G3
0.99xj + 0.98х2 = 1.970106
Решение этой системы с помощью той же формулы дает xi=3.oooo, хг=
=-1.0203 (приближенно). Рассмотрим вектор приращений свободных членов:
ДЬ = (-1.97е-004, 1.06е-004).
Его евклидову норму можно вычислить с помощью соответствующей
функции MATLAB: ||дь|| = погт(ДЬ) = i.4368e-004. Относительное приращение
I IN
нормы свободных членов 5b = \-^- = 5.1312е-005 (здесь norm(Ь) = 2.8002).
IMI
Можно констатировать, что относительное приращение вектора свободных
членов весьма мало.
Найдем вектор приращений решения Дх = {2.0000, -2.0203) и его норму
||Дх|| = погт(Дх) - 2.8428. Относительное приращение вектора решения Sx =
= Vii = 2.0102 Не мало (здесь norm (х) = 1.4142).
м
Отношение 5x/5b = з.9175е+004 — почти 40 тысяч!
Такой плохой результат объясняется не малостью определителя матрица А,
хотя он и в самом деле невелик (det(A)=-l.ooooe-oo4), но его легко сделать
равным -1, умножив на юо оба уравнения, входящих в систему, причем ни
решение, ни отношение йх/5ь при этом не изменятся.
Гораздо важнее плохая обусловленность матрицы а. Ее число
обусловленности можно найти: cond(A) = з.920бе+004, что лишь ненамного превышает
найденное выше значение 5х/5ь = 3.9175е+004.
12.10. Линейная алгебра
и новые типы данных
Описанные выше функции линейной алгебры ориентированы на работу с
вещественными данными удвоенной точности (double). Однако пакет
MATLAB 7 расширил возможность выполнения операций с
целочисленными данными (int8, uints, intie, uintie, int32, uint32) и вещественными
данными с одинарной точностью (single). Эти расширения отчасти
коснулись и некоторых функций линейной алгебры.
530
Глава 12
Так, например, функции формирования матриц eye, ones и zeros теперь
позволяют создавать массивы любого типа, однако для этого они используют
дополнительный параметр, определяющий класс возвращаемого результата
(пример 12.50).
! Пример 12,50. Формирование матриц с; данными норых:ти1!Ов.£^¾¾5 ^-^¾^ \
» ai8=eye {4, ' int8.') ;
» aui8=ones(3,6,"uint8');
» ail6=zeros(5,'intl6'j;
» af=eye{4,5,'single');
» whos
Name Size Bytes Class
af 4x5 80 single array
ail6 5x5 50 intl6 array
ai8 4x4 16 int8 array
aui8 3x6 18 uint8 array
В операторах присваивания теперь тоже можно указывать тип
возвращаемого значения:
» x=int8( [1 .2 3 4] );
» whos
Name Size Bytes- Class
x 1x4 4 int8 array
Естественно, что формируемые и присваиваемые значения должны
укладываться в диапазон чисел, допустимых для данного класса. В противном
случае соответствующие значения будут заменены либо верхним, либо нижним
числовым пределом соответствующего класса:
» fcj=uint8([100 200 300])
Ь =
100 200 255
Над массивами одинакового типа можно выполнять большинство
арифметических операций. Результат их выполнения принадлежит этому же классу
(пример 12.51).
1 Пример 12.51. Выполнение арифметических операций над массивами ;f ' ■'•? Щ
I одинакового типа
я ."*..." .(...„и..,'......',.'. ., .' -. ....* .».:
» x=intl6([l 2;3 4]) ;
» y=intl6([5 б;7 8]);
Линейная алгебра
531
» zl=x+y;
» z2=x.*y;
» z3=x";
» whos
Name
X
У
zl
z2
кЗ
Size
2x2
2x2
2x2
2x2
2x2
Byt
es
8
8
8
8
8
Class
lntl6 array
intl'6 array
intl6 array
intl6 array
intl6 array
При выполнении операций такого рода результат, выходящий за
допустимые пределы, заменяется соответствующим максимальным или
минимальным значением:
» x=uint8([10 100]);
» y=uint8([20 20]) ;
» х.*у
ans =
200 255
» х-у
ans =
0 80
Если одним из операндов является скаляр, то им должен быть либо скаляр
того же типа, либо значение типа double. Другие смешения типов
запрещены (пример 12.52).
;; Пример 12.52. Операция над матрицей и скаляром '•>■-«-^ -.
» x*int8(3)
??? Error using => mtimes
Integers can only be combined with integers of the same class, or scalar
doubles.
» x*uint8(3)
ans =
30 255
Целочисленные матрицы нельзя умножать или возводить в степень, хотя
аналогичные операции над матрицами типа single допустимы
(пример 12.53).
532
Глава 12
Ш§Ш5ё^Ш^Б^^ЗШ^^Ш^^^ВШ
т
» x=uint8([l 2;3 4]);
» х*х
??? Error using ==> mtiraes
At least one operand must be scalar.
» хл2
??? Error using ==> mpower
Both operands must be scalar.
» z=single([l 2;3 4]);
» z*z
ans =
7
15
» гл2
ans =
7
15
10
22
10
22
Довольно необычно модифицирована функция sum, вычисляющая сумму
элементов своего аргумента. Если аргументом является целочисленная
матрица любого типа, то функция sum возвращает значение типа double. Однако
если добавить еще один параметр-строку 'native', то тип возвращаемого
значения совпадает с типом матрицы. Если аргументом функции sum
является массив типа single, то она всегда возвращает результат типа single, и
добавка параметра 'native' в этом случае ничего не меняет (пример 12.54).
a
» x=int8([l 2 3 4]);
» y=sum(x)
У =
10
» 2=SUITl{X,
z =
lb"
» whos
Name
X
У
z
'native')
Size
1x4
lxl
1x1
Bytes
4
8
1
Class
int8 array
double array
int8 array
» xl=single.( [1 2 3 4]]
Линейная алгебра
533
»■ zl=surn(xl)
zl =
10
» whos zl
Name Size Bytes Class
zl 1x1 4 single array
>> z2=sum(xl, 'native')
z2 =
10
» whos z2
Name Size Bytes Class
z2 lxl -4 single array
Нормальную поддержку для матриц типа single обеспечивают функции
trace (вычисление следа матрицы) и inv (обращение матрицы). При этом
они сами определяют тип своего аргумента и возвращают результат того же
типа (пример 12.55).
[Пример 12 55^Йспо1пьзование функций trace и inv
т
»■ x=single
» y=inv(x)
У =
-2.000.0
1.5000
» z=trace(
z =
5
» whos
Name
X
У
z
([1 2;3 4])
1.0000
-0.5000
x)
^..
2x2
lxl
t
Bytes
16
16
4
Class
single array
single array
single array
Таким образом, введение целочисленных данных очень мало повлияло на
решение задач линейной алгебры. Скорее, оно рассчитано на использование
целочисленных массивов большого размера в задачах машинной графики.
Возможность работы с вещественными данными одинарной точности может
быть использована в конкретных задачах. Однако следует помнить, что
диапазон данных типа single на порядок уступает данным типа double, а в
задачах с плохо обусловленными матрицами удвоенная точность гарантирует
получение более качественных результатов.
Глава 13
Интерполяция
и аппроксимация
Предположим, что на числовой оси заданы точки х,<х2<... <хг (обычно их
называют узлами) и значения yi, уг, ..., уг., где каждое уа — вещественное
число, соответствующее узлу х;. Задача одномерной аппроксимации состоит
в том, чтобы построить просто вычисляемую функцию, в некотором смысле
приближающую эти данные. В зависимости от класса аппроксимирующих
функций и требований к способу аппроксимации возникают различные
постановки задач.
В дальнейшем изложении роль аппроксимирующих функций будут играть
полиномы и сплайны.
13.1. Интерполяционный полином
Требования к аппроксимации заключаются в том, чтобы искомый полином
в узлах Х1<жг< ... <хп принимал соответствующие значения yi, у2, ..., у„ и
имел наименьшую возможную степень.
Существует единственный полином степени не выше п-1, удовлетворяющий
этим условиям. Он называется интерполяционным полиномом для заданных xt
и yL.
Известны явные формулы, выражающие этот полином (интерполяционные
полиномы Лагранжа и Ньютона), однако они скорее удобны для "ручной
работы" на бумаге (или для самостоятельного программирования), а в
MATLAB мы воспользуемся для построения интерполяционного полинома
методом неопределенных коэффициентов.
Пусть этот полином степени п-1 имеет вид:
p-ix"'1 + p?xn"' + ... ■¥ pn.ix + рп.
IK Зпк. 890
536
Глава 13
Его коэффициенты должны удовлетворять системе линейных уравнений
Р1ХГХ + Р2Х""2 + •- + РП-3Х1 + Рп = Ух',
р^Г1 + p2x£"2 + ... + р,,.^ + pn = y2.
PlC1 + Рг^""2 +-.. + P„.1X„ + Pn = Уп.
Матрица этой системы представляет собой так называемую матрицу Вандер-
монда и может быть создана функцией vander(X), где х — столбец с
компонентами хь хг, ..., х„. Этот столбец можно создать командой
x=[xi,x2, ... ,хп] ' или х=[х1;х2,-... ;хп]. Аналогичным образом создается
и столбец правых частей системы уравнений Y=[yl,y2, ...,уп]'.
Единственное решение крамеровской системы получается путем левого
матричного деления (пример 13.1).
|}]ри мер ■ 13L1 решение1 1фяМёровс^й'сис1гёмы' ь^^^ф^я^^^^^^^^^^$-
» Х= [0.05;0.10;0.17;0.25;0.30;0.36]
X =
0.0500
0.1000
0.1700
0.2500
0.3000
0.3-600
» Y=t0.050;0.1003,-0..1717; 0.2553;0.30S3; 0.3764]
Y =
0.0500
0.1003
0.1717
0.2553
0.3093
0.3764
» P=vander(X)\Y
Р =
-4.5785
5.0346
-1.6381
0.3434
0.9746
0.0006
Интерполяция и аппроксимация
537
Коэффициенты аппроксимирующего полинома р{х) степени n, наилучшим
способом приближающего таблицу функции Y(x) в смысле наименьшего
квадратичного отклонения в узлах, проще найти, обратившись к функции
polyfit(x, y,n) (пример 13.2).
• ""■■■■■ ';!V""-""7/'"''"""*V«p;^""^^^
I Пример 1312.,Поиск коэффициентов апп
» P=polyfit(X,Y,5)
-4.5785 5.0346 -1.6381 0.3434 0.9746 0.0006
Из результатов видно, что оба подхода для полинома 5-й степени дали
одинаковый результат. Это вполне естественно — интерполяционный полином,
найденный с помощью функции vander, проходит через узловые точки, и
его отклонение в табличных точках равно 0. Однако к функции polyfit
можно обратиться и для построения аппроксимирующего полинома
меньшей степени, который, в общем случае, не может проходить через все
узловые точки.
Для проверки качества найденного полинома можно построить график, на
котором находится полиномиальная кривая и нанесены табличные точки
аппроксимируемой функции. Для вычисления значений полинома можно
использовать функцию y=polyval (р,х), где вектор х покрывает интервал
табличных значений [Х(1),х(п)] и даже слегка выходит за его пределы.
Тем самым интерполяционный полином будет использован также и для
экстраполяции данных. В примере 13.3 приведена программа, реализующая
описанные действия.
i Пример 13-3. Функция построения графика^. *'J.,_-...*■* ^¾¾^-¾^¾-^"Г^^^3*"^
function prog!3_l
х=[0.05 0.10 0.17 0.25 0.30 0.36];
у=[0.0500, 0.1003, 0.1717, 0.2553, О.ЗОВЗ, 0.3764];
xlabel1'х'); уlabel С у'); hold on
plot(x, у, 'ко')
t =-0.05:.01:0.45;
c5=polyf it (x, у, 5) ;
y5=polyval(c5,t);
plot(t,y5,'k-')
ti tie ('Полиномиальная интерполяция','FontName•,'Courier')
hl=legend(' данные", 'Интерполяция', 0-) ;
set{hL,'FontName','Courier')
538
Глава 13
Рисунок 13.1, отражающий результат работы программы, показывает, что в
данном примере качество интерполяции, а также экстраполяции в
выбранном диапазоне, весьма хорошее.
0.Б
0.5
0.4
0.3
0.2
0.1
0
ч
Полиномиальная интерполяция
О данные
Интерполяция
У*
#/
*S
- у
1 0 0.1 .0.2 0.3 0.4 0.5 0.6 ..
X
Рис. 13.1. Пример удачной интерполяции
Однако при других исходных данных качество может оказаться значительно
хуже. Виной этому обычно является желание воспользоваться полиномом
высокой степени (пример 13.4, рис. 13.2).
Пример 13.4ГФункцйя:п6строёнЙя'графи|а при других исходных, данных^"-'Щ \
function progl3_2
х=[-2,-1,0,1,2];
y=[0,0,l,0,0J;
title ('Полиномиальная аппроксимация','FontName', 'Courier')
xiabel('x'); ylabel('y'); hold on
plot(x, y, 'ko')
t =-3:.1:3,-
c2=polyfit(x,y,2);
y2=polyval(c2,t);
plot(t,y2,-k:')
c4=polyfit(x,y,4);
Интерполяций и аппроксимация 539
y4=polyval(с4,t);
plot(t,y4,'к-')
hl=legend('данные',"полином 4-й степени','полином 2-й степени',0);
set (hi., ' FontName', 'Courier')
Если интерполяционный полином 4-й степени проходит через табличные
узлы аппроксимируемой функции, то полином 2-й степени через эти узлы
уже не проходит. Но среди всех полиномов 2-й степени он дает наименьшее
среднеквадратичное отклонение в узлах табличной функции. Вполне
возможно, что именно он дает более приемлемые результаты в промежуточных
точках.
Полиномиальная аппроксимация
12
10
8
6
4
2
0
■-3 -2-1 0 1 2 3
I '.
Рис. 13.2. Интерполяция полиномами разной степени
13.2. Сплайны
Дальнейшего повышения качества аппроксимации табличных данных
можно достичь с помощью сплайнов — полиномов невысокой (обычно 3-й)
степени, приближающих данные не глобально, т. е. на всем заданном
интервале, а по отдельности на каждом частичном интервале между соседними
узлами. При этом в узлах должна быть обеспечена стыковка — совпадение
значений (график сплайна проходит через узлы), совпадение производных
(отсутствие изломов), иногда совпадение вторых производных. Могут также
задаваться краевые условия на концах интервала, например — обращение в
ноль второй производной-
О данные
- - полином 4-й степени
— полином 2-й степени
540
Глава 13
Для такого рода кусочно-полиномиальной аппроксимации табличных
функций у(х) предназначена функция interpi:
уу = interpi(х, у, xx,mechod) ;
Здесь:
□ х — абсциссы аппроксимируемой функции;
О у — ординаты аппроксимируемой функции;
□ хх — абсциссы контрольных точек, в которых вычисляются значения
аппроксимирующих полиномов, возвращаемые в качестве вектора уу;
П method — способ аппроксимации, задаваемый в виде строки символов
(на самом деле достаточно указать только первый символ).
Функция interpi предоставляет на выбор следующие методы:
О nearest' — аппроксимация кусочными полиномами нулевой степени
(ступеньками): для любого промежуточного значения хх находится
ближайшее табличное xj и в качестве уу берется соответствующее табличное
значение yij
П 'linear' — аппроксимация кусочными полиномами 1-й степени
(ломаными);
□ 'spline' — аппроксимация кусочными полиномами 3-й степени
(сплайнами); '
□ 'pchip' или 'cubic' — аппроксимация кусочными полиномами Эрмита
3-й степени.
Если параметр method опушен, по умолчанию используется 'linear'.
При аппроксимации по методу 'spline' в узловых точках непрерывны
первая и вторая производные, а во внутренних узлах, соседних с концевыми,
непрерывна также и третья производная.
При использовании метода 'pchip' вторая производная может иметь
разрывы. Сплайн, построенный по методу 'pchip', является монотонным на
любом участке, на котором монотонны данные, этот сплайн воспроизводит
локальные экстремумы данных.
Для гладких данных предпочтителен метод 'spline', для негладких лучше
Применять 'pchip'.
Если нас интересуют коэффициенты сплайнов, полученные в результате
кусочно-полиномиальной аппроксимации, то вместо функции interpi следует
обращаться к функциям spline или pchip. Они возвращают структуры, в полях
которых хранятся найденные коэффициенты (подробнее об этом см. в разд. 13.2.1).
Эти структуры могут задаваться в качестве аргументов при обращениях к
функции ppvai для вычисления значений аппроксимирующих функций
(пример 13.5).
Интерполяций и аппроксимация
541
\ Пример 13.5
»
»
»
ps
»
рр
х=[-2 -1
у=[0 0 1
; ПОИСК: КОЭфф
0 12];
0 0J;
ps=spline(х,у)
=
form:
breaks:
coefs:
pieces:
order:
dim:
'pp'
[-2 -10 12]
[4x4 double]
u
4
1
pp=pchip(x,y)
=
form:
breaks:
coefs:
pieces:
order:
'PP'
[-2 -10 12]
[4x4 double]
4
4
dim: 1
Построение негладких данных и сплайнов по методам 'spline' и 'pchip'
приведено в примере 13.6.
.Ч1.„..,..™....,.„....„.уч...,„.. ..„..„,.,.... ,uu..M,^»up»v^Vi..^.„?...v»rv»..^..u::».j-«u-.
Пример 13.6; Построение/негладких данных и с^тнов''',-1фл-^Щ^р^' &£'
function progl3_3
х=[-2 -1 О 1 2];
у=[0 0 10 0];
t 3.5:.05:3.5;
ps=spline(x,y);
pp=pchip(х, у) ;
plot(х,у,'ко',t,ppval(ps,t),'к:',t,ppval(pp,t),'к-Ч
hl=legend('данные','spline','pchip',0);
set(hL,'FontName','Courier')
title ('Два сплайна','FontName','Courier')
xlabel{'x'>;уlabel ('у')
Результат работы программы progl3_3.m отображен на рис. 13.3.
542
Глава 13
12
10
В
В
>->
Л
2
0
-2
-i
, ^
1
1
',
1
1
1
1
\
\
i
i
*
1
-
1 -3
\
\
-2
Два' сплайна
-1 0 1
X
_., # -.
•
Q данные
— spline
pchip
t
г
/
1
i
i
t
j
/
i
i
1
/
/
/
/
2 3 *
i
Рис. 13.3. Аппроксимация кубическими полиномами
Результаты, представленные на рис. 13.4, построены приведенной выше
программой для других табличных данных:
х = -3:3;
у = [-1 -1-10 111] ;
- 1.5
1
0.5
>, 0
-0.5
-1
-1.5
О данные
— spline
pchip
i
i i i
I -3 -2
Два сплайна
*
1
-1 0 1
X
,
2
,
Э
и
\
Рис. 13.4. Аппроксимация кубическими полиномами для других данных
Интерполяция и аппроксимация
543
13.2.1. Стандартные сплайны MATLAB
Названия методов 'spline' и 'pchip' являются именами функций, к которым
обращается interpi (другие два метода nearest" и 'linear' обрабатываются
непосредственно в interpi). Обращение к этим функциям имеет два разных
формата:
yy=spline(x,y,xx) или pp=spline(х,у)
y=pchip{x,y,xx) или pp=pchip(x,y)
В первом варианте смысл входных и выходных параметров тот же, что при
обращении к interpi. Во втором варианте обе функции возвращают так
называемую кусочно-полиномиальную форму (ppform, pieceweise polinomial
form) — специальный внутренний формат MATLAB для представления
сплайнов. В возвращаемой структуре, содержащей несколько полей, из
которых основными являются два — pp.breaks и pp.coefs.
Их можно получить так, как было продемонстрировано выше, или
выполнив команду [bp,cp]=ppbrk(pp).
Значением поля breaks является вектор х. Поле coefs представляет собой
матрицу, каждая строка которой заполнена коэффициентами полиномов
3-й степени, аппроксимирующих данные на отдельных участках:
П первая строка — на участке от breaks (1) до breaks (2);
□ вторая строка — на участке ОТ breaks (2) ДО breaks (3)
и т. д.
Например, табличная функция
х=-3:3;
у=[-1 -1-10 11 ib-
была обработана процедурой spline, и коэффициенты полученных
полиномов приведены в табл. 13.1.
Таблица 13.1
Интервал по х Коэффициенты Полином
1/4*х3-3/4*х2+1/2*х-1
1/4*х3-1/4*х-1
-1/4*х3+3/4*х2+1/2*х-1
-1/4*х3+5/4*х
1/4*х3-3/4*х2+1/2*х+1
1/4*х3-1/4*х+1
[-3, -2]
[-2. -1]
М.0]
[0,1]
[1.2]
[2,3]
1/4
1/4
-1/4
-1/4
1/4
1/4
-3/4
0
3/4
0
-3/4
0
1/2
-1/4
1/2
5/4
1/2
-1/4
-1
-1
1
0
1
1
544
Глава 13
Заметим, что старшие коэффициенты полиномов 1-го и 2-го участков
совпадают (также совпадают и старшие коэффициенты полиномов последнего
и предпоследнего участков). Это является следствием того, что третья
производная непрерывна в узлах, соседних с крайними.
Вычисление значения сплайна в любой точке хх происходит следующим
образом. Сначала определяется i — номер интервала между соседними
значениями breaks, которому принадлежит эта точка. Например, для хх=-2.5 будет
i=i (для точки хх=-з.5, лежащей слева от области определения сплайна,
также берется i=l). Затем берется t-xx-breaks (i) и вычисляется значение
соответствующего полинома (в данном случае i/4*t3-3/4*t2+l/2*t-i).
Значение сплайна в любой точке (точках) можно найти с помощью команды
yy=ppvai(pp,xx). Кроме ppvai в MATLAB имеются другие функции для
работы с кусочно-полиномиальной формой сплайнов:
□ fnval (f,xx) — то же, что ppvai, но применимо также и для других форм
представления функций, кроме ppform;
П fnder (f, k) — построение производной k-ro порядка (по умолчанию k=i);
□ fnint (f,iv) — построение первообразной функции (lv — значение на
левом конце, по умолчанию lv=o).
Функции fnder и fnint выдают результат в той же форме, в которой задана
функция f.
С помощью функции fnint можно, в частности, найти площадь под
графиком сплайна.
Рассмотрим график (пример 13.7), построенный функцией spline в
предыдущем примере.
!:Пример 13.7. Вычисление площади , > Т.." '"' щ& "h:.. ~$*
» х=[-2 -10 1 2];
>> у=[0 0. 1 О СП;
» spl=spline(х,у); % ppform для сплайна
» intspl=fnint(spl); % ppform для интеграла от сплайна
» area=ppval(intspl,x(length(х)))-ppvai(intspl,x(l))
area =
0.6667
13.2.2. Сглаженные сплайны
Обращение к функции, строящей сглаженный сплайн, имеет вид:
output = qsaps(x,yrp,xx,w);
Интерполяций и аппроксимация
545
Здесь:
□ х и у — аппроксимируемые данные;
□ р — параметр сглаживания (о<р<1);
□ хх — контрольные точки ("длинный вектор");
Пи — вектор весов (по умолчанию заполнен единицами).
Сглаженный сплайн f минимизирует выражение
pY w^ - f (х±))2 + а - P)[7f ' )2dx.
При р=о получается линейная функция, обеспечивающая минимум суммы
квадратов отклонений в узловых точках, при p=i — обычный кубический
сплайн.
Тип выходной переменной output зависит от способа обращений к
функции csaps. Если обращение содержит параметр хх, то output представляет
собой вектор значений сплайна в контрольных точках (т. е. фактически это
уу). Если же обращение имеет сокращенный вид output=csaps (х,у,р) или
хх=[ ], то output — кусочно-полиномиальная форма.
В примере 13.8 приведена программа построения сглаженных сплайнов с
различными параметрами сглаживания. Результаты ее работы отражены на
рис. 13.5.
Г Пример 13.8. Построение сглаженных сплайнов ■■ -■■*„■»' :СЙ^^кЩЙ
В*::'. .::: :.-.-.-.....::.......-. :.' :... ^s^^^m.\^jiM*Vaifak~^-Jin?.72^s3&A-is!££
function progl3_4
х = -4:4;
у = Ю .15 1.12 2.36 2.36 1.46 .49 .06 0];
xlabel('х'); уlabel('у'); hold on
plot(x,у,"ko1);
xx = [x(l):0.25:x{length(x))];
w = ones(length(x),1);
csl = csaps (x,y, 1, [],w);
plot (xx, ppval (csl, xx), • k-1) ;
cs07 = csaps (x, y, 0.7, [] ,w) ;
plot(xx,ppval(cs07,xx),'k—');
cs05 = csaps (x,y, 0.5, [] ,w) ;
plot(xx,ppval(cs05,xx),'k-.');
csO = csaps (x, y, 0, [] ,w);
plot (xx,ppval (cs.O, xx), ' k: ');
546
Глава 13
title (' Сглаженный сплайн', '-FontName', ' Courier')
hl=legend('данные','p = 1.0','p = 0.7',...
'p = 0.5', 'p = CO);
set(hL,'FontName','Courier')
Рис. 13.5. Сглаженные сплайны
13.2.3. Сплайны
с заданными условиями на концах
Сокращенная форма обращения к функции, строяшей сплайн с заданными
условиями на концах:
pp=csape(x,y)
В этом случае условия на концах в явном виде не задаются, по умолчанию
используются условия Лаграижа: первые производные на концах такие же,
как у сплайна, построенного функцией spline по четырем узлам,
ближайшим к соответствующему концу.
Полная форма обращения к функции
pp=csape{х,у,conds,valconds);
Здесь:
П х и у — аппроксимируемые данные;
П conds — тип условий на концах, задаваемый в виде строки символов (на
самом деле достаточно задать только первый символ);
Интерполяция и аппроксимация
547
П vaiconds — значения условий, задаются в виде вектора [а Ь], где а —
значение на левом конце, ь — значение на правом конце.
Параметр conds может принимать одно из следующих значений:
П 'complete' — задаются первые производные на концах (по умолчанию —
условия Лапэанжа);
О 'second' — задаются вторые производные на концах (по умолчанию —
[О 0]);
□ 'periodic' — совпадают первая и вторая производные на концах,
значение параметра vaiconds игнорируется;
П 'not-a-knot.' — в первом и последнем внутренних узлах непрерывна
третья производная (т. е. получается тот же сплайн, который строит
функция spline), vaiconds игнорируются;
□ Variational' — вторые производные на концах равны нулю, значение
параметра vaiconds игнорируется.
Некоторые из перечисленных возможностей демонстрирует программа
progl3_5.m (пример 13.9), результаты работы которой отражены на рис. 13.6.
Пример 13%Сплайн с граничнЬ|ми условиями
„.s^isi-a
function progl3_5
x=[-2,-l,0,l,2];
y=[0,0,1,0,0] ;
plot(x,y,'ko') ;
xx = [x(l):0.05:x(length(x))];
xlabel('x'); ylabel('y'); hold on
conp=csape(x, y, 'complete',[0 0]) ;
plot(xx,ppval(comp,xx),'k-');
sec=csape{x,y,'second',[0 0]);
plot(xx,ppval(sec,xx),'k:');
title ('Два вида граничных условий', *FontName','Courier')
hl=legend('данные','complete [0 0]','second [0 0]',0);
set(hL,'FontName','Courier')
Условия на концах можно задать в виде двухкомпонентного вектора
[conds (1) conds (2) ], для его составляющих возможны только два значения:
□ в vaiconds задается значение первой производной;
□ в vaiconds задается значение второй производной.
548 Глава 13
. - - Два вида граничных условий ..v;' .
1.2
1
О.В
0.6
0.4
0.2
0<
~"'"-2 ^/-1.5 • -1 ■ -0.5 0 0.5 1 ...1.5 2
:" X -_
Рис. 13.6. Аппроксимация с условиями на концах
Конкретные значения производных задаются в vaiconds(l) (на левом
конце) и в vaiconds(2) (на правом конце). Благодаря этому возможно задание
комбинированных условий. Например, команда
conib=csape (х, у,[1 2],[0 0])
создает кусочно-полиномиальную форму сплайна, у которого на левом
конце равна нулю первая производная, а на правом— вторая (вместо [0 0] в
vaiconds можно указать любые другие значения). Примером тому является
программа progl3_6.m (пример 13.10), результаты работы которой отражены
на рис. 13.7.
кПриищ ДЗЛО^Ллайн'с _ ^¾¾¾¾
function ргод13_.б
х=[-2,-1,0,1,2];
у=[0,0,1,0,0];
plot (х, у, 'ко');
xlabel (' х'),- ylabel Су'); hold on;
хх = [х(1):0.05:x(length(x))];
comb=csape(x,y,[1 2],[0 0]);
plot(xx,ppval(comb,xx), 'k-') ;
Интерполяция и аппроксимация 549
title{'Комбинация граничных условий: [1 2],[О 0J','FontName','Courier')
hL=legend{'данные','сплайн',0);
set(hL,'FontName','Courier')
■- ■'■ •' 1.2
'" ij
0.6
"'■ 0.6
0.4
0.2
: .0
"°'2-2 .-i:5 -1 -D.5 0 0:5 '1 ■■ 1.5 2 A '
к '
Рис. 13.7. Аппроксимация с комбинированными условиями на концах
13.3. Параметрическая аппроксимация
Предположим, что на координатной плоскости заданы точки:
PL(Xl,yi), Р2<Х2,Уа), •••' Ре(Хр.,Уп)
и требуется аппроксимировать их некоторой линией, проходящей через них
(в указанном порядке!) или недалеко от них.
Введем параметр t, значения которого tt<t2<..<tn (например, можно взять
ti=i), и построим две функции: x=<p(t) и y=\j/(t), которые представляют
собой параметрическое описание кривой, аппроксимирующей данные точки.
Для этого нам надо тем или иным способом аппроксимировать два набора
данных: (u, х0 и (ti, у<), а затем совместить результаты, исключив параметр t.
В приведенной ниже профамме progl3_7.m (пример 13.11) для заданных
табличных функций x=x(t), у=у (t) строятся четыре приближения:
□ кусочно-линейное (ломаная с вершинами в данных точках);
П сплайн (кривая проходит через узловые точки);
Комбинация граничных условий;. [1 2],[0.0]
550
Глава 13
0 интерполяционный полином 9-ii степени (кривая, проходящая через все
10 точек);
П аппроксимирующий полином 4-й степени, найденный по методу
наименьших квадратов.
Результаты отражены на рис 13.8.
1 Пример 13.11. Параметрическая интерполяция - -^;: .. ;'■
function progl3_7
t = [1 2 3 4 5 б 7 8 9 10];
х = [2 3 3 2 1 -1 -1 -2 -2 0'];
у - Ц2344 3 2 1 0 2] ;
subplot (2, 2,1}; plot ([-2.5. 3.5], [-0.5 4.5],'w')
subplot(2,2,2); p]ot([-2.5 3.5],[-0.5 4.5],'w'}
subplot(2,2,3); plot([-2.5 3.5],[-0.5 4.5],'w')
subplot(2,2,4); plot([-2.5 3.5],[-0.5 4.5],'w')
% Промежуточные точки для интерполяции
tt = [til) :.0.01 :t (length (t)) ];
%. Линейная параметрическая интерполяция
xline = interpi(t,x,tt,'linear');
yline = interpi(t,y,tt,'linear');
subplot(2,2,1); hold on; plot(xline,yline,x,у,'o')
% Полиномиальная параметрическая интерполяция
cx9 = polyfit (t,x, 9.) ;
x9 = polyval(cx9,tt);
cy9 = polyfit (t,y, 9) ;
y9 = polyval(су9,tt);
subplot(2,2,2); hold on; plot(x9,y9,x,y,'o')
sx = spline(t,x);
sy = spline(t,y);
xx = ppval(sx,tt);
yy = ppval (sy, tt) ;
subplot (2-,2,3) ; hold on; plot (хх,'уу,Х/Уг 'о')
cx4 = polyfit(t,x,4};
x4 = polyval (cx.4,tt) ;
Интерполяция и аппроксимация
551
су4 = polyfit(t,y, 4);
у4 = polyval(су4,tt);
subplot(2,2,4); hold on; plot(x4,y4,x,y,'о')
Рис. 13.8. Параметрическая интерполяция
По рис. 13.8 видим, что полиномы 9-й степени дают очень плохой
результат, а полиномы 4-й степени — вполне приличный. Еще лучший результат
дает использование сплайнов: полученная кривая проходит через все данные
точки и обладает достаточной гладкостью.
Иногда Moiyr возникнуть проблемы при аппроксимации замкнутой кривой.
В большинстве случаев достаточно повторить в конце данных координаты
первой точки. Однако этого может оказаться недостаточно, чтобы
аппроксимирующая кривая оказалась гладкой и на последнем интервале. Для обеспечения
гладкости на замыкающем узле можно построить периодический сплайн с
ПОМОЩЬЮ фуИКЦИИ csape, ИСПОЛЬЗУЯ КОНцеВое уСЛОВИе conds='periodic".
Этот прием демонстрирует профамма progl3_8.m (пример 13.12), результаты
работы которой отражены на рис. 13.9.
1
552
Глава 13
\ Пример 13,12. Использование условия conds='periodic' при аппроксимации j
function progl3_8
t = [1 2 3 4 5 б 7 8 9 10 11];
х = [2 3. 3 2 1 -1 -1 -2 -2 0 2] ;
у = [1 2 3 4 4 3 2 1 0 2 1];
subplot(2, 2,1); plot ([-2.5 3.5], [-0.5 4.5], V)
subplot(2,2,2); plot([-2.5 3.5],[^0.5 4,5],'w')
subplot (2, 2,3}; plot ([-2.5 3.5], [-0.5 4.5], TW)
subplot(2,2,4); plot([-2.5 3.5], [-0.5 4.5],'w')
% Промежуточные точки для интерполяции
tt = [1:0.01:11];
£ Линейная параметрическая интерполяция
xline = interpl(t,x,tt,'linear');
yline = interpl(t,у,tt,'linear');
subplot(2,2,1); hold on; plot(xline,yline,x,y,'o')
S Полиномиальная параметрическая интерполяция
cx-9 = polyfit{t,x, 9) ;
x9 = polyval (cx9, tt) ;
cy9 = polyfit.(t,y,9) ;
y9 = polyval(cy9,tt) ;
subplot(2,2,2); hold on; plot (x9,y9,x, у,'o')
'i Параметрическая интерполяция обычным сплайном
зу. = spline (с, х) ,-
sy = spline(t,у);
xx = ppval(sx,tt);
yy = ppval(sy,tt);
subplot(2,2,3); hold on; plot (xx, yy, x,y,'o')
% Параметрическая интерполяция периодическим сплайном
px=csape(t,x,'periodic');
py=csape(t,y,'periodic');
xxp = ppval(px,tt);
yyp = ppval(py,tt);
subplot(2,2,4); hold on; plot(xxp,yyp,x,у,'о')
Кусочно-линейная аппроксимация дает замкнутую ломаную
(многоугольник), аппроксимация с помощью обычных сплайнов — кривую, у которой
имеется излом в начальной (она же является и последней) точке. Аппрок-
Интерполяция и аппроксимация
553
симация с помощью периодического сплайна — гладкую кривую (на самом
деле непрерывна также и вторая производная).
Рис. 13.9. Обеспечение гладкости замкнутой кривой
13.4. Двумерная аппроксимация
13.4.1. Аппроксимация на прямоугольной сетке
В этом случае должны быть заданы:
□ вектор абсцисс х (l :m);
□ вектор ординат у (i -. п);
□ двумерный массив аппликат Z(l:m,i:n), в котором каждой паре
(х (i), у (j)) соответствует значение z (i, j) -
Для дальнейшего использования в функциях MATLAB векторы х и у
необходимо преобразовать в двумерные массивы х и y следующей структуры: строки
массива х являются копиями вектора х, столбцы массива у являются копиями
вектора у. Иными словами, они представляют координатную сетку на
плоскости ху. Массивы х и y могут быть созданы командой [x,Y]=meshgrid(x,y).
554
Глава 13
Если векторы х и у имеют одинаковые компоненты, можно написать короче:
[X,Y]=meshgrid(x).
Для двумерной аппроксимации данных предназначена функция interp2:
zz=interp2(X,Y,Z,xx,уу,method);
Здесь:
П х, y и z — аппроксимируемые данные;
П хх, уу — массивы, задающие набор контрольных точек, в которых
вычисляются значения аппроксимирующей функции zz;
□ method — способ аппроксимации, задаваемый в виде строки символов.
Он может принимать одно из следующих значений:
• 'nearest' — аппроксимация кусочными полиномами 0-й степени
(площадками): для любой пары значений (хх, уу) находится
ближайшая табличная пара (х, y) и в качестве zz берется соответствующее
табличное значение z;
• 'linear' или 'bilinear' — аппроксимация кусочными билинейными
функциями вида z=(a+bx) (c-i-dy)=poo+piox+poiy+puxy
(аппроксимирующая поверхность представляет собой фрагмент гиперболического
параболоида — седла);
• 'cubic' или 'bicubic' — аппроксимация кусочными бикубическими
ФУНКЦИЯМИ вида г=роо-^1ох+ро1У+рпху+Р2охг+Ро2У2+Р21Хгу+р1гху24-р3с,х3+
+рвзу^';
• 'spline' — аппроксимация сплайнами.
Если параметр method опущен, по умолчанию используется 'linear'. В этом
случае вместо функции interp2 можно обратиться к функции linear, что
демонстрируется в программе progl3_9.m (пример 13.13). Результат ее
работы отражен на рис. 13.10.
; Пример 13.13. Билинейная аппроксимация - *■• ^..<-- v, ...»...»•
it. ......'.... i ....:;. u„i ............**...I
function progl3_9-
x=[l 2 3];
y=[l 2 3];
Z=[l 2 1,-2 1 2;1 2 1];
[X, Y] = meshgrid(x);
[xx, yy] = meshgrid(1:0.1:3);
zz=linear(X,Y,Z,xx,yy);
surf (xx, yy, zz) ;
xlabel{'x'); ylabel('y'); zlabel('z')
■title (' Двумерная аппроксимация', ' EontName', ' Courier') ;
Интерполяция и аппроксимация
555
Рис. 13.10. Билинейная аппроксимация
Аппроксимация по методу "linear" выполняется следующим образом.
Мелкая сетка взята с шагом o.i, над каждым ее квадратиком
аппроксимирующая поверхность представляет собой фрагмент седла, цвет фрагмента
определяется текущей палитрой coiormap и пропорционален высоте z.
13.4.2. Аппроксимация
с помощью триангуляции
В этом случае должны быть заданы три вектора одинаковой длины: вектор
абсцисс х, вектор ординат у и вектор аппликат z. Таким образом, каждому
узлу на координатной плоскости (хь у±) сопоставляется свое значение zi.
Эти данные должны быть аппроксимированы некоторой достаточно простой
функцией z=f (х, у).
Самая простая аппроксимация — кусочно-линейная. Ее вычисление
включает несколько этапов. Вначале на множестве узлов (xi, yt) строится
триангуляция (разбиение плоскости на треугольники). Для заданного множества
узлов (если их больше трех) существует много разных триангуляции.
Наилучшая из них в некотором смысле, так называемая триангуляция Делоне, —
характеризуется тем, что минимальный по всем треугольникам угол
достигает максимального значения.
Триангуляцию Делоне по заданным векторам х и у можно построить с
помощью функции deiaunay(x,y>, возвращающей массив, каждая строка ко-
556
Глава 13
торого содержит тройку номеров узлов, образующих очередной треугольник.
Соответствующий пример демонстрирует программа progl3_10.m
(пример 13.14).
: Пример 13.14. Триангуляция Делоне -"=-- - -3^ ." у^" ' \'':%^^f'rj\ ■|^';'*/,Ч'|
function ргод13_10
х=[-2,-1,0,0,2, 3,3,4, 6, 6];
у=[ 2,-2,0,4,2,-2,5,3,-1, 1] ;
axes('XLim',[-2.5 6.5], ' YLira1, [-2.5 5.5])
tri = deiaunay(x,у);
s=siZG{tri) ;
hold on; grid off;
xlabel (' \itx') ; ylabel (' \i.ty') ;
title ('Триангуляция Делоне','FontName','Courier');
for t=l:s(l)
i=Lri(t,l);
j=tri(t,2>;
k=-tri<t,3);
xt=[x(i),x(j),x{k) ,x(i) ] ;
yt=[y(i),y(j),y(k),y(i)];
plot(xt,yt, 'k');
end
Функция deiaunay построила массив tri из 11 троек, содержащих номера
вершин соответствующих треугольников (рис. 13.11):
3 6 25 6 32 1 36 10 95 10 6
5 В 101 4 34 5 35 7 84 7 5
7 10 S
Простейший пример поверхности с треугольными фанями (рис. 13.12)
строит программа prog!3 1 l.m (пример 13.15).
I Пример 13.15. Построение поверхности с треугольными гранями
function progl3_ll
х=[-2,-1,0,0,2, 3,3,4, .6, 6];
у=[ 2,-2,0,4,2,-2,5,3,-1, 1];
z=[ 1, 2,3,4,5, 6,7,8, 9,10];
Интерполяция и аппроксимация
557
tri = delaur.ay (х,у) ;
crimesh(tri,x,у,zeros(size(х)));
hold on;
trimesh(tri,x,y, z) ;
xlabel('x'); ylabel('y'); zlabel('z')
colormap copper
title ('Поверхность с треугольными гранями','FontName','Courier');
В этой программе использована функция trimesh, которая строит
изображение поверхности с треугольными гранями по массивам х, у, z и
описанию триангуляции Делоне (массив tri).
Так как каждой вершине (хь yi) соответствует аппликата zi, то по исходной
табличной функции мы фактически построили поверхность, составленную
из треугольных граней. Теперь в любой точке (х, у), находящейся внутри
огибающего многоугольника, можно восстановить перпендикуляр до
пересечения с соответствующей гранью и найти значение нашей функции
z (х, у) в промежуточных точках.
Все эти вычисления выполняются с помощью функции griddata, которая
для заданных табличных значений (векторы х, у, z) и массивов
промежуточных точек (хх, уу) вычисляет значения соответствующих аппликат zz:
zz = griddata (х, у, z,хх, уу) ;
Рис. 13.11. Триангуляция Делоне
558
Глава 13
ДОгу —
8-.--
6-.--
4-.--
Рис. 13.12. Поверхность с треугольными гранями
Более полная форма обращения к этой функции позволяет использовать не
только треугольные грани, построенные над триангуляцией Делоне, но и
произвести некоторое сглаживание ребристой поверхности за счет указания
того или иного метода аппроксимации:
zz = griddata(х,у,z,xx,yy,method);
Параметр method может принимать одно из следующих значений:
П 'nearest' — аппроксимация горизонтальными площадками (для заданной
точки (хх, уу) находится ближайший узел (xlt ух) и в качестве zz берется
соответствующее табличное значение Zi);
П 'linear' — аппроксимация треугольными гранями (этот метод
применяется по умолчанию);
□ 'cubic' — сглаживание участков поверхности кубическими сплайнами;
□ V4' — специальное сглаживание с использованием градиента.
Поверхность с треугольными гранями
±-~Гк^ 7
i ■ * ■
! / \ /.
• „ ,' .,/^
7 ^~-^\ s-^~
/ £>s
/ -\ ; * -,. ^ •
-5 -2
Глава 14
Численное дифференцирование
и интегрирование
14.1. Конечные разности
Пусть на оси абсцисс отмечены узлы хь х2, ..., х„ и функция y=f (х) задана
таблицей значений в этих узлах:
X]
У1
Х2
У2
Хг,
Уп
Составим таблицы разностей:
Axi=X2~Xl
Ay;=y2-yi
ДХ2=Хз-Х2
Ду2=у3-У2
ДхГ1-1=хп-хп-1
ЛУп-]=Уп-уп-]
Если узлы равноотстоящие, т. е. Дх1=Дхг=...=ЛхГ1-1=ь, представляют интерес
также таблицы разностей 2-го, 3-го и т. д. порядков для значений
функции у:
Д2у1=Ду2-Ду]
AJyi=Azy2-Azyi
Д2у2=Дуз~Ау2
Д3у2=Д2уз-Д2у2
А2у ,,-2=Д уп-1 - Д Уп- 2
Д3У1>-з=Д2у1>-2-А2Ул-з
(заметим, что каждая следующая строка таблицы разностей на 1 короче
предыдущей).
В MATLAB имеется функция diff, которая по заданному вектору х строит
вектор разностей указанного порядка:
dx =diff(х) % вычисление разностей 1-го порядка
dnx=diff(х,п) % вычисление разностей n-го порядка
560
Глава 14
В примере 14.1 приводится фрагмент программы, результаты работы
которой для большей наглядности перенесены в табл. 14.1.
|Лри^ёЩ|4,'"1.Вычйрлеййё конечны* разностей'■""* v'^1£'S^^!f4^^4^_;}?v©5^
» х = 1:0.1:2;
» dx = dif f (x) ;
» у = log(x);
» dy = diff(y);
» d2y = dtff (y, 2) ;
Таблица 14.1
X
1.0
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2.0
i dx
| 0.1
| 0.1
| 0.1
j 0.1
| 0.1
! 0.1
! 0.1
1 0.1
! 0.1
1 0.1
j У
! о
1 0.0953
| 0.1823
I 0.262«
j 0.3365
j 0..4055
| 0.4700
| 0.5306
| 0.5878
! 0.6419
] 0.6931
| dy
1 0.0953
j 0.0870
| 0.0B00
| 0.0741
| 0.0690
| 0.0645
1 0.0606
| 0.0572
j 0.0541
| 0.0513
j d2y
| -0.0083
| -0.0070
| -0.0059
| -0.0051
I -0.0045
I -0.0039
| -0.0035
j -0.0031
j -0.0028
14.2. Численное дифференцирование
функций одной переменной
Производная — понятие локальное. Поэтому, если функция задана
таблицей значений, для нахождения производной функции в каком-то из узлов
обычно используют интерполяционные многочлены невысоких степеней,
которые хорошо приближают функцию в окрестности этого узла. Обычно
для построения этих многочленов используют формулы, основанные на
таблицах разностей. Наиболее известны интерполяционные формулы Ньютона.
Пусть узлы, в которых заданы значения функции, равноотстоящие, т. е.
Axi_=Ax2=~.=Axn-i=h. Тогда можно построить интерполяционные формулы,
Численное дифференцирование и интегрирование 561
позволяющие приближенно находить значения функции вблизи
произвольного узла Xi (в этих формулах q=(x-xi) /h).
Формула Ньютона 1-го порядка (линейное приближение):
П интерполяция вперед
y=f (x)=yi+q*Ay1
П интерполяция назад
y=f (x)Syi+q*Ayi-:
Формула Ньютона 2-го порядка (квадратичное приближение):
П интерполяция вперед
y=f (х) =y±+q*Ayi+ [q* (q-1) *ДгуО /2 !
П интерполяция назад
y=f (х) =yi+q*Ay;-i+ <q* (q+1) *A?yi-2) /2 !
Формула Стерлинга 1-го порядка (линейное приближение):
y=f (x)=yi+q* (Ду^+Ду;) /2
Формула Стирлинга 2-го порядка (квадратичное приближение):
y=f (x)=yi+q*{Ay;-1+Ayl>/2 + q3*A2yi-i/2!
Самую простую и достаточно точную формулу численного
дифференцирования можно получить, если продифференцировать полусумму формул
Ньютона 1-го порядка для интерполяции вперед и назад:
f' (х1) = (Ду1-1+Ду!) /2Ь-{у1,1-у1_1) /2h. (14.1)
Тот же результат дает дифференцирование формулы Стирлинга 1-го
порядка. Заметим, что формула (14.1) неприменима для концевых узлов, т. е. при
i=l и i=n, там приходится использовать по отдельности формулы Ньютона
для интерполяции вперед (i=i) и назад (i=n), причем целесообразно брать
формулы не 1-го порядка, которые в этом случае дают недостаточную
точность, а формулы 2-го порядка:
f ■ (х1) = (ДУ1-Д;!у1/2) /h=(-3yi+4y?-y3) /2h;
f • (хп) = (Дуп-1-Д?Уп-г/2) /h=(3ya-4yn-1+yn-2) /2h.
Приведем пример 14.2.
I Пример 14.2. Точность поиска производной численными методами
Для функции:
х=1:0.1:2=[1.0000 1.1000 . . . 1.9000 2.0000]
у=1од(х)=[0.0953 р.0870 . . . 0..0541 0.0513]
562
Глава 14
найдена производная двумя способами: численно по приведенным выше
формулам и точно — по формуле log(x) '=l/x (табл. 14.2).
Таблица 14.2
X
1.0
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2.0
1 Численно
| 0.9946
I 0.9116:
| 0.8353
; 0.7708
1 0.7155
! 0.6677
1 0.6258
| 0.588.9
1 0.5561
| 0.5268
! 0.5121
! Точно
| 1.0000
; 0.9091
1 о.еззз
| 0.7692
1 0.7143
! 0.6667
I 0.6250
| 0.5882
; 0.5556
I 0.5263
| 0.5000
1 Разность
I 0.0054
; 0.0025
| 0.0019
! 0.0015
| 0.0012
j 0.0010
| 0.0008
| 0.Q007
; 0.0006
j 0.0005
| 0.0121
Максимальная разность между численным и точным результатом на
интервале [l, 2] равна 0.0121. Если исключить концевые узлы, то максимальная
погрешность получится всего 0.0025, т. е. почти в 5 раз меньше.
Самую простую и достаточно точную численную формулу для второй
производной дает дифференцирование интерполяционной формулы Стирлинга
2-го порядка
f ■' <х,,) = (Ду^-Ду!-.) /h2= (yni-2yi.+yi-i) /h2.
14.3. Численное дифференцирование
функций двух переменных
Градиентом функции ?(х,у) называется вектор д<х, у), также зависящий от
х и у. Его координаты являются частными производными z по х и у:
gx=dz/dx, g.y=dz/3y. Для численного дифференцирования отношения
дифференциалов во внутренних узлах области заменяются разностными
отношениями:
gx = (z(x+hx,y)-z(x-hx,y))/2hx;
gy = (z(x,y+hy)-z(x,y-hy))/2hy.
На краях области используются другие формулы.
Численное дифференцирование и интегрирование
563
В MATLAB имеется функция, вычисляющая цифровой аналог градиента:
[gx, ду] = gradient(z,hx,hy);
Здесь:
П z — матрица значений дифференцируемой функции, в которой каждый
столбец соответствует некоторому значению х, а каждая строка —
некоторому значению у;
П hx, hy — шаги дифференцирования по к и по у (можно задать один
параметр h, который будет использоваться для обоих аргументов, или не
задавать его вовсе — тогда по умолчанию берется n=i);
П gx, gy — матрицы, содержащие компоненты градиента, как функции х и
у. Размеры этих матриц такие же, как у матрицы z.
Для графического отображения градиента можно использовать функцию
quiver (от англ. quiver— "колчан"), которая рисует векторы градиента в виде
стрелок. Простейшая форма обращения к ней — quiver (gx,gy>.
Оператор Лапласа для функции z (х, у) — сумма вторых производных:
Дг = З^/Эх2 + d'z/dy2.
Для его вычисления в MATLAB применяется функция dei2:
L = del2(z,hx,hy);
Здесь:
П z — матрица значений дифференцируемой функции, в которой каждый
столбец соответствует некоторому значению х, а каждая строка —
некоторому значению у;
П hx, hy — шаги дифференцирования по х и по у (можно задать один
параметр h, который будет использоваться для обоих аргументов, или не
задавать его вовсе — тогда по умолчанию берется h=i);
П l — матрица, содержащая значения Дг/4, как функции х и у. Размеры
этой матрицы такие же, как у матрицы z.
При hx=hy=h цифровой аналог оператора Лапласа вычисляется по формуле
L (х, у) = { (z (x-h, у) + (z (x+h, у) +z (х, y-h) +z (х, y+h)) /4-z (хг у) ) /h2
14.4. Численное интегрирование
В основе всех способов численного интегрирования, т. е. вычисления
площади криволинейной трапеции, расположенной под графиком заданной
функции, лежит суммирование значений функции в некоторых узлах,
причем значения берутся с определенными весами, зависящими от положения
узлов на отрезке интегрирования.
564
Глава 14
Общая формула численного интегрирования
J f(x)dx = ^А^(х±) + R(f),
где R(f) — остаточный член.
Чаще всего используются формулы с равноотстоящими узлами, когда
отрезок интегрирования [а, ь] разбивается на п равных частей системой точек:
xi=xo+ih (1=0,1, .. . ,п)
x,j=a
xn=b
h=(b-a)/n
Простейшая из формул численного интегрирования с равноотстоящими
узлами — формула трапеций:
ь
j"f(x)dx~h У° + У" +у, +у2 +-.. +yn-, J,
где y±=f (xi) (i=o, 1,..., n).
Для вычисления интеграла по формуле трапеций в MATLAB используется
функция trapz (пример 14.3).
L Пример 14.3. Вычисление интеграла '&&-•■;. ■ -**|L- -^¾¾ " -.".'".. -.■*' ,-1
» х=1:0.1:2;
» у=1од(х);
» trapz (х, у)
ans =
0.3В59
Точное значение интеграла, который берется аналитически, равно 0.3-863.
Длины векторов х и у должны быть одинаковы. Если вектор узлов не задан,
т. е. обращение имеет упрощенный вид s=trapz (у), то в качестве ординат х
используются их индексы (x=l: length (у)). Узлы по оси х могут быть и не
равноотстоящими (пример 14.4).
! Пример'14:4, Вычисление интеграла с неравномерным шагом по оси х .^.р: ^j|
» xn=[l:'0.1:1.5, 1.6:0.2:2];
» yn=log(хп);
Численное дифференцирование и интегрирование __^__ ^65
» trapz(x,y)
ans =
0.3859
Остаточный член формулы трапеций
Ятрап= -{{b-a)h2/12)f" (£), где а < £ < Ь.
Как показывает данное выражение, формула трапеций является точной для
линейных функций, поскольку вторая производная, входящая как
множитель в выражение остаточного члена, для этих функций тождественно равна
нулю (почти всюду равна нулю для кусочно-линейных функций).
Для f(x) = log(x) имеем f"(x) = -l/x2. При l < ^ < 2 вторая
производная -1 < f" (£) < -1/4. Так как b -a = l, h = o.l (имеется в виду случай
равноотстоящих узлов), остаточный член 0.0002 < к.,,раГ; < о.0008.
Напомним, что по формуле трапеций с равноотстоящими узлами было найдено
s = trapz(x,y> = 0.3859. С учетом остаточного члена истинное значение
интеграла заключено между 0.3861 и 0.3867 (его точное значение равно
0.3863).
Если функция задана таблично, для остаточного члена формулы трапеций
можно использовать приближенное выражение
(Ь - а)2 ~Г
ЕТРЭП = й У ,
где черта сверху означает среднее значение по отрезку интегрирования.
Для вычисления среднего значения компонентов любого вектора в MATLAB
используется функция mean. В данном случае ее надо применить к вектору
вторых разностей (пример 14.5).
■;v,v7"?^¥pu''^w'^^v"^f^;"""'""":v-"""''"''V""::""":'v ,,...^.,.^. .»,v,....y.......^yV...v...^...™ r-"»z
I рример 14;5. Использование приближенного значения остаточного члена . ..^ \
» х=1:0.1:2;
» y=log(x) ;
» d2y=diff(у,2);
» mears(d2y)
ans =
-0.0049
Подставляя найденное среднее в формулу остаточного члена, получим
R.,pan = 0.0004. Если прибавить эту поправку к ранее найденному значению
0.3859, получим 0.3863, что в пределах отображаемого количества разрядов
совпадает с точным значением.
566
Глава 14
Кумулятивное (т. е. накопительное) суммирование по формуле трапеций
осуществляется с помощью функции cumtrapz(x,y). Она возвращает
вектор, i-й компонент которого представляет сумму первых i слагаемых
формулы трапеций (пример 14.6). Значение функции cumtrapz можно
рассматривать как дискретный аналог интеграла с переменным верхним пределом.
I Пример 14.6. Накопительное суммирование по формуле трапеций
» х=1:0.1:2;
» y=log(x);
» cuiritrapz (х, у)
ans =
Столбцы с 1 по б
О 0.0048 0.0186 0.0-309 0.0708- 0.1079
Столбцы с 7 по 11
0.1517 0.2017 0.2576 0.3191 0.3859
Сравним полученный результат с точными значениями интеграла с
переменным верхним пределом, равным х * (iog(x)-i)+i. Чтобы вычислять по
этой формуле, ее необходимо "векторизовать":
» x.*(iog(x)-l)+l
ans =
Столбцы с- 1 по 6
0 0.0048 0.0188 0.0-311 0.0711 0.1082
Столбцы с 7 по 11
.0.. 1520 0.2021 0.2580 0.3195 0.3863
Разница между приближенным и точным значением не превосходит 0.004.
Более точная (и более сложная) формула численного интегрирования с
равноотстоящими узлами — формула Симпсона:
ь
J"f (x)dx = ~ (у0 + у2т + 2(уг + у4 + - + у2т_2) + 4(уг + у3 + у2т_г»,
а
Где yi = f (xt) , i = 0, 1, ..., n = 2т.
Для вычисления интеграла по формуле Симпсона в MATLAB применяется
функция quad. При обращении к ней шаг интегрирования не задается —
вместо этого используется (задаваемая явно или по умолчанию) требуемая
точность вычисления интеграла. Основную часть вычислительной работы в
этой функции выполняет рекурсивная подфункция quadstep, в которой
используются формулы Симпсоиа с небольшим числом узлов: з (m=i) и 5
Численное дифференцирование и интегрирование
567
(т=2). Найденные по этим формулам значения сравниваются. Если разница
между ними больше допустимой погрешности, отрезок интегрирования
разбивается на две равные части, функция quadstep рекурсивно применяется к
каждой половине, и результаты складываются.
Остаточный член формулы Симпсона:
IWi = -{ (Ь - a)hV'180)f"" (£>, где а < S < Ь.
Как показывает это выражение, формула Симпсона является точной для
многочленов степени, не выше 3-й, четвертая производная от которых
тождественно равна нулю (а для сплайн-функций 3-й степени — равна нулю
почти всюду).
Из описания способа вычислений функции quad вытекает, что невозможно
ограничиться заданием значений интегрируемой функции в каких-то
заранее известных узлах (как для trapz), а необходимо уметь вычислять ее
значения в любой точке интервала интегрирования. Невозможно также
использовать остаточный член для оценки точности, достигнутой функцией quad,
как это делалось выше для функции trapz, поскольку неизвестен
окончательный шаг h, необходимый при интегрировании. К тому же он не
обязательно одинаков на всем отрезке интегрирования (см. пример 14.8 с
трассировкой вычислений).
Минимальная форма обращения к функции, реализующей интегрирование
по Симпсону,— q=quad(fun, a,b). В качестве первого аргумента задается
указатель на подынтегральную функцию, второй и третий аргументы
определяют пределы интегрирования. Указатель fun может быть задан одним из
трех способов:
□ именем m-функции, заключенным в одинарные кавычки;
П указателем dfun, где am — имя функции;
□ строкой, содержащей любую формулу с одной независимой переменной:
» quad('log(х) ',1,2)
ans =
0.3863
Заметим, что в пределах отображаемого количества разрядов этот результат
совпадает с точным значением.
Функция quad допускает задание четвертого входного параметра —
абсолютной погрешности eps:
q=quad(fun,a,b,eps)
По умолчанию эта погрешность принимается равной i.e-б. Если задать ее
более высокой (например, i.e-16), интеграл будет вычисляться точнее, зато
существенно медленнее. О степени замедления можно судить по количеству
19 3ак. 899
568
Глава 14
fcnt обращений к вычислению значения подынтегральной функции
(пример 14.7).
Значение fcnt функция quad возвращает наряду со значением интеграла.
рПример 14.7, Зависимость скорости от точности вычислении. ^¾¾¾ Ъ.' }-$}"~ -/-. 'Лч
» format long
» [q,fcnt]=quad('log(х)',1,2)
q =
0.38629433-333642
fcnt =
13
» [q, fcnt] =quad('log (x)\l,2,l.e-6)
q =
0.38629433433642
fcnt =
13
» [q, fcnt] =quad Clog (x) ', 1,2*1. e-16)
q =
0.38629436111989
fcnt =
1173
» 2*log(2)-1
ans =
0.38629436111989
Еще один дополнительный управляющий параметр trace в обращении к
quad, позволяет более детально проследить за последовательными
итерациями (пример 14.8):
q=quad(fun,a,b,tol,trace)
Если trace=i, в процессе работы выдается последовательность строк вида
[fcnt а ь-а q], в которых показаны текущие значения соответствующих
переменных на каждой итерации:
П количество вычислений интегрируемой функции;
П левый конец промежутка;
□ его длина;
□ найденное значение интеграла по этому промежутку.
Если trace=o или этот параметр опущен, трассировка отключается.
Численное дифференцирование и интегрирование
569
[h^Mep^T^
» q = quad('log(х)',1,2,[),1)
(Задание параметра toi=[] приводит к использованию его значения по
умолчанию.)
Трассировка включает пять следующих строк:
5 1.0000000000 1.00000000е+000 0.3862878935
7 l.OOOOOBOOOO 5.00.000000е-001 0.1081975273
9 1.0000000000 2.50000000е-001 0.0289294372
11 1.2500000000 2.50000000е-001 0.0792682225
13 1.50.00000000 5.00000000е-001 0.2780966816
И окончательный результат:
q = 0.3863
Если интегрируемую функцию невозможно (или трудно) задать одним
арифметическим выражением, в качестве параметра можно указать имя
файла с расширением т, в котором вычисляется эта функция. Обращение в
этом случае выглядит так:
q = quad(@fun,...)
где fun.in — файл, доступный для MATLAB.
Функция logext.m (пример 14.9) отличается от обычной функции log тем,
что ее аргумент может принимать любые вещественные значения, в том
числе и отрицательные или близкие к нулю, которые либо недопустимы для
log, либо порождают комплексные значения. Хотя по смыслу аргумент
функции х и ее значение у — скаляры, внутри они обрабатываются как
векторы, поскольку вызывающая функция quad обращается к подынтегральной
функции с аргументом-вектором. Например, на самой первой итерации
таким ВекТОрОМ ЯВЛЯЮТСЯ Три ТОЧКИ: х=[а (а+Ь)/2 Ь].
\ Пример 14.9. Измененная функция для интефирования логарифма^'*^" "" '*?-'
• i .-..' '. t -...'. .-. : .-L-. i
function y=logext(x)
у = zeros(size(x));
for k = 1 : length(x);
if x(k) > l.e-10
y(k> = logfx(k));
end
end
570
Глава 14
Сохраним эту функцию в рабочем каталоге MATLAB под именем logext.m и
обратимся к функции quad:
» q = quad(Slogext,-1,2)
q =
-0.613.7
Такой же результат получается и при следующем обращении:
» q = quad(@logexc,0, 2)
q =
-0.6137
В то же время попытка выполнить аналогичное вычисление со стандартным
логарифмом сопровождается предупреждением:
» q =quad('log' ,0,2)
Warning: Log of zero
q =
-0.6137
Так как стандартный логарифм определен и для отрицательных аргументов,
но представлен в этой области комплексной функцией, то можно
вычислить, например, и такой интеграл:
» q=quad('log',-1,2)
q =
-1.6137 + 3.1416i
Еще одна возможность для пользователя функции quad — задание
произвольного числа дополнительных входных аргументов pi, р2, ..., которые
будут передаваться подынтегральной функции:
q=quad(fun,a,b, tol, trace,pi,р2,...)
Для функции, заданной таблицей значений, построим
сплайн-аппроксимацию (пример 14.10).
| Пример 14.10. Интегрирование сплайн-функции
» х = -3:3;
» у =1-1 -1-10 11 1);
» рр = pchip(x,y);
Значение полученной сплайн-функции в любой точке хх (или для вектора
хх) можно найти с помощью команды yy=ppvai(pp,xx). К сожалению, по-
Численное дифференцирование и интегрирование
571
рядок аргументов функции ppvai таков, что непосредственно подставить
ppval в quad невозможно — придется использовать функцию-посредника:
function уу = newppval(хх,рр)
уу = ppval(рр,хх);
Теперь сплайн-функцию можно проинтегрировать, передавая посреднику
структуру рр:
» q = quad(Gnewppval,-3,3, [], [],рр)
q =
О
» q = quad (gnewppval, 0, 3, [],[] ,рр)
q =
2.5833
(~" Замечание j
Те же самые результаты можно получить и другим способом: сначала найти
первообразную от сплайна с помощью функции ppint=fnint(рр), а потом
взять разность значений первообразной в соответствующих точках:
» ppval(ppint,3)- ppval(ppint,-3)
ans =
0
» ppval(ppint,3)- ppval(ppint,0)
ans =
2.5833
Если отказаться от равномерности разбиения отрезка интегрирования,
можно поставить вопрос о таком выборе узлов (и соответствующих им
коэффициентов), чтобы.при заданном количестве слагаемых численное
интегрирование давало точный результат для многочленов максимально высокой
степени. О такого рода формулах говорят, что они имеют наивысшую
алгебраическую степень точности. Доказано, что при п слагаемых можно
построить формулу, обеспечивающую точный результат для любого многочлена
степени не выше 2п-1.
Среди формул данного типа наиболее известными являются формулы
Гаусса. По ним составлены таблицы узлов для нормированного отрезка
интегрирования [-1, i] и соответствующих коэффициентов для большого
количества различных значений п [60, 641.
На основе подобных формул построена функция quadi, возможные
варианты обращения к которой полностью совпадают с вариантами обращения к
функции quad, построенной на основе формулы Симпсона.
572
Глава 14
Основную часть вычислительной работы в функции quadl выполняет
рекурсивная подфункция quadistep, в которой используются формулы, ана-
логичные формулам Гаусса, принадлежащие Лобатто (4 узла) и Кронроду
(7 узлов). Найденные по этим формулам значения сравниваются. Если
разница между ними больше допустимой погрешности, отрезок
интегрирования разбивается на 6 неравных частей, функция quadistep рекурсивно
применяется к каждой из них, и результаты складываются.
14.5. Задача Коши
для обыкновенных
дифференциальных уравнений
Дифференциальные уравнения — один из самых главных инструментов
математического моделирования физических и технических объектов и
процессов. Очень часто речь идет о процессах, развивающихся во времени,
поэтому независимую переменную обычно обозначают t.
Самый простой вариант — дифференциальное уравнение 1-го порядка,
разрешенное относительно производной:
dy/dt = f(t,y). (14.2)
Более сложный случай — уравнение, не разрешенное относительно
производной:
F(t,y,dy/dt) = 0. (14.3)
Аналитически, т. е. в виде формулы, преобразовать (14.3) к (14.2) не всегда
удается. Однако при численном решений дифференциального уравнения,
когда нужна не формула, выражающая производную, а только ее значения,
случай (14.3) достаточно легко сводится к (14.2) — просто всякий раз, когда
требуется значение f (t,y), надо решать (хотя бы численно) уравнение (14.3)
относительно производной при известных t и у.
Если переменная у является вектором (обычно столбцом), мы имеем дело с
системой дифференциальных уравнений. Дифференциальные уравнения (и
их системы), содержащие производные более высоких порядков, обычно
сводят к системам уравнений 1-го порядка с большим числом неизвестных.
Например, если в уравнении d2y/dt2 = F(t,y,dy/dt) обозначить у = yi, а
dy-i/dt = уг, получится система уравнений
yi' = у?;
у2" = F(t,y,,y2) -
В дальнейшем мы не будем особо различать уравнения 1-го порядка и
системы таких уравнений, трактуя систему как уравнение с векторной
функцией у и векторной правой частью f.
Численное дифференцирование и интегрирование
573
Задача Коши для обыкновенного дифференциального уравнения 1-го порядка
заключается в отыскании функции у = y.(t), удовлетворяющей этому
уравнению и начальному условию у (to) = у0, где t0 и у0 — заданные значения.
Способы численного интегрирования (решения) дифференциальных
уравнений разрабатывались, начиная с Эйлера, который предложил метод
ломанных: производная dy/dt заменяется разностным отношением Ду/At и,
начиная с t0, уо, вычисления производятся по формулам:
tk+i = tk+h;
Yfc+i = Ук+hf {t?.,yA).
где шаг h = At может быть как постоянным, так и переменным.
В неявном методе Эйлера используются формулы:
Wi - tfc+щ
Ук+i = Ук+hf (tit+i, уи+i) .
Чтобы найти очередное значение y^j по неявным формулам, необходимо
решить уравнение относительно этой переменной. Это можно сделать
одним из следующих способов.
П Методом итераций: взяв в качестве начального приближения y^'i = yk.
далее находим yi+'i = У* + htft^.y^),. yL+i = Ук + hf {t^-y^) и т. д.,
пока разность между соседними итерациями не станет достаточно малой.
Условием сходимости метода итераций является h— < 1 (в случае век-
ду
3f ( 3f£ 1
торной системы — = т-*-
ду I ()yd
— матрица-якобиан, |«|| — ее норма).
П Путем решения линеаризованной линейной системы уравнений
относительно Ду = yk+i - ук. Эта система имеет вид (i-h * (3f/Эу)) * Ду = hf.
Здесь i — единичная матрица, значения f и df/dy берутся при t = tk+1,
у = у:.:. Такой способ раскрытия "неявности" называется методом Розен-
брока.
Еще один вариант неявного метода — формула трапеций:
t-it+i = tt + ь;
Ук+i = Ук + (f(tt +ук) + fft^i, yk+i))h/2.
Чтобы найти очередное значение ущ.ь здесь также необходимо решить
уравнение относительно этой переменной.
Наиболее распространенными методами численного интегрирования
обыкновенных дифференциальных уравнений является семейство методов Руиге—
574
Глава 14
Кутты [51]. Порядок их точности определяется степенью h, входящей в
формулу остаточного члена. Чаще всего в литературе рекомендуют формулы
Рунге—Кутты 5-го порядка:
кг = h*f (tfcl ус);
к2 = h*f (tk + h/2,yk + kj/2) ;
k3 = h*f <tk + h/2,yk + кг/2> ;
k„ = h*f (tk + h, yk + кз) ;
y*+i = уч + (ki + 2кг + 2k3 + fc, )/6.
Использование более сложных неявных методов необходимо для так
называемых жестких систем уравнений, у которых возможна потеря точности в
процессе численного решения. Заранее по внешнему виду жесткую
систему распознать не всегда удается, тем более что свойство жесткости может
проявляться или не проявляться в зависимости от того, на каком
интервале переменной t ищется решение. На практике обычно сначала пробуют
решить задачу с помощью простого явного метода, а если обнаружится,
что численное решение идет вразнос или программа работает слишком
медленно (из-за чрезмерного измельчения шага), применяют более
сложный неявный метод.
Независимо от порядка точности метод Рунге—Кутты (явный или неявный)
является одношаговым — для нахождения у1;(1 требуется знать только yk, а
предшествующие значения ук-ъ yt.2 и т. д. ire используются. Для
интегрирования систем дифференциальных уравнений, описывающих траектории
спутниковых орбит, предпочитают многошаговые методы, в основном
связанные с именем Адамса. Они также могут быть явными и неявными.
Приведем две формулы, в которых для краткости обозначено fk=f(tk,yk). Во
всех случаях tk+i=tk+h.
Явный метод Адамса 2-го порядка:
Ук+1 = Ук + (3fk - fk-i)h/2.
Неявный метод Адамса 3-го порядка:
У*и = Ук + (5fi:n + 8fk - fk-i)h/12.
Куртис и Хиршфельдер," которые в 1952 г. ввели понятие жестких задач,
предложили для их решения неявные методы "дифференцирования назад".
Одна из их формул 2-го порядка имеет вид:
yk+i = (^ук + yk-i + 2hfk_i)/3.
Чтобы методы Адамса или Куртиса и Хиршфельдера могли стартовать,
необходимо иметь несколько начальных значений неизвестной функции.
Обычно их находят с помощью какого-нибудь варианта явного метода
Рунге—Кутты.
Численное дифференцирование и интегрирование
575
Библиотека MATLAB включает несколько функций, реализующих
различные методы решения задачи Коши для обыкновенных дифференциальных
уравнений (ode, ordinary differential equations). Синтаксически эти функции
различаются лишь именами (точнее говоря, алфавитно-цифровыми
добавками к символам ode), способ обращения к ним одинаков. Эти функции
используют методы разного порядка (иногда метод и/или порядок
варьируется от шага к шагу), имеются и другие внутренние различия.
В функции ode45 используется явный метод Рунге—Купы 4-го и 5-го
порядков в модификации Дорманда и Принца. Если характеристики задачи
неизвестны, рекомендуется первую попытку решения сделать с помощью
этой функции.
В функции ode23 используется явный метод Рунге— Купы 2-го и 3-го
порядков в модификации Богацки и Шампина. Если не требуется большая
точность и задача не очень жесткая, эта функция может оказаться более
эффективной, чем ode45.
В функции odeii3 используется метод Адамса, Башфорта и Моултона типа
предиктор-корректор переменного порядка. Если требуется большая
точность, а каждое вычисление интегрируемой функции является
"дорогостоящим", эта функция может оказаться более эффективной, чем ode<35.
Вышеуказанные алгоритмы предназначены для решения нежестких систем.
Если они дают неприемлемые результаты или работают слишком медленно,
надо применять одну из следующих функций, ориентированных на решение
жестких задач.
В функции odeiss используются численные методы дифференцирования и
формулы "дифференцирования назад". Ее следует применять, если функция
ode<35 потерпела неудачу или очень неэффективна и есть подозрения, что
задача жесткая.
В функции ode23s применяется модифицированный метод Розенброка
2-го порядка. Алгоритм этой функции одношаговый, поэтому если не
требуется большая точность, он может быть эффективнее, чем odei5s. Функция
ode23s может решить некоторые типы жестких задач, для которых odeiss
неэффективна.
В функции ode23t реализован неявный метод трапеций с использованием
"свободной" интерполяции. Ее следует применять для умеренно жестких
задач, если требуется высокоточное решение.
В функции ode23tb реализован неявный метод Рунге—Кутты с первым
шагом по методу трапеций и вторым шагом по методу "дифференцирования
назад" 2-го порядка. Подобно ode23s, эта функция может быть
эффективнее, чем odeibs, если не требуется большая точность.
576
Глава 14
В нижеследующем описании имя функции дано обобщенно в виде ode***,
где *** _ любой из приведенных выше алфавитно-цифровых суффиксов.
Простейшее обращение к любой функции ode*** имеет следующий вид:
[tout,yout] = ode*** (fun, tspan, уО.)
Здесь:
П fun — указатель на функцию вычисления правых частей
дифференциального уравнения;
□ tspan — вектор, содержащий "контрольные значения" независимой
переменной; минимальный вариант tspan=[to tfinai] (начальное и
конечное значения независимой переменной), но могут быть заданы и
промежуточные значения, тогда tspan= [to ti ... tfinai];
П yo — начальное значение зависимой переменной (скаляр или вектор-
столбец);
□ tout — вектор-столбец контрольных значений независимой переменной;
если используется минимальный вариант для tspan, выдаются все
значения, которые получались в процессе численного интегрирования; если
tspan содержит и другие значения кроме to и tfinai, то tout=tspan';
□ yout — решение, представленное массивом, в котором каждая строка
соответствует одному элементу в столбце rout.
Рассмотрим пример 14.11.
I Пример 14.11. Использование функций группы ode*** "•'■""
Дифференциальное уравнение у"=-д описывает движение материальной
точки в гравитационном поле Земли (константа д=9.8). Обозначив yi=y,.
у2=у', получим систему дифференциальных уравнений:
У1'=У2
Сформируем вектор-столбец начальных значений
у0=[0; 10]
(начальная, координата 0, начальная скорость 10) и вектор контрольных
значений
tspan=0:0.2:2
Функцию вычисления правых частей в нашем случае можно оформить в
виде анонимной функции:
» dydtH?(t,y) ty(2); -9.8];
Численное дифференцирование и интегрирование
577
Обратимся К функции ode45:
» [tout,yout] = ode4 5(dydt,tspan,уО)
Результаты представлены в табл. 14.3.
Таблица 14.3
tout
0
0.2000
0.4000
0.6000
0.8000
1.0000
yout(l)
0
1.8040
3.2160
4.2360
4.8640
5.1000
yout(2)
10.0Q0.0
8.0400
6.0800
4.1200
2.1600
0.2000
tout
1.2000
1.4000
1.6000
1.8000
2.0000
■
yout(l)
4.9440
4.3960
3.4560
2.1240
0.4000
yout(2)
-1.7600
-3.7200
-5.6800
-7.6400
-9.6000
Полная форма обращения к функциям ode*** имеет следующий вид:
[tout,yout,varargout] = ode***(fun,tspan,yO,options,varargin)
Здесь:
D options — аргумент, позволяющий задавать управляющие параметры;
□ varargin — дополнительные аргументы для вычисления fun;
□ varargout — дополнительные результаты, возникающие при некоторых
вариантах задания options.
Аргумент options позволяет отразить очень много управляющих
параметров, из которых опишем лишь некоторые. Все они задаются путем
обращения к функции odeset, аргументом которой является последовательность
пар вида
<'параметр', значение>
С
Замечание
Э
Название любого из параметров, приведенных ниже, должно быть заключено в
апострофы.
Параметр ReiToi задает допустимую относительную погрешность
вычислений, значение — положительное число, по умолчанию 1е-з.
Параметр AbsTol задает допустимую относительную погрешность
вычислений, значение — положительное число, по умолчанию ie-б. Может быть
также задан вектор-строка абсолютных погрешностей для каждой
компоненты решения.
578
Глава 14
Параметр initiaistep задает начальный шаг, по умолчанию начальный шаг
выбирается автоматически.
Параметр Mass определяет квадратную "матрицу масс" м, которая является
множителем при производной в левой части дифференциального уравнения
M(t,y) *y'=f (t,y). Значением этого параметра является сама матрица (имя
матрицы), если она заполнена константами, или указание на m-файл,
содержащий функцию, которая вычисляет матрицу масс, как функцию
переменных t и у. Например,
options=odeset('Mass', @mass) ;
Для применения В функциях odell3, ode23, ode23s, ode23tb, ode45 матрица
масс должна быть невырожденной, для применения в функциях odeiss,
ode23t матрица масс может быть вырожденной.
Параметр MassSinguiar позволяет сообщить, является ли (может ли быть)
матрица масс вырожденной. Значение этого параметра — одна из трех
строковых констант: 'yes', no', 'maybe' (последнее — по умолчанию).
Параметр Events задает "события", наступление которых влияет на ход
вычислений. Значением этого параметра является указание на m-файл,
содержащий функцию, которая отслеживает эти события. Например,
options=odeset('Events', @events) ;
Приведем пример функции events (ее имя, как и имена переменных, могут
быть любыми) — пример 14.12.
г- к',-";--- ~ "~ •-■"" ' ■■■ "i«™ — j-"T<<C'""^W<'':
: Пример 14:12. Условие окончания интегрирования '.■;* ;%&-"£-..,-я ■« ^жЧ'ЗИ
function [value,isterminal,direction1 = events(t,у)
% Фиксация времени, когда у(1) проходит через ноль
% в направлении убывания и прекращения интегрирования
value = у(1); % для слежения за обращением в 0 величины у(1)
isterminal = 1; % прекратить интегрирование при value=0
direction = -1; % при условии убывания value
В этой функции отслеживается обращение в о переменной value
(необходимым условием останова является обращение в о некоторого выражения).
Переменная isterminal задается равной 1, если при достижении vaiue=o
интегрирование должно прекращаться, и равной о, если интегрирование
должно продолжаться.
Переменная direction должна принимать одно из трех значений:
□ 1, если value возрастает при переходе через 0.;
Численное дифференцирование и интегрирование
579
О -1, если value убывает при переходе через о;
П о при любом обращении value в о.
Все три выходные переменные могут быть векторами одинаковой длины.
В этом случае их компоненты соответствуют друг другу: при value (i)=o
интегрирование прекращается, если isterminai(i)=i и продолжается, если
istermlnai (i)=o. Аналогично используются и компоненты direction(ij.
Если в примере с движением материальной точки в гравитационном поле
задать "событие" с помощью функции events, которое будет фиксироваться
в момент падения на землю: yi=o,yi'<o (direction=-i).
Параметр Jacobian задает в "аналитическом виде" якобиан 3f/3y,
используемый в неявных методах. Значением этого параметра является сама
матрица-якобиан, если она вся заполнена константами, или указание на т-
файл, содержащий функцию, которая вычисляет эту матрицу, как функцию
переменных t и у. Например,
options=odeset('Jacobian', GFJac);
Параметр Jacobian Имеет СМЫСЛ ТОЛЬКО ДЛЯ функций odel5s, ode23s,
ode23t, ode23tb. Если в одной из этих функций параметр jacobian не
задан, матрица-якобиан строится численно, что замедляет работу.
Функции odel5s и ode23t можно также применять для решения
дифференциально-алгебраических систем. Они возникают, если известен хотя бы
один первый интеграл системы дифференциальных уравнений, т. е.
соотношение между неизвестными функциями, которое обращается в тождество
при подстановке в него любого решения системы. В физике такие первые
интегралы обычно называются законами сохранения (энергии, импульса
и т. д.).
Снова рассмотрим систему дифференциальных уравнений движения
материальной точки в гравитационном поле.
У1'=У2
у2'=-д
Очевидным следствием этой системы является соотношение y2*y2'+g*yi'=o.
Если проинтегрировать его, получится 0.5*у2г+д*у1=с. Это закон
сохранения энергии (первое слагаемое — кинетическая энергия материальной точки
с массой 1, второе слагаемое — ее потенциальная энергия). Константа с
выражается через начальные условия: с=о.5*у2 (0)2+д*у1 (0). Если
использовать те же начальные значения уО=[0,- ioj, получится с=ьо.
Заменив одно из дифференциальных уравнений (например, второе) первым
интегралом, получим дифференциально-алгебраическую систему
У1,=Уг
0.5*у22 + д*у!-С=0
580
Глава 14
Внесем соответствующие изменения в функцию, вычисляющую правые части:
function dydt = funa(t,y)
dydt = fy(2); (1/2)*(у(2))"2+9.3*y(1)-50];
Первая и вторая компоненты выходного вектора этой функции играют
разную роль: первая по-прежнему представляет правую часть
дифференциального уравнения, а во второй записано выражение, которое в процессе
интегрирования должно оставаться равным о. Чтобы отразить это
обстоятельство в обращении к функции, решающей
дифференциально-алгебраическую систему, введем матрицу масс, которая является множителем при
левой части системы дифференциальных уравнений м=[1 о; о 0], и
укажем, что эта матрица вырожденная. Оба условия зададим командой
options=odeset('Mass',И,'MassSingular', 'yes')
Выполнив команду
[tout,yout] = ode23t(@funa,tspan,y0,options)
получим результаты, совпадающие с найденными ранее при помощи
функции ode45.
14.6. Краевая задача
для обыкновенных
дифференциальных уравнений
Краевая задача для обыкновенного дифференциального уравнения
заключается в отыскании функции у=у (х), удовлетворяющей на отрезке [а, ь] этому
уравнению и граничным условиям, наложенным па значения функции
и/или ее производной на концах отрезка, т. е. в точках а и ь.
Для одного уравнения первого порядка краевая задача некорректна,
поскольку значение у(а) полностью определяет поведение функции на всем
отрезке, в том числе и значение у (Ь).
Для уравнения второго порядка у''=f(х,у,у') граничные условия могут
иметь следующий вид (а, в, а0, ш, р\., Pi — заданные константы):
у[а)=А, у(Ь)=В
у'(а)=А, у'(Ь)=В
Олу(а) +Ctiy' (а)=А 1
Роу(Ь) i-P,y' [Ь)=В
Могут быть и другие варианты граничных условий, но для уравнения 2-го
порядка их число должно быть 2. Для уравнения произвольного порядка п
граничные условия (в количестве п) могут включать значения на концах от-
Численное дифференцирование и интегрирование
581
резка неизвестной функции и ее производных до (n-i)-ro порядка
включительно.
Для численного решения краевой задачи уравнение высшего (п>2) порядка
обычным образом сводят к системе из п уравнений 1-го порядка,
соответствующим образом преобразуются и граничные условия.
В MATLAB имеется функция bvp4c, решающая краевую задачу для системы
обыкновенных дифференциальных уравнений y'=f(x,y), где у— вектор,
у' — его покомпонентная производная, f(х,у) — вектор-функция.
Решение ишется в форме сеточной функции: отрезок [а, ь] делится точками
a-xi<x2<...<xn=b на части (не обязательно равные) и каждой точке xi
ставится в соответствие значение yj.. Исходя из начальных значений xt и уь
путем аппроксимации производной y'=dy/dx в каждой точке сетки
разностным отношением Ду/Дх, строится система уравнений, из которой находятся
значения уЛ. В процессе ее решения сетка xi может перестраиваться (в
частности, сгущаться), при решении используется матрица-якобиан 3f /Эу.
Начальные значения хг и yi задаются с помощью функции bvpinit:
solinit = bvpinit(xinit,yinit);
Здесь:
D xinit — вектор-строка a=xinit(l)<xinit (2) <...<xinit (n)=b;
□ yinit — гипотетические значения для y(i), могут задаваться в одной из
двух форм:
• вектор— каждая его компонента yinit(i) копируется в качестве
гипотетического решения для всех точек сетки, т. е. у {ir:) = yinit (i);
• функция задается в форме y=guess(x), где х— любая точка отрезка
[а, ь], у — вектор, длина которого равна порядку системы
дифференциальных уравнений. Для каждой точки сетки x(i) вычисляется
вектор гипотетического решения у (i,: )=guess (x(i));
□ solinit — структура, в которой при указанном выше способе обращения
к функции заполняются два поля:
• solinit.х = xinit
• solinit.у = y(i,:)
Решение краевой задачи можно найти, используя функцию bvp-зс,
простейшая форма обращения к которой:
sol = bvp4c(odefun,bcfun,solinit)
Здесь:
П odefun — функция, вычисляющая вектор правых частей;
582
Глава 14
П bcfun — функция, вычисляющая вектор граничных условий; аргументами
этой функции являются уа и yb — векторы решения у в точках а и ь; две
компоненты вектора граничных условий представляют собой выражения,
обращающиеся в о в точках а и ь соответственно;
П solinit — выходная структура функции bvpinit;
П sol — аналогичная структура, содержащая решение краевой задачи;
кроме полей sol.x и sol.у она имеет поле soi.yp, в котором содержатся
значения производной решения (sol. у)' в точках sol.x.
Рассмотрим пример 14.13.
I Пример 14.13 краевая задача для дифференциального уравнения 2-го порядка Я
Пусть имеется дифференциальное уравнение второго порядка у' ■+у=о с
граничными условиями у(0)=о, y(pi)=i.
Дифференциальное уравнение заменим системой:
У1'=У2
Уг'=-У1
и поместим в рабочий каталог m-файл, содержащий функцию,
вычисляющую правые части:
function dydx = exampl(x,y)
dydx - [y{2) -у{1)];
а также m-файл, содержащий функцию, задающую граничные условия:
function res = border(уа,yb)
res = [ ya(l) yb (1)-1] ;
В качестве начальных значений координаты х выберем с помошыо функции
linspace пять равноотстоящих точек на интервале [0, pi]
xinit=linspace(0,pi, 5)
xinit =
О 0.7854 1.5708 2.3562 3.1416
В качестве начальных приближений вектора решений в этих точках
выберем, например, yinit=[0 1].
С помощью функции bvpinit сформируем структуру solinit,
используемую при решении задачи:
» solinit = bvpinit(xinit,yinit)
solinit.x =
0 0.7854 1.5708 2.3562 3.1416
Численное дифференцирование и интегрирование
583
solinit.y =
0 0 0 0 0
11111
При таком выборе вектора yinit поле структуры solinit.y заполнено
копиями исходного вектора. Вообще говоря, такой выбор начального
приближения может оказаться не очень удачным. Альтернативный вариант состоит
в задании вспомогательной функции, вычисляющей эти компоненты. В
качестве примера возьмем функцию sincos:
function sc = sincos(x)
sc = [sin(x) cos(x)];
и выполним команду:
» solinit = bvpinit(xinit,@sincos)
solinit.x =
0 0.785« 1.5708 2.3562 3.1416
solinit.y =
0 0.7071 1.0000 0.7071 0.0000
1.0000 0.7071 0.0000 -0.7071 -1.0000
Начальное приближение, как правило, влияет на число итераций. Так что
выбор начального вектора или вида вспомогательной функции полностью
зависит от интуиции пользователя.
Для решения нашей задачи выполним команду
sol = bvp4c(@exampl,Gborder,solinit)
Результат приведен табл. 14.4, в которую для сравнения включен столбец
sin(soi.x), содержащий аналитическое решение краевой задачи.
Таблица 14.4
sol .X
0
0.1963
0.3.927
0.7854
1.1781
1.3744
1 sol.у(1)
| 0
! 0.1951
j 0.3827
j 0.7071
| 0.S23S
j 0.9808
| sol.у(2)
i 1.0000
j 0.9808
! 0.9239
| 0.7071
; 0.3827
j 0.1951
| sol.yp(l)
1 1.0000
j 0.9808
I 0.9239
| 0.7071
; 0.3827
| 0.1951
| sol.yp(2)
1 °
j -0.1951
1 -0.3827
| -0.7071
| -0.9239
I -0.980Б
j sin (sol.x)
! о
j .0.1951
j 0.3827
j 0.7071
! 0.9239
j 0.9808
1.5708 | 1.0000 | 0.0000 j 0.0000 j -1.0000 j 1.0000
584
Глава 14
( Замечание J
Сравним sol.x с xinit=[0 0.3927 0.7854 1.ПВ1 1.5708]. Можно
заметить, что функция bvp4c вставила два дополнительных узла: х=0.1963 и
х=1.3744.
Если попытаться построить решение краевой задачи в виде графика с
помощью команды plot (sol.x,s.ol.y(l,:)), результат получится не очень
гладкий — слишком мало точек содержит вектор sol.x. Эту трудность
можно преодолеть с помощью дополнительной функции bvpvai. Используя
информацию, содержащуюся в структуре sol, она строит интерполяционный
сплайн Эрмита для заданного вектора пробных точек хх, который может
содержать сколько угодно точек для обеспечения требуемой гладкости
результата.
Обращение к этой функции имеет вид:
уу = bvpvai(sol, хх)
Здесь:
П sol — выходная структура функции bvp4c;
П хх — вектор пробных точек:
П уу — значения сплайн-функиии в пробных точках.
Вектор, содержащий (по умолчанию для этой функции) 100 пробных точек,
создадим командой xx=linspace (0,pi/2), соответствующие значения
решения получим с помощью команды yy=bvpvai (soi,xx). Заметим, что каждый
элемент уу на самом деле является двухкомпонентным вектором
(подобно элементам sol.у), поэтому для рисования графика придется выполнить
команду plot (хх, уу (1,:)).
Полная форма обращения к функциям bvp4c и bvpinit позволяет:
П учесть дополнительные условия, используемые при решении;
□ использовать дополнительные аргументы в функциях odefun и befun;
Q находить значения неизвестных параметров (например, собственных чисел).
sol = bvp4c(odefun,befun,solinit,options, PI, P2, . . .) ;
Здесь:
□ options — аргумент, позволяющий задавать управляющие параметры;
О Р1, Р2, ... — дополнительные аргументы для вычисления odefun и befun.
Аргумент options позволяет отразить различные упраапяющие параметры,
из которых опишем основные. Все они задаются путем обращения к
функции bvpset, аргументом которой является последовательность пар вида
■<'параметр', значение>
Численное дифференцирование и интегрирование
585
(название любого из параметров, приведенных ниже, должно быть
заключено в апострофы).
Параметр ReiTol задает допустимую относительную погрешность
вычислений; по умолчанию ie-з.
Параметр AbsToi определяет допустимую абсолютную погрешность
вычислений; по умолчанию 1е-6. Может быть задан вектор-строка абсолютных
погрешностей для каждой компоненты решения.
Параметр FJacobian задает в аналитическом виде якобиан Э£/Эу, где f —
функция, вычисляемая в odefun. Значением этого параметра является
указание на m-файл, содержащий функцию, которая вычисляет эту матрицу,
как функцию переменных х и у. Например,
options=bvpset("FJacobian1,@FJac);
Параметр BCJacobian задает в аналитическом виде два якобиана
[Э(Ьс) /Э(уа) ] и [Э(Ьс)/Э(уЬ) ], где Ьс(уа,уЬ) — функция, вычисляемая в
bcfun. Значением этого параметра является указатель на m-файл,
содержащий функцию, которая вычисляет эти матрицы как функции переменных
уа И yb.
Неизвестный параметр (вектор неизвестных параметров) вводится с
помощью функции bvpinit, полная форма обращения к которой
solinit = bvpinit(xinit,yinit,parameters)
Здесь:
□ parameters — гипотетическое значение неизвестного параметра (вектор
гипотетических значений неизвестных параметров);
П solinit— Структура, В КОТОрОЙ Кроме ПОЛеЙ solinit. x=xinit
и solinit.у=у(i, :) заполняется еще одно поле:
solinit.parameters=parameters.
( Замечание J
Имя неизвестного параметра в обращении к функции bvpinit произвольно
(может быть, например, bvpinit (хО, уО, lambda)), однако имя поля
структуры solinit.parameters предопределено.
Полностью сформированная таким образом программа представлена
функцией bvptst.m (пример 14.14), а графический результат ее работы отражен
на рис. 14.1.
; Пример 14.14. Использование Якобиана в краевой задаче
function bvp_tst
options = bvpse.t (' FJacobian', @FJac, ' BCJacobian', @BCJac) ;
586
Глава 14
xinit=J.inspace(0,pi/2, 5) ;
yinit=[l 1] ;
solinit = bvpinit(xinit,yinit);
sol = bvp<3c (@exampl, Gborder, solinit, options) ;
xx = linspace(0,pi/2);
yy = bvpval (.sol, xx) ;
figure;
plot(xx, yy(l, : ) ) ;
xlabel('x');
ylabel('y'>;
%
function dydx = exampl(x,y)
dydx = fy(2)
-yd)];
%
function res = border(ya,yb)
res = [ya(l>
yb(1)-1];
щ
function dfdy = FJac(x,y)
dfdy = [0 1
-1 01 ;
% ,
function [dbcdya, dbcdyb] = 3CJac(ya,yb)
dbcdya. = (1 0
0 01;
dbcdyb = [0 0
1 0];
В случае, когда в задачу включены дополнительные неизвестные параметры,
должно быть увеличено число граничных условий — по одному
дополнительному условию на каждый неизвестный параметр. Эти параметры должны
быть аргументами функций odefun и bcfun (независимо от того,
Используются ли они реально для вычисления значений этих функций).
Аналитические якобианы, необходимые в случае задания условий Fjacobian и/или
BCJacobian, расширяются— теперь ЭТО [3f/3y, df/dp] И [Э(Ьс) /Э(уа) ,
Э(Ьс)/с)(уЬ), Э(Ьс)/Э(р)]. где для краткости через р обозначен
неизвестный параметр.
Численное дифференцирование и интегрирование 587
Рис. 14.1. Результат работы программы bvp_tst.m
В выходной структуре sol при наличии неизвестных параметров появляется
дополнительное поле sol.parameters, содержащее найденные значения
неизвестных параметров.
Рассмотрим дифференциальное уравнение второго порядка у''+ру=о с
неизвестным параметром р (пример 14.15).
•■ч.« и.мл ■*.«:*»■ '■ ■
л"^л:-7«у «л.'лущ;:^"-*:'1'»*"
^Ж^'ШШ^.
енциального уравнения
ЙПрймёр 1.4,1¾. Решение: краевой задачи для. диффёре
[^прря^^'- V^:f-^f ^f#^|
Дифференциальное уравнение заменим системой:
У1,= У2
y2'=-pyi
Внесем неизвестный параметр р в функцию exampi, вычисляющую правые
части системы:
function dydx = exampi(х,у,р)
dydx = [у(2)-р*у{1)];
К прежним граничными условиями у(0)=о, y(pi/2)=i добавим еще одно:
у' (pi/2)=c, соответственно изменим функцию, задающую граничные уело-
588
Глава 14
вия. Хота неизвестный параметр р не участвует в вычислении ее значения,
его необходимо включить в число аргументов.
function res = border(уа,yb,p)
res = Г уа{1) yb(2) yb(l)-l];
Как прежде, возьмем jd.nit=linspace(0,pi/2,5), yinit=[o 1] и зададим
начальное значение р=о.
Включим в программу команду
options = bvpset('FJacobian',@FJac, 'BCJacobian', gBCJac);
Функции FJac и BCjac теперь зависят и от параметра р:
function [dfdy, dfdp] = FJac(х,у,р)
dfdy = [0 1 -р 0];
dfdp = [0 -у[1)];
function [dbcdya, dbcdyb, dbcdp] = BCJac(ya,yb,p)
dbcdya = [10 0 0 0 0];
dbcdyb = [000110];
dbcdp = [0; 0; 0];
Выполнив команду
sol = bvp<3c (Gexampl, Sborder, solinit,options) ;
получим найденные ранее значения soi.x, sol.у, soi.yp и
sol.parameters=l.000.
14.7. Дифференциальные уравнения
неявного типа
Для решения неявных дифференциальных уравнений, т.,е. не разрешенных
относительно старшей производной, в MATLAB 7 появилась новая функция
odel5i.
Простейшая форма обращения к этой функции:
[t,y] = odelbi(odefun,tspan,yG,ypO)
Смысл входных и выходных параметров тот же, что и для других функций
ode*"*. В пояснении нуждается лишь параметр уро — начальное значение
производной. Для неявного дифференциального уравнения оно должно за- ,
даваться вместе с начальным моментом г.о и начальным значением функции
уб так, чтобы удовлетворялось условие F(t0,y0,yp0)=0 (здесь
f(t,y,d:y/dt)=o — неявное дифференциальное уравнение, его левая часть
Численное дифференцирование и интегрирование
589
вычисляется функцией odefun). Подобрать такие уо и уро помогает
вспомогательная функция decic, обращение к которой имеет вид:
[ у Omod, ypOmod] = decic(odefun,tO,yO,fixed_yO,ypO,fixed_ypO);
Здесь:
О yO, уро — задаваемые пользователем гипотетические начальные значения,
которые могут и не удовлетворять уравнению F(to,yO,ypO)=o;
П yOmod, ypOmod — модифицированные начальные значения, вычисляемые
функцией decic, которые достаточно точно удовлетворяют этому уравнению.
Процессом их вычисления можно управлять с помощью параметров
fixed_yO и fixed_ypO. Так, если задано fixed_yO=i, то yOmcd=yO. Если же
fixed_yO=o, то yOmod может отличаться от уо. Аналогичную роль для
вычисления ypOmod играет параметр fixed_ypo. Если мы имеем дело с системой
уравнений, когда переменные у и ур являются векторами, fixed_yo и
fixed_ypO также задаются как векторы, и соглашение об их значениях 0 и 1
относится по отдельности к каждой их компоненте. Если любой из этих
управляющих векторов задать в виде пустой матрицы [], это будет
равносильно равенству нулю всех его компонентов. По сути дела, функция decic
находит приближенное решение нелинейного уравнения.
Рассмотрим уравнение Вейссинджера (пример 14.16).
! Пример 14.16. Решение-уравнения Вейссинджера v cf.^^SH г ^^йл ^Щ^$м
Уравнение имеет вид (этот пример приведен в файле помощи):
ty^y'^Vfy'^+td^+Dy'-ey = о
Одним из его частных решений является функция y(t) = (t2+o.5)!/2.
Попробуем начальные условия to=i, y0=y(i>=sqrtp/2) и урО=о. Значение
функции уо получено подстановкой to в приведенное выше частное
решение, а начальное значение производной выбрано наугад. В том, что
выбранные начальные условия не удовлетворяют левой части уравнения
Вейссинджера, нас убеждает подстановка:
weissinger(tO,уО,урО)
ans =
-1.2247
Здесь weissinger — функция, вычисляющая левую часть уравнения
Вейссинджера. Соответствующий m-файл содержится в каталоге
MATLAB7\toolbox\matlab\demos, хотя написать единственную строчку в теле
функции труда не составляет:
function res = weissinger(t,у,ур)
res = t*yA2*yp.^-y^3*yp/42+t*(t/42+i)*yp-tA2*y;
590
Глава 14
Удивительно лишь то, что на авторство этой "программы" претендуют два
человека, и номер версии 1.6.1 свидетельствует о том, что программа
неоднократно модифицировалась.
Мы воспользовались этой программой лишь для того, чтобы
продемонстрировать возможности функции decic. Значение уо было взято из частного
решения, будем его считать точным, поэтому положим f ixed_yO=i. Значение
урО=о — является гипотезой (видимо, неточной), поэтому положим
fixed_ypO=0.
После обращения к функции decic:
[yOmod, ypOmod] = decic(@weissinger,t0,y0,1,ур0,0)
мы получим модифицированные начальные условия:
yOmod = 1.2247
ypOmod = 0.8165
которые дают удовлетворительный результат при подстановке в уравнение
Вейссинджера:
» weissinger(t0,y0mod,ypOmod)
ans =
1.2649е-004
Теперь можно непосредственно решать неявное дифференциальное
уравнение. Для сравнения найдем также значения точного решения.
ft,у] = ode!5i(Bweissinger,[1 10],y0mod,ypOmod);
ytrue = sqrt(t.A2 + 0.5);
Результаты вычислений представлены в табл. 14.5.
Таблица 14.5
t
1.0000
1.0379
1.0759
1.1518
1.2277
1.3036
1.4554
1.6072
1.7589
1.9107
У
1.2247
1.2561
1.2879
1.3522
1.4177
1.4840
1.6191
1.7569
1.8969
2.0362
ytrue
1.2247
1.255Э
1.2875
1.3515
1.4168
1.4830
1.6181
1.7558
1.8958
2.0374
t
3.1251
3.4286
3.5804
3.8840
4.1876
4.4912
5.0983
5.7055
5.9305
6.3805
У
3.2040
3.5002
3.6487
3.9467
4.2453
4.5446
5.1449
5.7456
5.9689
6.4158
ytrue
3.2041
3.5008
3.6496
3.9478
4.2469
4.5465
5.1471
5.7491
5.9725
6.4195
Численное дифференцирование и интегрирование
591
Таблица 14.5 (окончание)
t
2.0625
2.2143
2.5179
2.8215
У
2.1809
2.3248
2.6154
2.9087
у true
2.1804
2.3245
2.6153
2.9087
t
7.2805
8.1805
9-.0805
10.0000
У
7.3107
8.2067
9.1044
10.0217
ytrue
7.3147
8.2110
9.1080
10.0250
Рассмотрим пример 14.17.
; Пример 14.17. Колебательный контур с железом ,..■■ '■-■ ж% .,« igf?" -t
В книге Андронова А. А., Витта А. А. и Хайкина С. Э. "Теория колебаний"1
рассматривается колебательный контур, состоящий из электрического
конденсатора и магнитной катушки. Катушка снабжена железным сердечником,
магнитный поток в котором является нелинейной функцией Ф(Ц от
протекающего через катушку тока i. На практике эту функцию достаточно
хорошо аппроксимируют выражением:
Ф(1) = A*arctg(w*i/S) + B*w*i/S
Здесь а, в и s — некоторые константы, зависящие от материала сердечника,
aw— число витков провода в катушке.
После некоторых преобразований уравнения Кирхгофа и введения
безразмерных переменных интеграл энергии в предположении отсутствия всякого
рода потерь приводит к неявному дифференциальному уравнению
следующего вида:
A*ln(l+q'2) + B*q'2 + q2 = Е
Здесь:
Dq — заряд на обкладках конденсатора;
П q' = dq/dt — ток в контуре;
П е — значение энергии, зависящее от начальных условий.
Для t = о зададим начальные условия q0 = о, qo* = 1 и вместо обращения к
функции decic подберем константу е, удовлетворяющую уравнению энергии.
При этом функция F[t,q,qp) может выглядеть следующим образом:
function res=ABX(t,q,qp)
А=1.4;
В=25;
1 Андронои А. А., Витт А. А., Хайкин С. Э. Теория колебаний. — М.: Физматгиз, 1959.
592
Глава 14
E=A*log(2)+B;
res=A*log(l+qp*2)+B*qpA2+q'v2-E;
Заметим, что время t, которое не входит явно в уравнение, является
фиктивным параметром. Для обращения к функции odeisi составим еше одну
вспомогательную функцию:
function test_ABX
q0=0;
qpO=l;
tspan=[0,1001,-
ft,q]=odel5i(6ABX,cspan,qO,qpO);
plot(t,q)
XLabel.f ■ t'), YLabel (' q')
Результат интефирования на интервале [о, looj отображен на рис. 14.2.
Рис. 14.2. Колебательный контур с железом
При решении неявного дифференциачьного уравнения возможно досрочное
окончание процесса интегрирования по достижению некоторого условия —
равенства нулю заданного выражения. В этом случае список параметров
функции odeisi дополняется следующим образом:
[t, у] = odel5i(odefun, tspan, уО, урО, options)
Численное дифференцирование и интегрирование
593
где значение options формируется с помощью функции odesec, аргументами
которой являются пары "имя — значение". В нашем случае понадобится
параметр 'Events', а его значением будет указатель на функцию,
определяющую три выходных значения:
function [v,i,d]=qq(t,q)
v=q-4;
i=l;
d=l;
Контролируемое событие заключается в том, что значение v обращается в
нуль при условии возрастания этой величины (признак d=i), и процесс
интегрирования прекращается при наступлении указанного события (признак
i=D-
Обращение к odeibi в нашем случае может выглядеть так:
[t,q]=odel5i(@ABX,tspan,qO,qpO,odeset('Events', 6qq));
Результат работы модифицированной программы приведен на рис. 14.3.
( Замечание ^
Следует отметить, что справка по функции odelsi содержит дезинформацию
по поводу оформления функции events — реакции на событие прерывания
процесса интегрирования. Там указано, что эта функция должна получать три
входных параметра events (t,q,qp). Если следовать этому указанию, то
MATLAB выдает сообщение о том, что аргументов слишком много.
4
3.5
3
25
сг 2
1.5
1
0.5
Q
• i i • у
/
У
X
/
/
у
/
/
Г
/
/
У
/
/
/
' I . 1
"01234!
t
1
Рис. 14.3. Интегрирование до выполнения условия q=4
Глава 15
Нелинейные уравнения
и оптимизация
15.1. Корень уравнения
с одним неизвестным
Для решения уравнений вида fun(x)=o используется функция fzero.
Алгоритм, реализованный сю, представляет собой комбинацию хорошо
известного метода дихотомии (деления пополам), метода секущих и метода
обратной квадратичной интерполяции. В простейшем варианте обращения кроме
указателя на функцию, корень которой ишется. задается окрестность хс, с
которой начинается поиск:
х = fzero(fun,хО)
Аргумент fun может быть задан одним из способов:
П как формула с неизвестным х, заключенная в апострофы;
□ как имя m-файла (в апострофах и без расширения гп);
□ как указатель на функцию (например, @fun_name);
П как указатель на анонимную функцию (например, f unhandle).
( Замечание ^
Формула, заключенная в апострофы, в качестве независимой переменной
может содержать только х. Использование независимой переменной с другим
именем вызовет сообщение об ошибке.
Аргумент хО может быть задан одним из двух способов:
П как вектор [а ь], представляюший интерва;! (а<ь), на концах которого
функция fun меняет знак, что гарантирует нахождение, по крайней мере,
одного корня на этом интервале;
□ как скалярное значение, в окрестности которого предполагается
нахождение корня. В этом случае функция fzero сама пытается найти отре-
596
Глава 15
зок с центром в заданной точке хо, на концах которого функция fun
меняет знак.
Чтобы облегчить работу по выбору начального приближения, разумнее всего
построить график функции y=fun (х>.
График функции у = х*е~* + sin(x) представлен на рис. 15.1. Он получен с
помощью программы из примера 15.1.
"•'/■.".••*" vamw.' fzj ц» ■ ■ ■ * •* • * v :w'
■ Пример 15.1. Прстрреийе графика функции для локализации корня
» х=0:0.1:2*pi;
» plot(х,х.*ехр(-х)+sin(х))
» grid oh
» title ('y=x*exp(-x)+sin(x)')
v. f
Рис. 15.1. График функции для локализации корня
Из графика видно, что один из корней находится на интервале [з, <j].
И этой информацией естественно воспользоваться при обращении к
функции fzero:
» x=fzero('х.*ехр(-х)-i-sin(x)',[3,4])
х =
3.2665
Вместо явного задания формулы для функции fun мы могли бы объявить
соответствующую функцию, запомнив ее в виде автономного m-файла или
Нелинейные уравнения и оптимизация
597
включив ее в качестве подфункции в файл нашей программы. После такого
объявления обращение к функции fzero могло бы выглядеть так:
function fzerol
x=fzero(@fl,[3,41)
function y=fl(z)
y= z*exp(-z)+sin(z) ;
Если мы хотим получить не только значение корня, но и узнать значение
функции в найденной точке, то к функции fzero можно обратиться с двумя
выходными параметрами:
» [х,fJ=fzero('x. *exp(-x)+s.in(x) ', [3, 4] )
х =
3.2665
f =
2.0817е-016
Судя по значению функции, точность нахождения корня достаточно высока.
В ряде задач такая точность может оказаться излишней. MATLAB
предоставляет пользователю возможность формировать различные условия
прекращения итерационного процесса — по точности вычисления координаты
х, по модулю значения функции fun, по количеству обращений к функции
fun и т. д. Более подробно эти возможности описаны в разд. 15.6.
В некоторых случаях применение функции fzero может дать
парадоксальные (на первый взгляд) результаты. Например, попытка решить уравнение
tg(x)=o на интервале [1,2] приводит к следующим результатам
(пример 15.2).
'Пример 15:2. Поиск решения'tjj(ic)=0 на интервале [i, 2] ' • -' Ч™
и.Й&л^;&^^^^;^;::&^й.,../ЙйО....>::.й:^.Л^.„ л..::... ,;. ь;...-..л. А.:. .....
» [x,f]=fzero(.'tan{x)', [1,2])
X =
1.5708
f =
-1.2093е+015
Якобы "корень", соответствующий приближенному значению я/2, на самом
деле является точкой разрыва, при переходе через которую функция меняет
знак. Выведенное значение функции в найденной точке убеждает нас в том,
что найден не корень.
598
Глава 15
Функция fzero может возвратить еще два выходных параметра
(пример 15.3):
[х,f, e_flag,inform] = fzero(fun,xO)
Положительное значение e_f lag (обычно, это l) означает, что удалось
найти интервал, на концах которого функция fun меняет знак (пример с tg(x)
не должен притупить вашу бдительность). Если такой интервал не
обнаружен, то e_flag=-i. Структура inform содержит три поля с именами
iterations, funcCount И algorithm. В первом ИЗ НИХ находится количество
итераций, выполненных при поиске корня, во втором — количество
обращений к функции fun, в третьем — наименование алгоритма,
использованного для нахождения корня.
i Пример 15.3. Дополнительные параметры, возвращаемые функцией fzerp'S^i j
» [x,f,e_f lag,inform] =fzero ('x.*exp(-x)+sin(x)', [3,4])
x =
.3.2665
f =
2.0817e-016
e_flag =
1
inform —
iterations': 8
funcCount: 8
algorithm: 'bisection, interpolation'
Обратите внимание на то, что для достижения очень высокой точности
потребовалось всего 8 итераций. Простое деление отрезка пополам для
достижения такой же точности потребовало бы намного больше итераций.
Условие обнаружения интервала, на концах которого функция принимает
значения разных знаков, является принципиальным для алгоритма,
использованного в функции fzero. Даже в таких тривиальных уравнениях, как хг=о,
обычно не удается найти решение (пример 15.4).
! Пример 15.4. Задание интервала с одинаковым знаком фунщий'на^кон!)^''3^'-''^
» [х, f,e_flag]=fzero СхЛ2', [-1,1])
??? Error using ==> fzero
The function values at the interval endpoints must differ in sign.
Нелинейные уравнения и оптимизация
599
Отказ произошел из-за того, что на обоих концах заданного интервала
функция принимает положительные значения. Если начальное
приближение "случайно" совпадает с корнем, то функции fzero не остается ничего
другого, кроме как выдать подвернувшееся решение (пример 15.5).
» [x,f,e_flag]=fzero('x'-2,,0)
x =
О
f" =
О
e_flag =
1
Однако изменение стартовой точки вновь ставит алгоритм поиска в тупик.
Попытка расширять интервал с центром в точке х=1 приводит к появлению
бесконечно больших значений функции (пример 15.6), но интервал, на
котором бы произошла смена знака, так и не может быть обнаружен (обратите
внимание на значение выходного параметра e_f lag).
Шрш^рЧ5:6^0|Щб^
:>> [к,£,е_Г1ад]=Е2его('хЛ2',1)
Exiting fzero: aborting search for an interval containing a sign change
because NaN or Inf function value encountered during search
(Function value at -1.716199e+154 is Inf)
Check function or try again with a different starting value.
x =
NaN
f =
NaN
e_flag =
-1
15.2. Решение систем
нелинейных уравнений
Функция f solve, вообще говоря, предназначена для решения систем
нелинейных уравнений вида f(x)=o, где х — вектор или матрица неизвестных, а
20 3як 809
600
Глава 15
f — функция, значением которой является вектор или матрица. Алгоритм
ее работы использует начальное значение хо и базируется на минимизации
суммы квадратов составляющих функции F методами Гаусса—Ньютона
и Левенберга— Марквардта (более подробные сведения о них приведены в
разд. 15.4.3). В простейшем случае обращение к fsolve имеет вид:
х = fsolve(F,X0)
В частности, функцию fsolve можно использовать и как альтернативу
функции fzero для нахождения корня единственного нелинейного
уравнения (пример 15.7), например, sin(x)=o.
I Пример 15.7. Поиск корня с помощью функций %S6lW-'"Sb^f-' ■ ;^^>зйй1йР Vk
» х = fsolve (@sin, 1)
Warning: Cannot, determine from calling sequence whether to use new
(2.0 or later) FSOLVE function or grandfathered FSOLVE function.
Assuming new syntax; if call was grandfathered FSOLVE syntax,
this may give unexpected results.
To force new syntax and avoid warning, add options structure argument:
x = fsolve(@sin,3,optimset('fsolve'));
To force grandfathered syntax and avoid warning, add options array
argument:
x = fsolve(Gsin,3,foptions);
Optimization terminated successfully:
First-order optimality is less than options.TolFun.
x =
0
Смысл довольно длинного предупреждения заключается в том, что по
форме вызова MATLAB не сумел понять, какая Из двух функций fsolve имеется
в виду — очень устаревшая (grandfathered) или более современная (версии
2.0 или выше). Для того чтобы отличать одну версию от другой, MATLAB
предложил использовать дополнительно третий параметр. Тем не менее
наше обращение было воспринято как вызов более свежей версии, которая
нашла решение, ближе всего расположенное к начальной точке х0=1.
Интересно, что второй аргумент функции fsolve может быть задан в виде
вектора начальных значений, и для каждого компонента этого вектора будет
найдено близлежащее решение (пример 15.8).
Нелинейные уравнения и оптимизация
601
[Пример 15.8, Поиск решений для вектора начальных 'зйъЧа&к ^*:^аЩ^'1''°% - !
» х = fsoive[@sin,[1 2 3 4 5 6].optimset(■fsolve'))
Optimization terminated successfully:
First-order optimality is less than options.TolFun.
x =
0 3.1416 3.1416 3.1416 6.2832 6.2832
В отличие от fzero функция fsolve может найти приближенное решение
для упоминавшегося выше уравнения х2=о и не спасовать в окрестности
точки разрыва функции tg(x) (пример 15.9).
{ Пример 15.9. Поиск решения »e2=Q и.йдЧх),^Щ^?^КШ^^-^г^^^^5Й^----1
» х = f solve (' x"2',l,optimset(' Display', 'off') )
x =
0.0078
» x = fsolve(Stan,l,optimset('Display',"off ))
x =
2.3205e-010
Смысл третьего параметра в двух предыдущих обращениях заключается в
подавлении "лишних" сообщений. Более подробно о дополнительных
входных параметрах функции f solve см. в разд. 15.6.
Главным назначением функции fsoive является решение систем
нелинейных уравнений, что мы продемонстрируем на примере 15.10.
{ Пример 15.10. Решение системы нелинейных уравнений;'^ ^^Щ^Ф^-Щу^1\
Уз = Xi + хг - sin(nxi)
Уг = xi - Х2 - cos (71хг)
Объявим функцию funs с, значения которой сформируем в виде вектора-
столбца:
function у = funsc(х)
y=[x(l)+x(2)-sin(pi*x(l)); х(1)-х(2)-cos(pi*x<2))];
А теперь обратимся к функции fsoive, задавая каждый раз разные
начальные значения (xl, х2). Так как fsoive подобно fzero умеет возвращать и
вектор-столбец функций в найденной точке, то мы воспользуемся двумя
выходными параметрами, чтобы оценить точность решения. Обратите вни-
602
Глава 15
мание на то, что координаты начальной точки тоже представлены в виде
вектора-столбца:
» [x,f] = fsolve(Gfunsc, [0.2,-1] ,optimset ['Display1, 'off') )
x =
0.3915
0.5510
f =
1.0e-010 *
0.8924
-0.0333
Результаты последующих обращений к функции solve из разных стартовых
точек приведены в табл. 15.1.
Таблица 15.1
№
1
2
3
4
5
6
x0=[xl;x2]
xl
0.2
1
1
-0.2
-0.5
-1
х2
1
0.5
-0.2
0
-1
-2
Решение
xl
0.3915-
0.5000
0.7776
-0.2329-
-0.5000
-0.4595
х2
0.5510
0.5000
-0.1345
-0.-3352
-0.5000
-1.6778
Значения функции
yi
0.8924е-010
0.1654е-008
0.7000е-007
-0.1062е-009
-0.2195е-00б
-1.1454
Y2
-0.0333е-010
0.0000
0.1638е-007
0.0018е-009
-0.0000
0.6883
Из табл. 15.1 видно, что для первых пяти начальных точек было найдено
пять разных решений, тогда как шестой эксперимент вместо корня
обнаружил нечто похожее на точку локального минимума.
Разобраться со всеми ситуациям помогут графики наших функций. На
рис. 15.2 представлены:
□ графики двух функций: x2=sin(pi*xi)-xi (сплошная линия) и xi=
=cos (pi*x2)+x2 (штриховая линия). Эти функции получены путем
разрешения уравнений системы относительно соответствующих переменных;
П решения системы — крупные точки пересечения этих графиков и
соответствующие стартовые точки (мелкие) с соединяющими их отрезками.
Для их построения была использована программа progl5_l.m (пример 15.11).
Нелинейные уравнения и оптимизация
603
function progl5__l
axesCXlim', [-1 1.5],'Ylim', [-1 1.5])
axis equal; grid off; hold on
xl=-l:0.1:1.5; y=sin(pi*xl)-xl; plot(xl,y,'k-');
x2=-l:0.1:1.5; y=cos(pi*x2)+x2; plot(y,x2,'k:');
xlabel('xl'); ylabel('x2');
title ('Решение нелинейной системы','FontName','Courier');
xlx2=[0.2,1,1,0.5,1,-0.2,-0.2,0,-0.5, -1,-1, -2];
for j=l:6
xl=oclx2(2*j-l);
x2=xlx2(2*j) ;
lirie(xl,x2, 'Marker', '.', 'MarkerSize', 10);
x = fsolve(@funsc,[xl,x2],optimset('Display','off'));
line(x(l),x(2),'Marker','.','MarkerSize',20);
plotdxl x(l)],tx2 x(2)],'k-');
end
function у = funsc(x)
y=[x(l)+x(2)-sin(pi*x(l)); x(l)-x(2)-cos(pi*x<2))];
1.5
к
*,
.i.Wzr- Ч-ЙГ*
"
"
-
-1.5
Решение нелинейной систему ,-, ч
.---''
\ ^
\;
.
■"^^"А
/ \~~-
I / 3\
<^1
-1 -0.5' " 0 0.5 .
х1.
,~~
Л
>
J
\
1
■;■*■■
•?-■
Г
f
I
§;
-¾^
Рис. 15.2. Графики функций
604
Глава 15
В выделенные пределы неудачная стартовая точка не попала, но если бы на
полученные графики были нанесены линии уровня минимизируемой
функции у? + у\, то можно было бы обнаружить, что точка 6 действительно
соответствует локальному минимуму. Если бы мы не отключили выдачу
сообщений функции fsoive, то в последнем запуске было бы выдано следующее
пояснение:
Optimizer is stuck at a minimum that is not a root.
Try again with a new starting guess
Среди выходных аргументов функции fsoive могут присугствовать такие же
по смыслу параметры, которые допускала функция f zero:
[х,fval,exitflag,output] = fsoive(fun,xO)
Значение признака exitf lag=l свидетельствует о том, что решение системы
найдено. При exitflag=o решение не найдено, т. к. итерационный процесс
был прерван в связи с достижением максимального количества итераций
или обращений к функции fun. При exitfiag=-i достигнутый минимум не
является решением системы.
В структуре output появились дополнительные поля с именами:
П stepsize, в котором выдается величина шага при завершении поиска;
П firstorderopt, в котором выдается точность, достигнутая по значению
функции.
Например, на одном из предыдущих запусков мы могли бы получить
следующую информацию:
.» [х,f,e_flag,inform] = ...
fsoive(Sfunsc, [1;0.5],optimset('Display', 'off')}
x =
0.5000
0.5000
f =
1.0e-OOB *
0.1654
O.'OOOD
e_flag =
1
inform =
iterations: 7
funcCount: 21
algorithm: 'trust-region dogleg'
firstorderopt: 1..6541e-009
Нелинейные уравнения и оптимизация
605
Обратите внимание на то, что в отличие от функции fzero здесь число
итераций не совпадает с количеством обращений к функции fun. Дело в том,
что алгоритм поиска решения в функции fsolve активно использует
якобиан системы уравнений, который в данном примере находится численным
методом (аналог замены производных разностями). В функции fun может
быть предусмотрена возможность задания операторов, вычисляющих
якобиан по аналитическим формулам (пример 15.12). Это может существенно
уменьшить количество обращений к функции fun, и, тем самым, ускорить
итерационный процесс.
Подключение якобиана предусматривает два момента. Во-первых, среди
входных параметров при обращении к функции fsolve должно быть
соответствующее указание типа optimset( ■ jacobian', 'on*). Во-вторых,
операторы для вычисления якобиана должны входить в определение функции
fun, которая в данном случае должна возвращать два выходных аргумента.
г""?"""?""""""""''""""" :"" ■-■■■ '""'■ "\v:;""^s^"o4j:^;5V'"?'""""™s№-""W'";4i;''"T""^vv'^'"""v^S^:k*''1£™^^"«:
| Пример15-12: Вычисление якобиана поч^_{ши,™чес|мм;формулам^^^^^В-^^
function [F,J] = fun(x)
Г = ... % вычисление вектора или матрицы системы
if nargout > 1 % два выходных значения
J = ... % вычисление якобиана как функции от х
end
В рассматриваемом примере якобиан представляет собой матрицу 2X2,
образованную частными производными от yi и уз по xi и хг:
ЭУ1 ЭУ1
Эх5 Эх2
ЭУ; ЭУ2
Эх: Эх.
Добавим к функции funsc формулы для вычисления якобиана:
function [у,j] = funscj(х)
y=[x(l)+x(2)-sin(pi*x<l)>; x(l)-x(2)-cos(pi*x{2))];
if nargout>l
j=[l-pi*cos(pi*x(l) 1; 1 -l+pi*sin(pi*K(2))];
end
Зададим x0=[l;0.5] и выясним, насколько помогает наличие формул
вычисления якобиана:
» [х,f,e_flag,inform] = ...
fsolve(@funscj,[1;0.5],optimset('Jacobian','on'))
606
Глава 15
Optimization terminated successfully:
First-order optimality is less than options.TolFun.
x =
0.5000
0.5000
f =
1.0e-008 *
0.1653
g.oooo
e_flag =
1
inform =
iterations: 7
funcCount: 7
algorithm: 'trust-region dogleg'
firstorderopt: 1.6525e-009
По сравнению с предыдущим запуском для нахождения корня с такой же
точностью потребовались те же 7 итераций, но количество обращений к
функции fun уменьшилось в три раза. Справедливости ради следует
отметить, что время работы функции за счет вычисления якобиана увеличилось
примерно в два раза. Так что общий выигрыш по скорости нахождения
корня составил примерно .50%.
В теории линейных управляемых систем часто возникают матричные
уравнения (пример 15.13). Они могут быть как линейными (уравнения Ляпунова
и Сильвестра — см. разд. 13.7.3), так и нелинейными (уравнение Риккати —
не путать с дифференциальным уравнением Риккати).
ёПример 15.13. Метрйчйыв'уравйГеййя'.,^^Ё^?1^ .-. ■;**>&*.> .^,-^.-:¾¾¾.-, '-^щ^Ы
Рассмотрим квадратное матричное уравнение вида ах2+вх+с=о, отвлекаясь от
его происхождения. Определим функцию, аргументами которой кроме
неизвестной матрицы х являются матрицы-коэффициенты а, в, С:
function F= quadratic (X, А, В, С)
F = А*Х*Х+В*Х+С;
Зададим конкретные матрицы-коэффициенты А, в, с и стартовую матрицу хо:
» А=еуе(2); % единичная матрица 2x2
» В=еуе(2); % единичная матрица 2x2
» О[-6, -5; 0, -6];
» X0=ones(2); % матрица 2x2, заполненная единицами
Нелинейные уравнения и оптимизация
607
и обратимся к функции f solve:
» opt = optimset('Display','off');
» [XI, F, e_f lag]=fsolve (@quadratic, XO, opt, А, В, C)
Обратите внимание на тот факт, что обращение к функции quadratic
требует передачи ей не только аргумента х, но и еще трех дополнительных
параметров — матриц а, в, с. В приведенном выше вызове функции f solve
показано, как эти параметры должны быть переданы.
В результате решения матричной системы уравнений получим следующие
результаты:
XI =
2.0000
-0.0000
F =
1.0е-009 *
0.3961
-0.2319
е flag =
1
1.
2.
-0.
0.
.0000
.0000
.6771
.3961
Вообще говоря, матрица xi=[2 1,-0 2] является точным решением нашего
матричного уравнения. Однако f solve нашла приближенное решение, в чем
можно убедиться, выдав большее количество значащих цифр:
» format long
» XI
XI =
2.00000000008849 0.99999999982918
-0.00000000004637 2.00000000008849
Именно этим и объясняется ненулевая невязка f в найденной точке.
Задав другую стартовую матрицу хо=-2*еуе(2), найдем второе решение
квадратного матричного уравнения:
XI =
-3.0000 -1.0000
0 -3.0000
F =
1.0е-013 *
0 0.3730
0 0
..e_f lag =
1
608
Глава 15
Как и в примере 15.10, не всякая стартовая матрица приводит к настоящему
решению: для xo=-ones (2) получим:
XI -
-0.5314 -79.6478
-0.0784 -0.5314
F =
-0.0010 -0.0008
0.0049 -0.0010
e_flag =
0
И довольно большая невязка f, и значение признака e_flag=o
свидетельствуют о том, что найденное "решение" не является корнем нашего уравнения.
Итерационный процесс был прерван в связи с превышением максимального
количества итераций или обращений к функции quadratic. Установить
более точную причину позволяет анализ одного из полей структуры, которую
можно получить в качестве выходного параметра:
» [XI,F,e_flag, out]=fsolve (Squadratic,X0, opt,А,В,C)
XI =
-0.5314 -79.6478
-0.0784 -0.5314
F =
-0.0010 -0.0008
0.0049 -0.0010
e_flag =
0
out =
iterations: 82
funcCount.: 402
algorithm: 'trust-region dogleg1
firstorderopt: 0.1514
Значение поля out.funccount свидетельствует о том, что превышено
максимально допустимое количество обращений к функции.
Рассмотрим пример 15.14.
I. Пример 15.14; Поиск корней модуля полинома, ■-&&■?•.— " "Vv-V «fe»u* , ""■■ г- 1
В теории полиномов рассматривается вещественная функция комплексного
аргумента — модуль полинома. Она, естественно, равна о в тех точках
комплексной плоскости, которые являются корнями полинома. Рассмотрим
Нелинейные уравнения и оптимизация
609
комплексный полином w=z3+z, корнями которого ЯВЛЯЮТСЯ zi,3=±i И z2=0.
Построим функцию — модуль этого полинома, в которой комплексный
аргумент z представлен как вещественный вектор х[1:2]:
function у = abspoly(x)
z = complex(х(1),х (2)) ;
w = z."3+z;
у = abs(w);
Попробуем с помощью функции fsolve найти решение нелинейной
системы из одного уравнения с двумя неизвестными, задавая разные начальные
точки:
» xl=-0.5; х2=1.5; x0=[xl;x2];
» options=optimset('Display','off ) ;
» [x,f,e_flag] = fsolve(@abspoly,xO,options)
При первом же запуске функция fsolve выдает предупреждение о том, что
метод "trust-region dogleg" не умеет решать неквадратную систему
уравнений, поэтому она переключается на метод Гаусса—Ньютона:
Warning: Default trust-region dogleg method of FSOLVE cannot handle
non-square systems; switching to Gauss-Newton method.
(Type "warning off Optimization:fsolve:NonSquareSystem" to suppress this
warning.)
Вывод текста предупреждения можно подавить, если предварительно
выполнить команду:
» warning off Optimization:fsolve:NonSquareSystem
Результаты трех пробных запусков приведены в табл. 15.2.
Таблица 15.2
№
1
2
3
хО
xl
-0.5
1
0.5
х2
1.5
0.5
-1.5
X
х(1)
-0.0019
0.4860 е-008
0.0019
х(2)
1.0013
-0.2634 е-008
-1.0013
fz
0.0046
3.6l.4 4e-0O9
0.0046
В первом и третьем случае невязка не очень мала. По дополнительной
информации можно обнаружить, что процесс поиска корней был прерван
(e_fiag=o) после 33 итераций и 202 обращений к функции. Во втором
случае (e_fiag=i) для нахождения достаточно хорошего приближения к
решению потребовалось всего 5 итераций и 28 обращений к функции. На рис. 15.3
610
Глава 15
представлены линии уровня функции abs(w) и три найденных решения
вместе со стартовыми точками. Получено это изображение с помощью
программы progl5_2.m (пример 15.15).
Рис. 15.3. Нули комплексного полинома w=z3+z
шштшшштшшмшшмшшвштш
function ргод15_2
h=0.1; X0=-1.5:h:1.5; Y0=-2:h:2;
[X Y]=meshgrid(XO,YO);
s=size(X);
for i = l:s(l)
for j = 1:3(2)
Z(i,j) = abspoly([X(i,j); Y(i,j>]>;
end
end
M=max(max(Z)); v=0:0.2:l; V=1:M;
contour(X,Y,Z,[v VI,'-r');
hold on; axis equal; grid off;
Нелинейные уравнения и оптимизация
611
xlabel('xl'); ylabel(•х2•);
title('Решение нелинейного уравнения','Font-Name','Courier');
xlx2=[-0.5,1.5,1,0.5,0.5,-1.5];
options=optimset ('Display', 'off ) ;
for j=l:3
xl=xlx2<2*j-l); x2=xlx2(2*j ) ;
line(xl,x2, 'Marker', '.', 'MarkerSize', 10);
[x,Л,e_flag,inform] = fsolve(@abspoly,[xl;x2], options)
line(x(l),x{2), 'Marker', '.', 'MarkerSize', 20);
plot([xl x(l)], [x2 x(2>], 'k-');
end
15.3. Минимизация унимодальной функции
одной переменной
Функция одного переменного y=f (х) называется унимодальной на отрезке
[а, ь], если имеется единственное значение х0е[а, ь] такое, что:
П f (хо) — минимум f (х) на [а, ь];
О f (х) строго убывает при х<хп;
□ f(x) строго возрастает при х>хо.
Для отыскания минимума унимодальной функции на заданном отрезке
(пример 15.16) используется функция fminbnd. Алгоритм, реализованный
ею, представляет собой комбинацию метода золотого сечения и обратной
параболической интерполяции. В простейшем варианте вызова кроме
указателя на минимизируемую функцию fun задаются начало и конец интервала
Поиска: x=fminbnd(fun,a,b).
» х=йт.пЬп<ЗГхЛ3-2*х',0,2)
х =
0.8165
Рассмотрим пример 15.17. График функции y=fun(x)=3x4-4x3-i2xz
представлен на рис. 15.4. На каждом из интервалов [-2, о] и [о, з] эта функция
унимодальна. Для нахождения ее минимумов на указанных интервалах и
построения графика с выделением точек минимума использована программа
progl5_3.m.
612
Глава 15
^:..-.,^.,^.^.,,^..^,.................
Пример 15.17;'Прйе1с:мин'ймумрв KOHkpew
ШШШШ>Ш**
function progl5_3
хх=-2:0.1:3; yy=fun(xx);
plot (хх, уу, 'к-')
hold on; grid;
xlabel('x'); ylabel('y');
[x,f]=fminbnd<Gfun,-2,0)
line(x,f, 'Marker', '.', 'MarkerSize', 20);
[x,f]=fminbnd(@fun,0,3)
line(x, f, 'Marker', '.', 'MarkerSize', 20);
function y=fun(x)
у=3+х.л4-<3*х.л3-12*х.л2;
40
30
20
10
^ 0
-10
-20
-30
-40,
-л
- \
■
■
■
>. Sfi, -1 о
1
■^
^\
^
i
-1 '•
X
\ /
v_/
,
2
-
1
/-
/-
/ -
/ -
-
.i '.
1Й'- ..
л
, i
3 -.,
Рис. 15.4. Поиск минимума унимодальной функции
Запуск этой программы дает следующие результаты:
X =
-1.0000
f =
-5.0000
х =
2.0000
f =
-32.0000
Нелинейные уравнения и оптимизация
613
На отрезке [-2, з] эта функция не является унимодальной, однако
программа fitiinbnd находит один из минимумов (х=2.оооо) и не выдает никаких
сообщений.
Минимизируемая функиия может быть негладкой и даже разрывной (см.
график на рис. 15.5):
function prog!5_4
line ([-2,-eps],[g(-2),g(-eps)]);
hold on; grid off;
line{[eps,2],[g (eps), g (2)]);
xlabel('x'); ylabel('y');
[x,f]=fminbnd{@g,-2,2)
line(x,f,'Marker','.','MarkerSize',20);
function y=g(x)
if x<=0
y=-x-l;
else
y=x+l;
end
'"'.. ?
*' 2.5
X^2
1.5
Ul 1
0.5
0
, -0.5
-1,
• 1 <«Л
-
\
\
I -1.5 -
:¾
■0.5
/
ч
■o
X
— .-_.
0.5
m- .
1 1.5
Ы.
4s
2
Рис. 15.5. Минимум разрывной функции
Если в определении целевой функции g заменить if х<=о у=-х-1 на if х<0
у=-х-1, вид графика и результат поиска минимума не изменятся, хотя,
строго говоря, новая функция своего минимума не достигает, а лишь неог-
614
Глава 15
раниченно к нему приближается. Положение спасает приближенный
характер всех вычислений.
15.4. Многомерная
безусловная минимизация
Минимизации функций посвящено большое количество работ, из которых в
нашем списке приведены [51, 68]. Задача поиска минимума вещественной
функции векторного аргумента y=f(x) называется безусловной, если на ее
аргумент не наложено никаких ограничений. В противном случае, когда
вектор х должен удовлетворять каким-то уравнениям и/или неравенствам,
говорят об условной минимизации. В MATLAB имеется несколько функций,
реализующих различные подходы к безусловной минимизации.
15.4.1. Функция fminsearch
В одной из функций — fminsearch — используется так называемый
алгоритм симплексного поиска, идея которого заключается в следующем. В
окрестности стартовой точки n-мерпого пространства строится симплекс —
(п+1) точка в общем положении (никакие 3 точки не лежат на одной
прямой, никакие 4 не лежат в одной плоскости и т. д.). Целевая функция
измеряется в этих точках и та точка, в которой значение функции максимально,
отбрасывается, а вместо нее в симплекс по определенным правилам
вставляется другая точка. Процесс завершается, когда диаметр симплекса
становится меньше заданного порога. Целевая функция может быть негладкой и
даже разрывной.
Простейшая форма обращения к этой функции совпадает с ранее
приводившимися:
х = fminsearch(fun,хО)
Рассмотрим пример непрерывной, но негладкой функции двух переменных
y=fun(x)=3|xi|+|xz|, единственный минимум которой находится в начале
координат. Обращение к функции fminsearch дает следующий результат:
» [x,f] = fminsearch('3*abs(x(l))+abs(x(2))',[1;1]>
х =
1.0е-004 *
-0.1439
0.3565
f =
7.8809e-005
Нелинейные уравнения и оптимизация
615
Рассмотрим разрывную функцию двух переменных discont, единственный
минимум которой находится в начале координат:
function z=discont(x)
if (х{1) > 0) s (х(2) >= 0) % квадрант 1
z = х(1)+2*х(2);
elseif (х(1) <= 0) & (х{2) ■> 0) % квадрант 2
z = -2*х(1)+х(2);
elseif (х(1) < 0) & (х{2) <= 0) % квадрант 3
z = -х(1)-2*х(2>;
elseif (х(1) >= 0) & (х(2) < 0) % квадрант 4
z = 2*х(1)-х(2);
elseif (х(1) = 0) | (х(2) = 0) % начало координат
z = 0;
end
После обращения к функции fminsearch получены следующие результаты:
» options=optimset('Display', "off );
» х0=[0.5; 0.1];
» [x,f,e_flag] = fminsearch(@discont,x0,options)
x =
1.0e-003 *
0.0640
-0.1342
f =
2.6229e-004
e_flag =
1
Примерно такие же результаты получатся и при других значениях х0.
Рассмотрим пример 15.18.
Знаменитый банан Розенброка имеет вид:
z - 100(x2-x12)2+(l-xi)2
Графически он представляет собой овраг с очень крутыми склонами, дно
которого при "взгляде сверху" имеет форму параболы (рис. 15.6) и плавно
спускается к точке минимума х=[1;1], в которой z=o. Ее линии уровня
представляют собой изогнутые овалы (отсюда "банан"). Чтобы получить бо-
616
Глава 15
лее компактный рисунок, коэффициент 100 перед первым слагаемым
заменим более скромным значением 5:
function f = Rosenbrock(х)
f = 5*(х(2)-х(1)Л2)Л2+(1-х(1))Л2;
Рис. 15.6. Минимизация "банана"
Для поиска минимума и построения линий уровня функции Розенброка
(см. рис. 15.6) была использовапа программа progl5_5.m:
function prog!5_5
Х0=-3:0.1:3; Y0=-2:0.1:5;
[X Y]=meshgrid(X0,Y0) ;
s=size(X); Z=zeros(s);
for i = l:s(l)
for j = l:s(2)
Z(i,j) = Rosenbrock([X(i,j); Y(i,])]);
end
end
axesCXlim', [-3 3] ,'Ylim', [-2 5] ) ;
axis equal; grid off; hold on;
Нелинейные уравнения и оптимизация
617
v=l:2:10; V=10:4:20;
contour(X,Y,Z,[v VJ);
xlabel('xl'); ylabel('x2')
x0=[-2; 2];
line(xO(l),x0(2),'Marker','.','MarkerSize',10);
[x,f] = fminsearch('5*(x(2)-x{l)A2)"2+{l-x(l))^2,,xO)
line (x (1), x (2), 'Marker', ' . ', 'Marker-Size',20) ;
plot([xO(l),x(l)],[xD(2),x{2)],'k-');
colonaap copper
Найденный минимум:
X =
1.0000
1.0000
f =
1.81-61e-009
Функция fndnsearch подобно функциям решения нелинейных уравнений
может возвращать дополнительные параметры — признак завершения
работы, структуру с информацией о результатах поиска (пример 15.19).
/
\ Пример -15.19;Допрлнительнtie №араметрЯ|'Воаэращабмые*£)Аш^^1:^/.^гг!.'^
» х0=[-2;2];
» [х,f,e_flag,inform]= ...
£minsearch('5*(x(2)-x(l)л2)л2+(1-х(1))л2' ,xQ)
i
x =
1.0000
1.0000
f =
1.8161e-Q09
e_flag =
1
inform =
iterations: 61
funcCount: 115
algorithm: 'Nelder-Mead simplex direct search'
618
Глава 15
15.4.2. Функция fminunc
В том случае, когда функция fun(x) является достаточно гладкой, для
поиска ее минимума можно воспользоваться функцией fminunc. Идея поиска
минимума с помощью производных принадлежит Коши и заключается в
следующем: градиент функции fun(x) в любой точке х есть вектор д,
направленный в сторону наибольшего локального увеличения функции
fnn(x). Следовательно, для достижения минимума надо двигаться в
направлении наискорейшего спуска -д. В более развитом варианте этого алгоритма
используются также вторые производные, которые образуют так
называемую матрицу Гессе (гессиан) н. При помощи формулы Тейлора строится
локальная квадратичная аппроксимация целевой функции в окрестности
текущей точки хк:
Eun(xk+p) = fun(xk)+g}:,*p + р'*нк*р/2
Минимум выражения в правой части (если он существует) достигается при
векторе смещения р, который удовлетворяет системе уравнений нк*р=-д*.
Такой способ выбора направления называется методом Ньютона. Иногда на
вектор смещения накладывается ограничение |р|<Д при специально
подобранном Д — в этом случае говорят о методе доверительного интервала.
Большинство форм обращения к функции fminunc, в которой
реализованы оба эти метода, аналогично обращению к рассматривавшимся ранее
функциям.
В простейшем случае ее аргументами являются указатель на функцию fun и
начальная точка:
х = fminunc(8fun,x0)
Для ускорения процесса поиска в функцию fun желательно включить
формулы для вычисления градиента (это должно быть также оговорено в
управляющих параметрах options). В противном случае функция fminunc выдает
11 редупреждение:
Warning: Gradient must be provided for trust-region method; using
line-seareh method instead.
Это предупреждение не препятствует продолжению работы, т. к. градиент (и
гессиан) могут быть построены в каждой точке численно.
Рассмотрим пример 15.20.
| Пример 15.20. Поиск минимума функции ^' ~. I.Vi'w .г ■'Sx.^ss^&sSv-!
Путь имеется функция:
f = *l + *2 - 3*1Х2
Нелинейные уравнения и оптимизация -
619
Ее линия уровня при f=o представляет собой известную в геометрии кривую —
декартов лист. Подключим к профамме вычисления значения функции
операторы для нахождения градиента g и гессиана н (см. текст функции
Descartes). Сообщим об этом в списке управляющих параметров для
функций минимизации:
options=optimset('Display','final','GradObj', 'on', 'Hessian', 'on');
Значение параметра Dispiay=final означает, что все промежуточные
выдачи, кроме заключительной, блокируются. Возьмем стартовую точку для
поиска минимума хО=[2; 2]. Обращения к функции fminunc выполним в
форме, позволяющей получить на выходе также значения градиента й
гессиана.
[х,f1,e_f lag, out,grad,hes]=fminunc(@ Descartes,xO, options)
Построение линий уровня, фиксация начальной точки и найденного
минимума (рис. 15.7) выполнены с помощью программы progl5_6.ni:
function ргод15_б
axes{'Xlim',[-1.5 2.5],'Ylim',[-1.5 2.5]);
axis equal; grid off; hold on;
xlabel('xl'); ylabel('x2'); cplormap copper
X0=-1.5:0.05:2.5;
[X Y]=4tieshgrid(X0) ;
s=size(X); Z=zeros(s);
for i = l:s(l)
for j = l:s(2)
Z(i,j) = Descartes{[X(i,j>; Y(i,j)]);
end
end
V=-0.8:0.2:l; contour(X,Y,Z,V);
options = ...
optimset('Display','final','GradObj','on','Hessian', 'onM;
xO=[2; 2];
Iine(x0.(l),x0(2) , 'Marker', '.', 'MarkerSize', 10) ;
[x,fl,e_flag,out,grad,hes] = fminunc(@Descartes,xO,options)
line(x(l),x(2),'Marker','.','MarkerSize',20);
plot([xO(l),x(l)], [x0(.2),x(2)],'k-');
620
Глава 15
function [f,g,H] = Descartes(x)
f = х(1)л3+х(2)л3-3*х(1>*х(2>;
if nargout > 1
g = [ЗМх(1)л2-х(2П; 3* (х(2)л2-х(1) ) ] ;
end
if nargout > 2
H = [6*x(l) -3; -3 6*x(2)];
end
end
Рис. 15.7. Декартов лист
Результаты работы программы progl5_6.m приведены ниже:
»■ Optimization terminated successfully:
First-order optimality less than OPTIONS.TolFun, and nc negative/zero
curvature detected
x —
1.0000
1.0000
Нелинейные уравнения и оптимизация
621
fl =
-1
e_flag =
1
out =
iterations: 6
funcCount: 6
cgiterations: 5
firstorderopt: 6.9849e-010
algorithm: 'large-scale: trust-region Newton'
grad =
1.0e-0.09 *
0.6985
0.6985
hes =
6.0000 -3.0000
-3.0000 6.0000
В найденной точке (x=[i, ll) градиент близок к нулю, а гессиан —
положительно определен, что свидетельствует об успешном решении задачи.
Рассмотрим пример 15.21.
.Пример 15.21. Практическое приложение; ?>^^^\*^«^^- ^^=1¾¾¾^^^ i: ^1
Рассмотрим задачу об управлении роботом-манипулятором в упрощенной
двумерной постановке. Она формулируется так: робот представляет собой
многозвенный механизм, состоящий из нескольких стержней. Один конец
первого стержня закреплен в шарнире и может в нем поворачиваться,
остальные стержни соединены последовательно также с помощью шарниров.
На конце последнего стержня находится рабочий орган — cxeatn.
На рис. 15.8 стержни изображены в виде отрезков, шарниры в виде
кружочков, закрепленный шарнир — кружочек с треугольником, схват —
маленький квадрат. На рисунке также обозначены углы qi, q2, q3, являющиеся
обобщенными координатами манипулятора.
Введем декартову систему координат Ох\х2, начало которой совпадает с
неподвижным шарниром, ось Ох\ направлена вправо, ось Ох2 — вверх.
622
Глава 15
Рис. 15.8. Манипулятор
Координаты схвата выражаются через длины стержней и, 12, 13 и углы qi,
<q2, q3:
xj^ll^cos(ql)+12+COS(ql+q2)+13*cos(ql+q2+q3)
X2=ll*sin(ql)+12*sin(ql+q2)+13*srn(ql+q2+q3)
Вектор x=[xi,- x2] вычисляет функция coordciamp, построенная на основе
этих формул:
function x=coord_clamp(q,1)
Q=cumsum(q);
x=[sum(l. *cos (Q}) ; sum(l.*sin(Q}') ] ;
Требуемое положение схвата задается вектором хс, целью управления
является минимизация нормы разности х-хс:
function d=discrepancy(q,1,хс)
■x=coor.d_clamp (q, 1) ;
d=norm(x-xc) ;
Зададим начальный вектор углов qo, вектор длин стержней 1, требуемое
положение схвата хс и обратимся к функции fminunc:
» с0=[0.7 -1 0.5];
» 1=[5 5 5];
» хс=[12; 01;
>> [q,f l=fminimc (Sdiscrepancy,q0, [J,l,xc.)
Optimization terminated successfully:
Search direction less than 2*options.TolX
q =
0.6650 -1.576.8. 0.6036
Нелинейные уравнения и оптимизаций
623
f =
4.6500е-007
Весьма малая величина невязки f легко объяснима: для схвата достижима
любая точка плоскости, отстоящая от начала координат на расстояние, не
превышающее сумму длин стержней (в примере требуемое расстояние 12,
сумма длин 15). Начальное и конечное положения манипулятора,
представленные на рис. 15.9, получены с помощью программы progl5_7.m:
function progl5_7
axes('Xlim\ [-1 15], ' Ylim', [-1 10]);
axis equal; grid on; hold on;
1=[5 5 5]; xc=[12; 0);
qlnit=[0.7 -1 0.5];
[XInit,YInit]=hinges(qlnit,1);
plot(XInit,YInit,* k:');
qCptim=[0.8650 -1.5768 0.6036];
[XOptim,YOptim]=hinges(qOptim,1);
plot(XOptim,YOptim,'k-•,'LineWidth', 2) ;
plot (10],[-0.3],'k~\'MarkerSize',15);
plot(XInit(1:3),YInit(1:3),'ко');
plot ([XInit(1)], [YInit(4)],'ks', 'MarkerSize',15};
plot(XOptimfl:3),Y0ptim(l:3),'ко');
plot([XOptim(4)],[YOptim(4)],'ks','MarkerSize',15);
xlabel('xl'); ylabel(■x2 *);
hL=legend('Начальное','Конечное');
set(hL,'FontName', 'Courier')
title ('Два положения манипулятора','FontName','Courier');
function [X,Y]=hinges (q, 1)
Q=cumsum(q);
x=l.*cos(Q); y=l.+sin(Q_) ;
x-[0 x]; y=[0 y];
X=cumsum (x); Y=cumsurn (у) ;
Функция hinges (шарниры) вычисляет положения всех шарниров при
заданных значениях углов и длин стержней.
624
Глава 15
* - в
»V:A,£"r-""
#'&£ 6
»:i--o«iSa -
о
--■ -2
Два положения манипулятора
Начальное
Конечное
Г
—V,- тч"-- --<&=*-
■
..- —□
].
5 10 ■ 15
xi
Рис. 15.9. Начальное и оптимальное положения манипулятора
15.4.3. Функция Isqnonlin
Функция isqnonlin применяется в тех случаях, когда целевая функция
имеет вид F=Sf i2. В этом случае градиент g и гессиан н функции f выражаются
через якобиан j вектор-функции f=.[fi, f2,..., fm] ':
g=J'*f;
H=J'*J+R;
Остаточный член R включает вторые производные от F, но в окрестности
минимума им обычно пренебрегают по сравнению с j'*j. Это дает
возможность не вычислять вторые производные, что значительно ускоряет работу
по сравнению с общим случаем. Поэтому для поиска минимума целевой
функции рассматриваемого вида (сумма квадратов) нецелесообразно
использовать функцию fminunc.
Система уравнений для отыскания вектора сдвига н*р=-д при замене н на
J'*j превращается в j'*J*p=-j'*f. Этот способ называется методом Гаусса-
Ньютона.
В методе Левенберга—Марквардта матрица j'*j в левой части системы
уравнений заменяется на j1 *j+A*i, где i — единичная матрица, а X —
некоторое неотрицательное число. Для вектора смещения задается офаничение
|р|<Д, где значения Д и X взаимосвязаны.
Нелинейные уравнения и оптимизация
625
В функции lsqnonlin применяются оба метола: Гаусса—Ньютона и Левен-
берга—М ар квардта.
В обращении x=isqnoniin<fun,xO) минимизируется сумма квадратов
компонент вектора-столбца, который вырабатывает функция fun (это может
быть также матрица). Второй аргумент хО как всегда, стартовая точка для
поиска.
Рассмотрим пример 15.22.
Функция Розенброка представляет собой сумму двух квадратов, поэтому для
ее минимизации можно применить lsqnonlin. Определим функцию:
function f = Rosenbrock2(х)
f = [sqrt(5)*(x(2)-x{l)-2); l-x(l)];
Зададим начальное приближение хО и обратимся к функции lsqnonlin:
» хО =[-2; 2];
» х = lsqnonlin(GRosenbrock2,xO)
х =
1.0000
1.0000
Рассмотрим пример 15.23.
I Пример 15.23^Псевяорешение несовместной системы линейных уравнений •-
Для несовместной системы линейных уравнений а*х=ь можно поставить
задачу нахождения вектора х, дающего минимальную сумму квадратов
компонент вектора невязки г=а*х-ь. Этот вектор называют псевдорешением (в
случае совместной системы псевдорешение совпадает с обычным
решением). Рассмотрим конкретную систему:
function fr=r(x)
A=[l 1; 1 -1; 2 1];
Ь=[2;0;2];
fr=A*x-b;
Зададим начальный вектор для поиска хО и обратимся к функции
lsqnonlin:
» х0=[0;0];
» х = lsqnonlin(@г,х0)
626
Глава 15
Q.7143
.0.8571
(~ Замечание ^
Задание матрицы а и вектора Ь непосредственно внутри функции — не самое
оптимальное решение (для другой матрицы и/или вектора придется
переписывать функцию). Предпочтительно сделать эти объекты дополнительными
аргументами функции г, включив их также в обращение к lsqnpnlin. Тогда
определение функции г станет гораздо лаконичнее (и универсальнее):
function fr=r(x,A,b)
fr=A*x-b;
Конкретные матрицу а и вектор ь зададим в качестве дополнительных
входных аргументов функции lsqnonlin:
х = lsqnonlin(@r,x0, [],[], П,A,b)
Пустые матрицы [] замешают аргументы, о которых речь пойдет дальше.
("" Замечание ^
Рассмотренный пример носит чисто иллюстративный характер— искомое
псевдорешение можно получить гораздо проще, выполнив команду х=А\Ь.
Рассмотрим пример 15.24.
'i'ij'i/i.i'i^ii-it^yi
Некоторые химические процессы описываются уравнением y=a+be"c\
Неизвестные коэффициенты а, ь, с обычно определяют по экспериментальным
данным, стараясь минимизировать среднеквадратичное отклонение
теоретической кривой от наблюдаемых значений:
Z(y-<a+be-c*})2
Введем вектор р, компонентами которого являются параметры модели:
а=р(1), Ь=р(2), с=р(3)
Определим функцию expmod(p,x,y):
function q=expmod(p,x,y)
q=y-(p(l)+p(2)*exp(-p(3}*x)>;
Зададим векторы-столбцы х и у, выберем начальное приближение рО и
обратимся К функции lsqnonlin:
»х= [ 0.4; 1.4; 5.4; 19.5; 48.2; 95.9];
» у= [51.6; 53.4; 20.0; -4.2; -3.0; -4.8];
Нелинейные уравнения и оптимизация
627
» рО=[0; 0; 0]
» р = isqnoniin(@expmod, рО,[],[],[),х, у)
Maximum number of function evaluations exceeded;
increase options.MaxFunEvals
P =
■ 8.3312
9.3646
0.0711
Поместив в левую часть обращения конструкцию [р, resnorm]=..., кроме
основного результата р получим сумму квадратов разностей:
resnorm =
3:.0609е+003
Результат не слишком ободряющий, да и сплошной график на рис. 15.10
довольно далек от экспериментальных точек. Можно было бы попытаться
достичь большей точности, увеличив максимальное количество обращений
к функции (по умолчанию функция isqnoniin перестает работать, когда
количество обращений достигает 300):
» options=optimset('MaxFunEvals',600);
» [р,resnorm] = Isqnoniin(@expmod,p0, [], [J,options, x,y)
P =
6.6477
10.0967
0.0860
resnorm =
2.9463e+003
Значения коэффициентов а, ь, с получились несколько иными, но
квадратичное отклонение осталось достаточно большим. Но ведь метод isqnoniin
не сообщил, что решение найдено. Останов произошел из-за нарушения
некоторого условия (превышено количество обращений к функции). Вполне
возможно, что более серьезной причиной послужил неудачный выбор
начального приближения.
Можно ли достичь хорошего результата с помощью функции isqnoniin?
Попробуем повторно обратиться к ней, задав в качестве начального
приближения нехорошее решение:
» р0=р;
>> [р,resnorm] = Isqnonlin(@expmod,p0,[],[],[],х,у)
Maximum number of function evaluations exceeded;
increase options.MaxFunEvals
628
Глава 15
Р =
10.7401
19.6528
0.1151
resnorm =
1.8844е+003
"Решение" улучшилось, но причина прекращения итераций осталась
прежней. А что будет, если повторить попытку с новой начальной точки:
» р0=р;
» [р,resnorm] = lsqnonlin(Gexpmod,pO, [],[],[],х,у)
Optimization terminated successfully:
Relative function value changing by less than OPTIONS.TolFun
P =
-4.8524
65.2656
0.1657
resnorm =
74.0366
На этот раз оптимизация завершена успешно, да и невязка уменьшилась
почти в 30 раз. Если бы мы начинали поиск оптимума не с нулевой точки,
а, например, из точки [ю, ю, 10J, то решение было бы найдено с первой
попытки.
Для сравнения, минимум функции ехрпюаг, которая вычисляет сумму
квадратов компонентов функции expmod, был найден с помощью функции
fminsearch и совпал с приведенным выше результатом. График "хорошего"
приближения нанесен на рис. 15.10 черными точками, и он вполне
удовлетворительно аппроксимирует экспериментальные данные (рисунок получен
с помощью программы progl0_8).
function p.rogl5_8
axes('XIim\ [-20 100],'Ylim',[-10 601);
grid on; hold on;
x= [0.4; 1.4; 5.4; 19.5; 48.2; 95.9];
y= [51.6; 53.4; 20.0; -4.2; -3.0; -4.6];
plot(x,y,'ko');
.options=optimset('MaxFunEvals', 600} ;
p0=[0;0;0];
[p,resnorm] = Isqnonlin{@expmod,p0, [],[],options,x,y)
xp = -10:100; yp = p(l}+p(2)*exp(-p<3)*xp);
Нелинейные уравнения и оптимизация 629
plot(xp,ур,'к-'),-
[q,f] = fminsearch(@expmod2,p0,options,х,у)
xq = 10:2:100; yq = q(l)+q(2}*exp(-q(3)*xq);
plot(xq,yq,'k.'};
title ('Две экспоненциальные модели.','FontName','Courier')
xlabeK'x'}; ylabel('y')
hL=legend('данные','1-я модель','2-я модель', 0);
set(hL,'FontName','Courier')
function q2=expmod2(p,x,y)
q=y-(p(l)+p(2)*exp(-p(3)*x));
q2=sum(q.A2) ;
Две экспоненциальные модели'
60
50
40
30
г*
20.
10
0
"'-20 0 20 40 60 8D 100*
х
Рис. 15.10. Аналитическое приближение экспериментальных данных
Заметим, что полиномиальная аппроксимация с тремя коэффициентами
(у=ах2+Ьх+с) бьша бы гораздо хуже, а увеличивать число коэффициентов
модели при 6 наблюдениях нецелесообразно.
15.4.4. Функция fminimax
К функции lsqnonlin идейно близка функция fminimax: в обеих скалярная
целевая функция не задается непосредственно в обращении, а формируется
путем свертки из компонентов вектора (или матрицы), передаваемого функ-
L..J
I* i
Л i • 1
т*—' "
Л 1
■ * 1
' "J Ч-Т--- --
1 1
О данные
1-я модель
■ 2-я модель
j
>*
630
Глава 15
ции. В isqnoniin минимизируется сумма квадратов компонентов, а в
fminimax — максимальная составляющая (по желанию пользователя —
максимальная по абсолютной величине). Алгоритм, реализованный в fminimax,
многократно использует квадратичное программирование, а также поиск с
помощью градиента и гессиана.
Простейшая форма обращения к fminimax аналогична обращениям к
предыдущим функциям поиска минимума:
х = fminimax(fun,хО)
Рассмотрим пример 15.25.
:.'..; Л -..:......:-..:... A.^.-vS.v...-......-..: :.'. .-. ...v;.:..:;:v.i.".;K«.^S.-»^
Найдем минимум функции max(-xi,xi,-x2,x2). Для этого определим
вектор-функцию plusminus:
function f = plusminus(х)
f(1)= -x(l);
f(2)= x(l);
f(3)= x(2); ,
f(4)= -x(2);
Зададим начальную точку xo и обратимся к функции fminimax:
» xD=[l; И;
» х = fminimax(@plusminus,xO)
Optimization terminated successfully:
Search direction less than 2*options.TolX and maximum
constraint violation is less than options.TolCon
Active Constraints:
1
2
3
x =
1.0e-024 *
0
0.8272
Найденный минимум достигается в точке, очень близкой к началу
координат. Смысл последнего сообщения (Active Constraints. . .) состоит В том,
что найденная точка является пересечением трех поверхностей: f(i)=o;
f (2)=о; f (3)=о (в данном случае это плоскости). Точка принадлежит и
четвертой плоскости f (4)=0, но в трехмерном пространстве для идентифика-
Нелинейные уравнения и оптимизация
631
ции точки достаточно трех поверхностей, и программа выбирает первые
попавшиеся.
С помощью функции fminimax можно построить так называемую
равномерную или чебышевскую аппроксимацию табличных данных.
Напомним, что если на числовой оси заданы точки xi<x2<... <хп и значения
yi, у2, ..., уг, где каждое ух — вещественное число, соответствующее точке хь
то задача одномерной аппроксимации состоит в том, чтобы построить просто
вычисляемую функцию y=f (х,а), аппроксимирующую эти данные. Здесь а —
один или несколько параметров, выделяющих конкретную функцию в
некотором классе (например, вектор коэффициентов полинома). Эти параметры
выбираются так, чтобы минимизировать разницу между заданными
значениями ys и вычисленными при помощи функции y=f (xifa). Известны два
основных подхода к построению модели — метод наименьших квадратов (см.
разд. 13.1) и равномерная аппроксимация. В первом случае ищется минимум
2(yi-f (xifa) )2, ВО ВТОРОМ — МИНИМУМ велИЧИНЫ max |yi-f(xi, а) |.
Рассмотрим пример 15.26.
['ДЗ§|йШ|ЙШ^Ж аппроксимация
ПреДПОЛОЖИМ, есть Табличные данные х=[-2;-1;0;1;2], у=[0;0;1;0;0].
В гл. 13 (см. пример 13.2) с помощью функции polyf it был построен
полином степени 2, наилучшим образом приближающий эти данные в смысле
наименьших квадратов. Его коэффициенты р= [-0.1429 о.оооо 0.48571.
Построим теперь полином той же степени, дающий равномерную
аппроксимацию этих данных. Определим функцию, основным аргументом которой
яапяется неизвестный вектор коэффициентов с, а данные х, у —
дополнительными аргументами.
function u=unifonrt(с,х,у)
и=аЬз<у-(с(1)*хЛ2+с(2)*х+с(3})));
Зададим начальный вектор со и обратимся к функции fminmax (пустые
операнды в этом обращении заменяют аргументы, о которых речь пойдет в
разд. 15.5):
» х=[-2;-1;0;1;2];
» у=[0;0;1;0;01;
» сО = [0;0;0];
» с = fminimax (^uniform, сО, [], [] Д], [] Д] Д] ДЬ П,х,у)
Active Constraints:
1
2
3
4
21 Зак.899
....:.:.4>j~».w..w....-..."...:..........r
632
Глава 15
с -
-0.2500
-0.0000
0.6250
По этим коэффициентам был с помощью программы progl5_9.m построен
график полинома, равномерно приближающего данные (рис. 15.11).
'." 1-5
1
- С0*
0
>г
-.1
-1.5
■
-2.
-.■ '■"' '"
•
•
ш
т
*
*
Л
3 . .
jr *
*
•
ш
-2
Дв& полиномиальные
О
"•••.
J&-
модели •■'itis-^.-- ■■■■■■■
О данные
мин.квадраты
• равномерная
i&'^r'
-¾¾ Щ*;
• ° ° *>^ Щ.
• ^ " -**"""
■ Л
•
• Г-
*
^
-1 о' 1 '■.,:•, 2 ,-.-. з
Рис. 15.11. Полиномиальная аппроксимация
Для сравнения на том же рисунке приведен график полинома, полученного
по методу наименьших квадратов.
function ргод15_9
axes('Xlira', [-3 3],'Ylira',[-2 1.5]};
hold on;
x=[-2;-l;0;l;2];
y=[0;0;l;0;0];
c0=[0;0;0];
[c, f,maxf, e_f lag, inform] = ...
fminimax(@unifonn,cO, [],[|,[],I1i[)f[]i[], П,х,у)
p=polyfit(x,y,2)
xx = -3:0.1:3;
plot(x,y,'ko',xx,polyval(p,xx),'k-',xx,polyval(c,xx),'k.'}
Нелинейные уравнения и оптимизация
633
title('Две полиномиальные модели','FontName','Courier')
xlabel('x'); ylabel('y')
hL=legend('данные','мин. квадраты','равномерная', 0) ;
set(hL,'FontName','Courier'}
Выполнение функции progl5_9.m помимо вывода графиков, приведенных
на рис. 15.11, сопровождается следующими результатами:
» ргод15_9
Optimization terminated successfully:
Search direction less than 2*options.TolX and
maximum constraint violation is less than options.To1Con
Active Constraints:
1
2
3
4
с =
-0.2500
-0.0000
0.6250
f =
0.3750
0.3750
0.3750
0.3750
0.3750
maxf =
0.3750
e_flag =
1
inform =
iterations: 4
funcCount: 29
stepsize: 1
algorithm: 'minimax SQP, Quasi-Newton, line_search'
f irstorderopt: []
cgiterations: []
P ~
-0,1429 0.0000 0.4857
634
Глава 15
При обращении к функции fminimax можно задать управляющий параметр
MinAbsMax, который заменяет компоненты вектора-функции их
абсолютными величинами (однако при выводе значений компонентов их знаки
сохраняются). В предыдущем примере за счет этого управляющего параметра
можно было бы опустить abs в определении функции uniform.
Рассмотрим трехкомпонентную вектор-функцию одной переменной
(пример 15.27).
."■"■ ■■■■■"".?'■" -.-v.".. .• • ...v . .............,^.
:;Яример 15.27. Поиск минимума максимальной компоненты вектора-функции ,., \
function f=threefun(t)
f (1,: )=-1.5*t,-
f(2, :)=2*t-t.-2;
f(3,:>=t-6;
С помощью fminimax найдем минимум максимальной из ее компонент и
представим на графике (рис. 15.12) полученные результаты.
function progl5_10
tt=-3:0.1:4,- f f=threef un (t £) ;
hold on; grid off;
title('fminimax без MinAbsMax','ForitName','Courier')
xlabeK't'}; ylabel('f ),-
plot(tt,ff(1,:),'k:');
plot(tt,ff(2,:),'k:');
plOt(tt,ff(3,:),'k:');
mf=zeros(size(tt));
for i=l: length(tt)
ft =threefun(tt(i));
mf(i)=max([ft(l,:), ft(2,:), ft(3,:)]);
end
plot(tt,mf,'k-'};
graf(-l);
graf(3.5),-
function f=threefun(t)
f (1,:)=-1.5*t;
f (2,:}=2*t-t.~2;
f{3,:)=t-6;
Нелинейные уравнения и оптимизация
635
function giraf(tO)
options - [];
line(tO,0, 'Marker', '.', 'MarkerSize', 10);
[t,fval,maxfval] = ...
fminimax(Gthree£un,tO,[], [J, [], [], [], [], [], options)
line(t,maxfval,'Marker','.','MarkerSize', 20);
plot ([tO t], [0 maxfval],'k-');
function f=threefun(t)
f(l,:)=-1.5*t;
f(2,:}=2*t-t.A2;
f (3,:) =t-6;
% Решение для t0=-l
Active Constraints:
1
2
t = % найденный минимум
4.5174e-017
fval = % значения компонентов функции в найденной точке
-0.0000
0.0000
-6.0000
maxfval =
-б.7761е-017
S Решение для t0=3.5
Active Constraints:
2
3
t- = % найденный минимум
3.0000
fval = % значения компонентов функции в найденной точке
-4.5000
-3.0000.
-3.0000
irtaxfval =
-3.0000
636
Глава 15
Рис. 15.12. Минимум максимальной компоненты
Рассмотрим пример 15.28.
^Пример ;Щ ' >-А'" • н*
Продемонстрируем влияние свойства MinAbsMax на результат работы функции
fminir.ax. Для этого в программе progl5_10 подменим значение параметра
options. Значением управляющего параметра MinAbsMax является количество
составляющих вектора-функции, заменяемых абсолютными величинами:
options = optimset('MinAbsMax',3}
Дополнительно придется воспользоваться модулями составляющих функции
threefun при обращении к функции plot:
plot(tt,abs(ff(1,:}), 'k:'};
plot(tt,abs(ff(2, :)), 'k: '};
plot(tt,abs(ff(3, :}), 'k:") ;
Результат работы модифицированной таким образом функции minmaxtstl
представлен на рис. 15.13.
В этом варианте для обеих начальных точек to=-i и to=3.5 функция
fminmax возвращает одну и ту же точку, в которой достигается минимум:
Active Constraints:
2
3
Нелинейные уравнения и оптимизация
637
t = % найденный минимум
2.4000
fval = % значения компонент функции в найденной точке
-3.6000
-0.9600
-3.6000
maxfval =
3.6000
Рис.15.13. Минимизация модулей функции
15.5. Условная минимизация
Если при поиске минимума вещественной функции векторного аргумента
y=f (х) на аргумент наложены те или иные ограничения в виде уравнений
и/или неравенств, говорят об условной минимизации. Основной метод
решения таких задач основан на использовании множителей Лагранжа. Каждое
неравенство вида д(х)<о превращается в уравнение g(x)+v2=o (слагаемое v2
заведомо нео'фицательно). Затем левая часть каждого уравнения добавляется
к целевой функции с некоторым множителем, эти множители и величины v
включаются в число переменных. Для модифицированной таким образом
функции решается задача безусловной минимизации.
638
Глава 15
15.5.1. Функция fmincon
Для решения задачи условной минимизации функции fun(x) при наличии
линейных ограничений оптимизации а*х<Ь (а — матрица, ь — вектор)
используется функция fmincon, обращение к которой требует задания
начальной точки хо:
х = fmincon)fun,хО,А,Ь)
Функция fmincon допускает наложение дополнительных ограничений вида:
П Aeq*x=bsq — линейные уравнения (Aeq — матрица, beq — вектор);
□ ib<x<ub — ограничения на координаты (lb, ub — два вектора).
И тогда простейшие варианты обращения к fmincon выглядят следующим
образом:
х = fmincon(fun,хО,A,b,Aeq, beq)
х = fmincon(fun,хО,A,b,Aeq,beq,lb,ub)
Еще одно нелинейное условие может быть задано с помощью двухкомпо-
нентной функции [c,ceq]=nonlcon(x), для которой искомая точка
минимума должна удовлетворять двум ограничениям: с(х)<о и ceq(x)=o. В этом
случае к списку входных параметров добавляется указатель на функцию
nonlcon:
х = fmincon(fun,хО,A,b,Aeq,beq,lb,ub,nonlcon)
Если какой-то из перечисленных выше входных параметров не используется,
вместо него задается пустой аргумент ([]). Если отсутствуют ограничения на
отдельные компоненты x(i) сверху или снизу, то соответствующие
компоненты векторов ub и ib задаются как +°° (ub(i)=inf) или -» (ib(i)=-inf).
Рассмотрим пример 15.29.
[Пример 15.29. Минимум функции Розенброка в полуплоскости "
Найдем минимум функции Розенброка при ограничении x-l-x2+4<o,
задающем полуплоскость.
Определим матрицу а=[1 -1], вектор ь=[-4], начальную точку х0= [-3,-4]
(эта точка удовлетворяет ограничению) и обратимся к функции fmincon:
» А=[1 -1] ;
» Ь=[-4];
» х0=[-а,-4];
» х = fmincon('5*(x(2}-x{l)A2)'-2h(l-x(l))^2,rxO,A,b)
Нелинейные уравнения и оптимизация
639
Active Constraints:
1
х =
2.5431
6.5431
При более полной форме обращения [x,fvai]=fmincon(...) можно
получить значение целевой функции в найденной точке:
fval =
2.4098
Для другой начальной точки х0=[0;1] (эта точка не удовлетворяет
ограничению) получим fvai=6.484i. в точке х= [-1.5311 -2.4 689]. Графические
результаты двух этих попыток представлены на. рис. 15.14. Они получены с
помощью, программы ros_tst.m:
function ros_tst
Х0=-5:0.1:3;
Y0=0:0.1:7;
[X Y]=meshgrid(X0,Y0);
s=size(X); Z=zeros(s);
for i = 1:S(1)
for j = l:s(2)
x = [X(i,j); Y(i,j)];
z = Rosenbrock(x);
Z(i,j) = z;
"end
end
V=l: 10;
contour(X,Y,Z,V);
hold on; grid off;
xl=-5:5; x2=0:7;
xlabel('xl'); ylabel(.'x2')
plot ([-4 3], [0 7], "k-'l;
x0=[-3; 4]; graf(xO) %#1
x0=[ 0; 1]; graftx0} %#2
function graf(xO)
A=L1 -1); b=[-4'J;
options=[];
640
Глава 15
line(xOd),х0(2), 'Marker', '.', 'MarkerSize', 10};
[x, fval] = fmincon(@Rosenbrock,xO,A,b)
line(x(lj,x(2), 'Marker', '.', 'MarkerSize', 20);
plot([xO(l),x(l}], [x0(2},x(2)],'k-');
function f = Rosenbrock(x)
f = 5*(х(2)-х(1)л2)л2+(1- х(1))л2;х(1}}л2;
Рис. 15.14. Минимум функции Розенброка
Рассмотрим пример 15.30.
(Пример 15.30. Минимум функции Розенброка внутри единичного круга 1\ -*А-? \ ;
Найдем минимум функции Розенброка при ограничении (xi-i)2+(x2-
-1)2<1, задающем внутренность единичного круга с центром в точке (1, д.).
Определим функцию circleli:
function [с, ceq] = circleli(х)
с = (х(1)-1)Л2+(х(2)-1)Л2-1;
ceq = [],-
Нелинейные уравнения и оптимизация
641
Зададим х0=[2;1] и обратимся к функции fmincon:
х = йш.псоп{'5*(х(2)-х(1)л2)л2+(1-х(1))л2■,...
хО, [],[], [],[], n,[],Gcirclell)
No Active Constraints
x =
0.9963
0.9926
Сообщение "No Active constraints" означает, что найденная точка не
удовлетворяет ограничению, как равенству.
При более полной форме обращения [х, fval]=fmincon.(...) функция
возвратит значение целевой функции в найденной точке:
fval =
1.4019е-005
Точное значение минимума равно нулю.
Более полная форма обращения к функции fmincon позволяет передавать
минимизируемой функции fun и функции ограничений nonicon кроме
аргумента х список дополнительных параметров pi, Р2, ...:
x=fmincon(fun,xO,A,b,Aeq,beq>ib,ub,nonicon,options,El,P2,...)
Ускорение вычислительного процесса может быть достигнуто заданием
формул вычисления градиента и/или гессиана (пример 15.31).
|;,П|^ё^5.31^щи!1^^^.градиента и гессиана^ /-,,^ ^:^¾¾¾¾¾^¾¾^¾¾¾¾
Дополним функцию Розенброка вычислением градиента g и гессиана н:
function [f,g,H] = Rosenbrock(х)
f = 5Мх(2)-х(1)Л2}Л2+(1-х(1})Л2;
if nargout > 1
g= [-20*(x(2)-x(l)*-2}*x(l)-2*(l-x(l)); 10* (x(2)-x(l) "2) ] ;
end
if nargout > 2
H= [20*(3*x(l)-x(2})+2 -20*x(l); -20*x(l) 10];
end
Зададим x0= [-2,-2] и выполним команды:
» options = ...
optimset("Display','final','GradQbj','on','Hessian','on■),
642
Глава 15
» к = fmincon(GRosenbrock,хО, [], [], [], [], [], [], dcirclell,Options)
No Active Constraints,
x =
1.0000
i.oooo
Наиболее полный список выходных параметров, возвращаемых функцией
fmincon, представлен в следующем обращении:
[х,fval,e_flag,inform,lambda,grad,hes] = fmincon(...}
Кроме ранее упоминавшихся выходных аргументов здесь добавилась
структура lambda, содержащая множители Лагранжа.
Попытка выполнить последнее обращение к функции fmincon в наиболее
полной форме приводит к выводу довольно большого объема полезной
информации:
» [х,fval,e_flag,inform,lambda,grad,hes]=...
fmincon(@Rosenbrock,xO,[],[],[],[],[],[],@circlell,options)
fval = % значение целевой функции в найденной точке
6.8910е-010
e_flag = % поиск завершен успешно
1
inform =
iterations: 13
funcCount: 62
stepsize: 1
algorithm: 'medium-scale: SQP, Quasi-Newton, line-search'
lambda =
% информация о множителях Лагранжа; в данном случае она пустая,
% поскольку найденная точка не удовлетворяет ограничению
% как равенству
lower: [2x1 double]
upper: [2x1 double]
eqlin: [1x0 double]
eqnonlin: [1x0 double]
ineqlin: [1x0 double]
ineqnonlin: 0
grad = % градиент
1.0e-003 *
Нелинейные уравнения и оптимизация
643
0.2121
0.6299
hes = % гессиан
43.3203 -20.4714
-20.4714 10.1446
Видим, что действительно найден минимум, т. к. компоненты градиента
достаточно малы, а гессиан — положительно определенная матрица, в чем
можно убедиться с помощью критерия Сильвестра:
43.3203 > 0,
det(hes) = 20.3891 > 0.
Рассмотрим пример 15.32.
[ Пример 15.32. Другой вариант задачи управления роботом £Щз&>шvj
а'. -— .' - ^ .-. .". "... I.....'. ;,...J.....;.;„. .vj.....f
В примере 15.21 рассматривалась задача об управлении
роботом-манипулятором в двумерной постановке. Выяснилось, что решать ее как задачу
минимизации невязки, т. е. расстояния между требуемым и фактическим
положением рабочего органа манипулятора (схвата), совпадающего с концом
последнего стержня, не имеет большого смысла: для любой достижимой
точки невязка получается практически равной нулю, а из бесконечного
множества возможных решений, т. е. углов поворота стержней (при их
числе больше 2) выбор делается, по существу, случайно. Рассмотрим эту задачу
в несколько иной постановке.
Попадание схвата в нужную точку будем рассматривать как нелинейное
ограничение, вырабатываемое функцией hitting (о списке входных
параметров см. ниже). Функцию hitting определим так, чтобы кроме самого
ограничения она вырабатывала его градиент:
function [c,ceq,GC,GCeq)=hitting(q., I,xc,q0)
Q=cumsum(q) ;
x=[sum(.l.*cos (Q) ) ; sum(l.*sin(Q) } ] ;
c=[];
ceq=0.5*sum((x-xc).Л2) ;
if nargout > 2
GOU;
xql=[-x(2);x(l)];
xq2=[-sum(1(2:3).*sin(Q<2:3)));sum(1(2:3).*cos(Q(2:3)))];
xq3=l(3)*[-sin(Q(3));cos(Q(3))];
GCeq=[s.um( (x-xc) . *xql) ;suni( (x-xc) -*xq2) ;sum( (x-xc) .*xq3) ] ;
end
644
Глава 15
Кроме нелинейного ограничения ceq=o зададим также простые ограничения
на углы q, каждый из которых не должен выходить из диапазона [~п,п].
Для этого определим ub=pi*ones (1,3), ib=-ub.
Целевую функцию построим, исходя из условия наименьших шевелений
стержней: взвешенная сумма квадратов разностей начальных углов (вектор qo)
и получающихся (вектор q) должна быть минимальной. В качестве весов
возьмем сумму длин стержней, которые перемещаются при изменении
каждого из углов: для первого угла это сумма всех длин, для второго угла — сумма
всех длин, кроме первой и т. д. Эта идея воплощена в функции stir (о списке
входных параметров см. ниже). Функцию stir определим так, чтобы кроме
значения самой целевой функции она вырабатывала также ее градиент.
function [s,g]=stir(q,l,xc,qO)
L=cumsum(fliplr(lj);
L=fliplr(L);
s=0.5*sum(L.*(q-qO)."2) ;
if nargout > 1
g=L.*(q-qO);
end
В каждой из двух функций hitting и stir, задействованных в решении
задачи о манипуляторе, содержательно имеется свой список входных
параметров, реально используемых в теле соответствующей функции. Однако
список дополнительных параметров функции fminco.n должен быть
сформирован как единый — этим и объясняется появление лишних входных
параметров: qO В hitting И хс В stir.
Данные возьмем те же, которые были использованы в примере 15.21:
□ начальные углы qO=L0.7 -1 о.5];
О длины стержней 1=[5 5 5];
П требуемое положение схвата хс=[ 12,- 0].
Зададим условия:
» options = optimset('Display','final', ...
'GradObj ', 'on', 'GradConsttr', 'on');
После чего обратимся к функции fmincon:
» [q, fval]=fmincon(@stir,qO, [] ЛЬ (L П ,lb,ub, . . .
Shitting, options:, l,xc,q0)
q =
0.944.6
-1.4801
0.-2308
Нелинейные уравнения и оптимизация
645
fval =
1.7826
Напомним, что fval — взвешенная сумма квадратов изменений углов и она
не может быть очень малой, коль скоро полученное значение q заметно
отличается от начального qo. Чтобы понять, насколько точным получилось
попадание схвата в заданную точку, обратимся к функции hitting:
» [c,ceq,GC,GCeql = hitting(q,l,xc,qO)
Получим значение самой функции ceq=i.i4 8le-ou и ее градиента
GCeq=i.0e-004*[0.0946 0.2630 0.1085]. Видим, что попадание схвата в
заданную точку (условие ceq=o) выполнилось весьма точно, градиент также
достаточно мал.
Для сравнения рассмотрим еще одно положение манипулятора, при
котором схват находится в заданной точке: стержни (их длины равны 5)
представляют собой две боковые стороны и малое основание равнобочной
трапеции. Большое основание трапеции — отрезок от неподвижного шарнира
до заданной точки (его длина равна 12). Проекция боковой стороны на
большое основание равна (12-5)/2=3.5, острый угол при основании
трапеции a=acos(3.5/5)=0.7954.
Зададим вектор углов q=[a -а -а], а значения всех остальных параметров
сохраним прежние. Выполнив команду [c,ceq,GC,GCeq]=hitting(q, l,xc,q.0),
получим ceq=o, GCeq=[0 0 0] (абсолютно точное попадание схвата в
заданную ТОЧКу). ВЫПОЛНИВ Команду [s,g]=stir(q, l,xc,qO), ПОЛуЧИМ S=4.4727,
что в 2,5 раза больше, чем минимальное значение, найденное функцией
fmincon. С помощью программы progl5_ll.m проведены указанные
вычисления, а их результаты графически отражены на рис. 15.15.
function ргод15_11
axesCXlim', [-1 15],'Ylim',[-1 10]);
axis equal; grid off; hold on;
1=[5 5 5]; xc=[12; 0];
qlnit=[0.7 -1 0.5];
[XInit,YInit]=hinges(qlnit,1);
plot(XInit,YInit,'k:\ 'LineWidth',2);
a=acbs(0.7); qTrapz=[a -a -a];
[XTrapz,YTrapz]=hinges(qTrapz,1);
plot(XTrapz,YTrapz,'k—','LineWidth',2);
options=optimset('Display','final', ...
'GradObj','on', *GradConstr','on *);
ub=pi * ones(1,3); lb=-ub;
[qOptim,fval]=fraincon(@stir,qlnit, [],[],[],[], lb,ub,Shitting,...
options, 1, xc, qlnit);
646
Глава 15
[XOptim,YOptim]^hinges(qOptim,1);
plot(XOptim,YOptim,'k-','LineWidth', 2) ;
plot([0], [-0.3], 'к'4', 'MarkerSize',15);
plot(XInit(l:3},YInit(l:3),'ко');
plot([XInit(4}],[YInit(4}],'ks','MarkerSize',15);
plot(XTrapz(1:3),YTrapz(l:3),'ко');
plot([XTrapz(4)],[YTrapz(4>],'ks','MarkerSize', 15);
plot(XOptim(1:3),YOptim(1:3),'ко');
plot([XOptiin(4}], [YOptim{4)], ' ks', 'MarkerSize*, 15) ;
xlabel('xl'); ylabel('x2'>;
hL=legend( 'Начальное-', 'Трапеция', 'Оптимальное') ;
set(hL,'FontName','Courier')
title ('Три положения манипулятора','FontName",'Courier');
8
6
4
« 2
0
-2
-4
Три положения манипулятора
■ "" ' ■■"" "
*
— Начальное
— Трапеция
Оптимальное
• J^^x а
/' ^*"""--»»_\.
A ^¾
-
0 5 10
XI
1
jPf **ч V*
15
Рис. 15.15. Положения манипулятора
15.5.2. Функции Isqnoniin и fminimax
При использовании функций isqnoniin и fminimax, в которых целевая
функция является сверткой вектора, также можно задавать ограничения.
Для функции isqnoniin доступны только простейшие ограничения типа
ib<x<ub. Обращение к; функции isqnoniin в этом случае имеет вид
х = isqnoniin(fun,хО,lb,ub,options,P1,P2,... )
Нелинейные уравнения и оптимизация
647
Рассмотрим пример 15.33.
I Пример 15.33. Дополнительные параметры функции lsqnoniin {'■' .
В примере 15.22 минимум функции отыскивался с помощью функции
lsqnoniin. Для этого была определена функция Rosenforock2(x), которая
вычисляет компоненты вектора, сумма квадратов которых задает функцию
Розенброка.
Введем ограничения xi<o, х2>о:
lb=[-Inf; 0]
ub=[0; Inf]
Из стартовой точки х0=[-2;2] функция lsqnoniin находит следующий
приближенный результат (точным решением является точка [о; о]):
» х = lsqnoniin(@Roseribrock2,хО,ib,ub}
х =
1.0е-004*
-0.0000
0.7727
Функция lsqnoniin может возвратить довольно много выходных параметров:
[х,resnorm,residual,e_flag,inform,lambda,jacofoian] =lsqnonlin(...)
Кроме ранее встречавшихся выходных аргументов здесь представлены:
П resnorm — значение целевой функции в найденной точке: sum (fun (х) .Л2);
О residual — компоненты функции fun(x) в найденной точке;
П jacobian — якобиан функции fun в найденной точке.
Обращение к функции fminimax мало чем отличается от вызова функции
fmincon:
x=fminimax(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options,PI, P2,...)
Рассмотрим пример 15.34.
I, Пример 15.34. Поиск минимума функции max
Найдем минимум функции max(-xi,xi,-x2,x2> из примера 15.25 вне
цилиндра с радиусом 1, т. е. с дополнительным ограничением xj + xij > i. Для
обращения к fmincon там был определен вектор-функция piusminus. Определим
648
Глава 15
теперь функцию, задающую ограничение-неравенство (ограничение-равенство,
которое здесь не используется, представлено пустым массивом []).
function [с, ceq] = circle(х)
с = 1-(х(1)Л2+х(2)Л2);
ceq = [];
Зададим стартовую точку х0= [1; 1] и обратимся к функции fminimax:
» х = fminimax(Gplusminus,хО,[],[],[],[],[],[],@circle)
Active Constraints:
1
3
4
x =
0.7071
0.7071
Функция fminimax может возвратить довольно много выходных аргументов,
значения которых позволяют уточнить информацию о найденном решении:
[х,fval,maxfval,exitflag,output,lambda] = fminimax(...)
Выполним последнее обращение к функции fminimax в наиболее полной
форме:
» [х,fval,maxfval,e_flag,inform,lambda] = ...
fminimax(@plusminus,xO, [], [], [], [], [], [] ,Gcircle)
Active- Constraints:
1 •
3
4
x =
.0.7071
0.7071
fval =
-0.7071
0.7071
"0.7071
-0.7071
maxfval =
0.7071
Нелинейные уравнения и оптимизация
649
e_flag =
1
inform =
iterations: 6
funcCount: 31
stepsize: 1
algorithm: 'minimax SQP, Quasi-Newton, line_search'
lambda =
lower: [2x1 double]
upper: [2x1 double)
eqlin: [Oxl double]
eqnonlin: [0x1 double]
ineqlin: [0x1 double]
ineqnonlin: 0.3536
15.6. Управление
итерационными процессами
Все функции оптимизации и решения нелинейных уравнений, описанные в
этой главе, включают в списке своих входных параметров перечень свойств,
влияющих на ход итерационных процессов. Эти свойства представлены
структурой options, поля которой формируются с помощью функции
optimset. Задание значения любого свойства производится парой
параметров функции optimset, первый из которых представляет наименование
свойства, а второй — его значение:
options = optimset('Свойство_1',Значение_1,'Свойство_2',Значение_2,...);
х = fxxx(fun,xO,...,options)
х = fxxx(fun,x0,..., options,PI,P2,...}
Перед входным параметром options может располагаться некоторое
количество входных параметров, перечень которых для каждой функции
оптимизации индивидуален. Параметры pi, Р2, ..., располагаемые вслед за
структурой options, передаются оптимизируемой функции вместе с независимым
аргументом х — fun(x,pi,Р2,...).
Список большинства параметров, управляющих процессами поиска
решений нелинейных уравнений или нахождения минимума функций, приведен
в табл. 15.3.
650
Глава 15
Таблица 15.3
Параметр
Назначение
Значение по
умолчанию
Diagnostics
DiffMaxChange
DiffMinChange
Display
GradC'onstr
GradObi
Hessian
HessMult
Jacobian
JacobMult
LargeScale-
LievenbergMarquardt
MaxFunEvals
Вывод диагностической информации off
о функции fun (од | off)
Максимальный шаг no переменной для le-1
вычисления конечных разностей
Минимальный шаг по переменной для 1е-8
вычисления конечных разностей
Режим отображения информации о
шагах итерационного процесса:
• off — вывод отключен;
• iter — вывод на каждой итерации;
• notify — вывод в случае
необходимости;
• final—финальный вывод
Определен ли пользователем градиент off
для нелинейных ограничений (on | off)
Определен ли пользователем градиент off
для обрабатываемой функции (on I off)
Определен ли пользователем гессиан off
для обрабатываемой функции (on | off)
Определена ли пользователем функция 11
умножения на гессиан (указатель I [ ])
Определен ли пользователем якобиан off
для обрабатываемой функции (on | off)
Определена ли пользователем функция П
умножения на якобиан (указатель | [ ])
Использовать ли алгоритм on
large-scale, если это возможно
(on | off)
Заменить ли алгоритм
Гаусса—Ньютона на алгоритм Левенберга—Марквардта
(on | off)
Максимальное количество обращений к
функции fun
Maxlter
Максимальное количество итераций
Нелинейные уравнения и оптимизация
651
Таблица 15.3 (окончание)
Параметр Назначение Значение по
умолчанию
MaxPCGlter Максимальное количество итераций в
методе сопряженных градиентов (pcg)
MinAbsMax Количество компонентов вектора- О
функции для минимизации абсолютных
значений
TolCon Прекращение итераций при нарушении
ограничений
То!Fun Прекращение итераций при достижении
точности по значению-функции
TdlPCG Прекращение итераций для алгоритма PCG 0.1
То1Х: Прекращение итераций при достижении 1е-б
минимального шага по X
Глава 16
Математическое
программирование
Решение задачи безусловной или условной минимизации, вообще говоря,
зависит от стартовой точки. Получить все минимумы (равно как и все
решения нелинейного уравнения или системы уравнений) можно либо путем
теоретического анализа (асимптотическое поведение функции и т. п.), либо
(не всегда с полной уверенностью) путем использования большого
количества стартовых точек. Один из авторов был свидетелем того, как его коллега
искал минимум функции 6 переменных, заданной алгоритмом ее
вычисления. Задача решалась не в среде MATLAB (его тогда не было), но с
помощью примерно тех же самых алгоритмов. Многочисленные стартовые точки
давали решения со значением целевом функции порядка Ю-3. Между тем из
общих соображений было достоверно известно, что истинный минимум
целевой функции имеет порядок 10~6, т. е. примерно в 1000 раз меньше!
Однако есть класс задач условной минимизации, называемых задачами
математического программирования, в которых точка минимума либо
единственна, либо множество этих точек легко обозримо.
Под задачами математического программирования обычно понимают задачи
поиска минимума линейной или квадратичной функции в многогранном
множестве. Эти задачи называются соответственно задачами линейного и
квадратичного программирования.
16.1. Линейное программирование
Для решения задачи линейного программирования в MATLAB используется
функция linprog. Область поиска для нее задается следующими условиями:
П а*х<=ь — линейные неравенства (а — матрица, ь — вектор);
П Aeq*x=beq — линейные уравнения (&eq — матрица, beq — вектор);
□ ib<=x<=ub — ограничения на координаты (lb, ub — два вектора).
Целевая функция f ■ *х в linprog задается вектором коэффициентов f.
654
Глава 16
Формы обращения к этой функции:
х = linprog (f, A,.b,Aeq,bsq)
х = linprog (f. A,b,Aeq, beq, lb, ub)
x = linprogff,A,b,Aeq,beq,lb,ub,xO}
x = linprog(f,A,b,Aeq,beq,lb,ub,xO,options)
[x,fval] = linprog(...)
[x,fval,exitflag] = linprog(...)
[x,fval,exitflag,output] = linprog(...)
[x,fval,exitflag,output,lambda] = linprog(...)
Семантика входных и выходных параметров очевидна. Единственное
необходимое пояснение касается стартовом точки хо. В большинстве случаев она
не нужна (а если все же задана, то игнорируется).
В функции linprog по умолчанию используется так называемый прямо-
двойственный алгоритм, при использовании которого одновременно
решается как данная задача, так и двойственная к ней (см. ниже). Впрочем,
решение двойственной задачи не выдается. Если для свойства Largescale
установлено значение off, будет использоваться хорошо известный симплекс-
метод линейного программирования, для которого нужна стартовая точка
хО. Однако если стартовая точка не задана, она выбирается автоматически.
Рассмотрим примеры 16.1 и 16.2.
I Пример 16.1. Задача максимизации дохода ? ' ]
Рассмотрим условное производство столов и стульев. Сведения о затратах
ресурсов на единицу продукции, их наличии и о доходе от производимой
продукции отражены в табл. 16.1.
Таблица 16.1
Наименование ресурса
Древесина (кг/ шт.)
Кожа (м2/ шт.)
Клей (г/ шт.)
Труд, затраты (чел-час/ шт.)
Доход (руб./ шт.)
Продукция
Стул
5
0.5
100
10
10
Стол
25
-
250
10
20
Ограничения
по ресурсу
500
15
7500
400
Математическое программирование
655
Задача производственного планирования заключается в том, чтобы
составить план выпуска стульев и столов, обеспеченный имеющимися ресурсами
и дающий максимально возможный доход. Ее математической моделью
является-задача линейного программирования (ЗЛП) в стандартной форме —
найти х.1 и Х2 такие, что функция f (х)=10x1+20x3 достигает максимума при
следующих ограничениях:
5хг + 25X2 S 500
0.5xi < 15
lOOxi + 250х2 < 7500
10xi + Юх2 < 400
xi > 0, х2 > 0
Для обращения к функции linprog подготовим входную информацию:
П вектор коэффициентов целевой функции f=flO; 20];
П матрицу коэффициентов системы линейных неравенств а=[5 25;
0.5 0;:100 250;10 10J;
О вектор свободных членов системы линейных неравенств ь=[50.0; 15;
7500; 400];
П вектор нижних границ для переменных ib=zeros (2,1).
Функция linprog ищет минимум, а в постановке задачи идет речь о
максимуме, поэтому необходимо либо сменить знак коэффициентов целевой
функции f, либо поставить знак минус перед именем этого вектора:
[x,fval] = linprog{-f,А,Ь, [], [],ib)
Получим следующие результаты:
х = [25 15]
fval = -550"
Таким образом, найден оптимальный план мебельного производства: надо
выпустить 25 стульев и 15 столов, при этом получится доход 550 руб. План
получился целочисленным, однако в общем случае решение может оказаться
и вещественным. Если целочисленность решения — обязательное
требование, его пало включать в постановку задачи, однако в MATLAB пет
специальных функций для решения общей задачи целочисленного линейного
программирования.
Для любой ЗЛП можно сформулировать так называемую двойственную
задачу. Пусть в исходной задаче требуется найти максимум f'*x при а*х<ь и
о<х. Тогда в двойственной задаче требуется найти минимум Ь' *у при a' *y>f
И 0<у.
656
Глава 16
Сформулируем задачу, двойственную к рассмотренной в примере 16.1.
Чтобы привести неравенство к требуемому виду, умножим его на -1, получим
-A'*y<-f. Необходимо также скорректировать вектор нижних границ:
lb = zeros(4,1)
Обращение к функции linprog теперь имеет такой вид:
[y,gval] = linprog (b,-A',-f, [], [], lb)
Получим следующие результаты:
у =[0.50 0.00 0.00 0.75]
gval = 550.0000
Видим, что значения целевых функций совпадают (если учесть
искусственно внесенный минус в целевой функции прямой задачи). Это совпадение не
случайно, о нем говорит теорема двойственности в ЛП. Значения
двойственных переменных имеют экономическую интерпретацию: они
представляют собой оценки ресурсов. Так, нулевые значения переменных у2 и у3,
соответствующих ресурсам кожа и клей, говорят, что эти ресурсы не являются
ценными, поскольку для производства 25 стульев и 15 столов имеющиеся
количества этих ресурсов избыточны, в чем можно убедиться, подставив
значения xi=25, хг=15 в левые части неравенств прямой задачи. Значение
yi=0.5 говорит о том, что при увеличении ресурса древесина на некоторое
небольшое количество Д; можно получить дополнительный доход о.5-Дь
Аналогично значение у„=о.75 говорит о том, что при увеличении ресурса
труд, затраты на некоторое небольшое количество Д4 можно получить
дополнительный доход 0.75-Д4.
Положим, например, Ai=o, Д«=40 т. е. возьмем ь= [500; 15; 7500; 440].
Решив заново прямую ЗЛП, получим
х *= [30 14]
fval = -580
Видим, что (с учетом измененного знака fval) доход действительно
увеличился на 0.75-Д4=30.
Решение задачи ЛП, т. е. точка оптимума, может быть не единственным
(хотя оптимальное значение целевой функции определяется однозначно).
! Пример 16.2. Задача линейного программирования " ц~ '' ~ г "I
Рассмотрим задачу: найти максимум функции г=хг+х2 при o<xt<2 (i=i,2) и
xi+xj<3. Эти неравенства задают на плоскости квадрат размером 2X2 со
срезанной вершиной в правом верхнем углу (рис. 16.1).
Математическое программирование
657
Подготовим данные:
» lb = zeros(2,1);
» ub = 2*ones(2,l);
» A = ones(1,2) ;
» b = 3;
» f = A;
и обратимся к функции linprog:
» [x,fval] = linprog(-f,A,b,[],[],lb,ub)
x =
1.5000
1.5000
fval =
-3.0000
Целевая функция принимает одно и то же значение (f=3) во всех точках
отрезка с концами [1 2], [2 1]. Для концов отрезка это легко проверить
подстановкой их координат в выражение целевой функции. Точка х=[1.5 1.5]
является серединой этого отрезка.
Для двух переменных ЗЛП имеет простую геометрическую интерпретацию.
Ограничения на переменные определяют выпуклый замкнутый
многоугольник — область допустимых значений переменных. Функции цели
соответствует прямая линия (в нашем примере x+y=const). Если параллельно
перемещать линию функции цели, то она сначала коснется одной вершины (или
грани) допустимой области значений, а потом — противоположной
вершины (или грани). Одно из этих положений соответствует минимуму целевой
функции, а другое — максимуму. Это объяснение наглядно демонстрирует
рис. 16.1, на котором маркером выделена точка, найденная с помощью
функции linprog. Для построения этого рисунка использовалась программа
iinprog_draw с последующей ручной корректировкой полученного
изображения (штриховка и маркировка функции цели).
function linprog_draw
axes('Xlim',[-0.5 2.5],'Ylim',[-0.5 2.5]};
axis equal; hold on;
x=[0 2 2 1 0 0]; y=[0 0 1 2 2 0];
plot(x,y,'k');
line(2,1, 'Marker', '.','MarkerSize',20};
lined,2, 'Marker', '. ', 'MarkerSize',20} ;
lined. 5,1.5, 'Marker', '. ', 'MarkerSize', 20);
xlabeK'xl'}; ylabel ('x2 ') ;
658
Глава 16
line([-0.5,0.5],[0.5,-0.5])
line([-0.5,1.5],[1.5,-0.5])
line([-0.5,2.5], [2.5,-0.5])
line([0.5,2.5],[2.5,0.5])
Рис. 16.1. Геометрическая интерпретация ЗЛП
16.2. Бинарное линейное программирование
Задача бинарного линейного программирования отличается от обшей задачи
более жесткими ограничениями на переменные, которые могут принимать
только два булевых значения: 0 или 1. Решение задачи в этом случае
использует стандартный алгоритм линейного программирования в сочетании с
методом ветвей и границ. Чтобы найти оптимальное решение в булевых
переменных, строится серия "ослабленных" задач линейного
программирования, в которых на переменные (сначала на все) накладываются более слабые
ограничения: 0<x(i><l.
Алгоритм создает дерево поиска многократным добавлением булевых
ограничений. На каждом шаге ветвления алгоритм выбирает некоторую
переменную x(i), текушее значение которой не целое, добавляет ограничение
x(i)=o, чтобы сформировать одну ветку, и ограничение x(i)=i, чтобы
сформировать альтернативную ветку. Этот процесс можно представить двоичным
деревом, в котором каждый узел соответствует введению булева ограничения
по одной нз переменных.
Математическое программирование
659
В каждом узле двоичного дерева алгоритм решает "ослабленную" задачу
линейного программирования и выясняет, надо ли строить две ветви от этого
узла или переходить к другому узлу. При этом имеется три возможности:
П "ослабленная" задача в текущем узле не имеет решений или значение
целевой функции хуже (больше), чем найденное ранее наилучшее булево
решение; этот узел удаляется из дерева, и алгоритм переходит к другому
узлу в соответствии с некоторой стратегией выбора;
О алгоритм обнаруживает новое допустимое булево решение со значением
целевой функции лучшим (меньшем), чем найденное ранее наилучшее
булево решение; алгоритм корректирует текущее наилучшее решение и
переходит на следующий узел;
П "ослабленная" задача в текущем узле дает значение целевой функции
лучше (меньше), чем найденное ранее наилучшее булево решение,
однако это решение не удовлетворяет булевым ограничениям. В этом случае
происходит расширение поиска.
Для решения задачи бинарного линейного программирования в MATLAB 7
используется функция bintprog. Формы обращения к этой функции:
х = bintprog(f}
х = bintprog (f, A, b}
x = bintprog(f,A,b,Aeq,beq)
к = bintprog(f ,A,b, Aeq,beq,:xO)
x = bintprog(f,A,b,Aeq,beq,xO,options)
[x, fval] = bintprog (...)
[x,fval,exitflag] = bintprog(...)
[x,fval,exitflag,output] = bintprog(...)
Семантика входных и выходных параметров та же, что у функции linprog.
Через входную переменную options с помощью функции optimset задаются
параметры, управляющие ходом вычислительного процесса и его
отображением на мониторе. Отметим некоторые из них, характерные именно для
функции bintprog:
П 'Maxiter' — максимально допустимое число итераций, значение по
умолчанию равно l00000*nuniberOfVariables (nuiriberOfVariables —
количество переменных);
П 'MaxRLPiter' — максимально допустимое число "ослабленных" задач
линейного программирования, значение по умолчанию равно
10 0 * numberOfVariables;
□ 'MaxNodes' — максимально допустимое число узлов дерева, значение по
умолчанию равно 1000*numberOfVariables;
660 Глава 16
П 'MaxTime' — максимальное время решения (в секундах), значение по
умолчанию 72оо;
П ■ Toixinteger' — предельно допустимое отличие переменных от целых,
значение по умолчанию 1. е-8.
Два параметра определяют стратегию выбора узла и выбора переменной, по
которой производится ветвление:
П 'Nodesearchstrategy' — возможны два варианта: 'df' — используется
стратегия поиска'в глубину, 'Ьп' — используется стратегия поиска,
которая выбирает узел с самым низким (т. е. наилучшим) значением целевой
функции. По умолчанию используется 'Ьп*;
□ 'Branchstrategy' — возможны два варианта: 'mininfeas' — выбирается
переменная со значением, минимально отличающимся от целого; т. е.
переменная, величина которой наиболее близка к 0 или 1 (но не 0 или
I), 'maxinfeas' — выбирается переменная со значением, максимально
отличающимся от целого, т. е. переменная, величина которой наиболее
близка к 0.5. По умолчанию используется 'maxinfeas'.
Возможные значения выходного параметра exitflag:
П 1 — успешное завершение вычислений, найлено решение х (и, если было
указано в обращении, значение целевой функции fval);
По— число итераций превысило заданное в optimset значение параметра
Maxlterj
П -2 — задача сформулирована некорректно;
П -4 — число узлов дерева превысило заданное в optimset значение
параметра MaxNodes;
П -5 — время поиска превысило заданное в optimset значение параметра
MaxTime;
П -б — число решаемых "ослабленных" задач линейного .программирования
превысило заданное в optimset значение параметра MaxRLP.
Перейдем к рассмотрению примера 16.3.
! Пример 16.3. Задача 6 разбиении множества'""- '■ > ■?,*
В математическом фольклоре эта задача носит образное название "задачи о
камнях". Суть се такова: имеем кучу камней разного веса (какие-то веса
могут и совпадать). Требуется сформировать из этих камней две новые кучи
так, чтобы веса этих куч отличались друг от друга как можно меньше.
Несмотря на простоту формулировки, "задача о камнях" относится к
категории так называемых NP-полных задач [52].
Математическое программирование
661
Чтобы сформулировать "задачу о камнях" в терминах бинарного
программирования, введем вектор весов камней w. Тогда вес всей кучи будет равен
sum(w). Компоненты вектора решения х будем интерпретировать так: если
x(i)=i — положим i-й камень в первую кучу из двух, если x(i)=o —
положим i-й камень во вторую кучу. Потребуем, чтобы вес первой кучи был
максимальным, но не превосходил половины общего веса всех камней.
Это можно записать так: найти max(Zw(i)*x{i}) при Ew(i)*-x(i}<o.5*sum(w}.
Для обращения к функции bintprog подготовим вектор весов w =[19538].
Эти веса будут играть троякую роль:
О они являются коэффициентами целевой функции (поскольку ищется ее
максимум, в обращении берется вектор -w);
□ они же являются элементами однострочной матрицы ограничений;
П половина их суммы является правой частью ограничения.
Обратимся к функции в форме, обеспечивающей выдачу максимального
количества итоговой информации:
[х,fval,exitflag,output] = bintprog(-w,w,0.5*'sum(w))
Получим результат:
Optimization terminated.
x =
1
1
0
1
0
fval =
-13
exitflag =
1
output =
iterations: 6
nodes: 3
time: 0.05007200000000
algorithm: 'LP-based branch-and-bound'
branchStrategy: 'maximum integer infeasibility'
nodesrchstrategy: 'best node search'
message: 'Optimization terminated.'
662
Глава 16
Интерпретация результатов: в первую кучу пало положить три камня с
номерами I, 2 и 4; во вторую кучу надо положить камни 3 и 5. При этом веса
обеих куч будут равны 13.
16.3. Решение матричных игр
Линейное программироваггие можно использовать для решения матричных
игр, т. е. для поиска оптимальных смешанных стратегий участников игры.
Матричная игра задается платежной матрицей А=(а1;,), строки этой матрицы
соответствуют чистым стратегиям первого участника игры р, столбцы —
чистым стратегиям второго участника q. Если р выберет стратегию i, a q —
стратегию j, то р получит (a q заплатит) сумму, равную ап. Смешанная
стратегия участника р представляет собой вектор относительных частот
Р={р,), с которыми участник использует отдельные чистые стратегии при
повторных актах игры. Аналогично определяется смешанная стратегия
участника q — это вектор относительных частот q=(qj). Математическое
ожидание выигрыша р (проигрыша q) при выборе ими смешанных стратегий р и
q выражается формулой p'*A*q (предполагается, что р и q— векторы-
столбцы). Ясно, что любая чистая стратегия является частным случаем
смешанной (когда одна из относительных частот равна 1, а остальные — о).
Основной результат теории матричных игр — теорема Джона фон Неймана, —
утверждает, что
max min(p' * А * q) = min max (p' * A * q).
p q q p
Эта величина обозначается v и называется ценой игры, а те р и q, при которых
она достигается, называются оптимальными смешанными стратегиями
участников игры. Игру естественно назвать справедливой, если ее цена равна о.
Смысл оптимальности стратегий р и q таков: если р будет придерживаться
оптимальной стратегии р, ему гарантируется выигрыш не менее v, какой бы
(чистой или смешанной) стратегии ни придерживался q. Если q будет
придерживаться оптимальной стратегии q, ему гарантируется проигрыш не
более v, какой бы (чистой или смешанной стратегии) ни придерживался р.
Гарантия подразумевает, что каждый участник делает свой ход (выбор
стратегии), не зная хода соперника.
Для игр с "узкой" матрицей (гхп или тх2) существуют простые
графоаналитические приемы решения, т. е. нахождения цены и оптимальных
смешанных стратегий, однако в общем случае это довольно сложная задача.
Математическое программирование
663
Чтобы найти иену игры с платежной матрицей A=(aiS) размером mXn и
оптимальные стратегии участников, надо решить пару двойственных задач
линейного программирования:
1. Найти вектор х=[хг,-.. .,хга], для которого F=xi+...+xra достигает
минимума при условиях А'*х>1п (здесь in — вектор-столбец из п единиц).
2. Найти вектор y=[yi;.. .,уГ1], для которого G=yi+...+yn достигает
максимума при условиях А*у<1„, (здесь im — вектор-столбец из m единиц).
Из теорем двойственности в ЛП следует, что F„lln=Gma)t. Тогда цена игры
v=i/Frnin=i/G],,av, а оптимальные смешанные стратегии p=v*x, q=v*y. Случай
v=o обсуждается в примерах 16.4 и 16.5.
I Пример ^:6.4г:Ма^р!|адная"карточная игра i
Рассмотрим игру "Жулик" (название станет ясно из дальнейшего описания).
Ее правила таковы: каждому участнику сдается три карты — красный туз,
черный туз и двойка, причем у р двойка красная, а у q — черная. Этот
расклад известен обоим участникам. Каждый выбирает из своих трех карт одну
и кладет ее рубашкой вверх на стол. Затем карты открывают и определяют
исход игры. Если обе карты одного цвета, выигрывает р, если разных — Q.
Сумма выигрыша/проигрыша определяется достоинством карты,
выложенной победителем: если это туз — одно очко, если двойка — два очка. Если
открылись две двойки, объявляется ничья (платеж равен нулю). Платежная
матрица этой игры представлена в табл. 16.2.
Таблица 16.2
Красный туз
Черный туз
Красная двойка
Красный туз
1
-1
2
Черный туз
-1
1
-1
Черная двойка
-2
1
0
Чтобы решить игру с помощью функции linprog, подготовим данные для
прямой и двойственной задач:
» А = [1 -I -2;-1 I 1,-2 -1 0J;
>> % Обращение для прямой задачи:
» [x,fval] = linprog{ones(3,1),-A',-ones (3,1},[],[],zeros(3,1))
Optimization terminated successfully.
x =
0.0.000
3.0000
2.0000
22 2-ях 8'W
664
Глава 16
fval =
5.0000
» % Обращение для обратной задачи:
» [y,gval] = linproq (-ones (3,1) ,A,ones (3,.1), Г], [], zeros (3,1))
Optimization terminated successfully.
У =
2.0000
3.0000
0.0000
gval =
-5.0O0O
Отрицательное значение gval вызвано изменением знака перед вектором
коэффициентов целевой функции. Цена игры: v=i/fvai=i/5. Смешанные
стратегии:
p=v*-x=[0 3/5 2/5], q=v*y=[2/5 3/5 0].
Обсудим вопрос о справедливости этой игры. На первый взгляд, особенно
если ограничиться словесной формулировкой правил, игра кажется
справедливой. Легко себе представить, как участник р ("Жулик") уговаривает
сыграть другого участника q (которого в данной ситуации можно назвать
"Лохом"). Лоху кажется, что все в порядке, и он садится играть. Однако
после, скажем, 100 игр выяснится, что Лох оказался в проигрыше (не менее
20 очков). И дело не в везении или невезении — просто Жулик
придерживался оптимальной для себя стратегии: он никогда не выкладывал на стол
красного туза, в 60% игр выкладывал черного туза, а в 40% игр красную
двойку, чередуя их случайным образом. И что бы ни делал Лох, если он не
сумеет подглядеть, какую карту выложил Жулик, в длинной серии игр он
окажется в проигрыше (хотя в отдельных играх будет выигрывать, что
лишь усыпит его бдительность). Его проигрыш будет в среднем 20 очков
на 100 игр, если он будет придерживаться оптимальной для себя стратегии:
никогда не выкладывать на стол двойку, в 60% игр выкладывать черного
туза, а в 40% игр красного туза, чередуя их случайным образом.
( Замечание )
Как раз для справедливых игр с ценой v=0 способ решения игры с помощью ЛП
не срабатывает.
| Пример 16.5. Матричная игра "Орёлгрёшка"" ' - у;уь£'--' *%М
Сюжет игры "Орел-решка" можно описать так: участники кладут на стол по
монете равного достоинства, прикрывая ее ладонью. Затем они одновремен-
Математическое программирование
665
но убирают руки. Если монеты лежат кверху одной и той же стороной, обе
монеты забирает р, в противном случае обе монеты забирает q. Первая
чистая стратегия каждого участника: положить на стол монету кверху "орлом",
вторая стратегия — кверху "решкой".
Платежная матрица этой игры or=[1 -i; -l l].
Интуитивно очевидно, что цена этой игры v=o, оптимальные смешанные
стратегии р= [1/2 1/2], q= [1/2 1/2]. Составим две задачи ЛП для этой игры:
F=xl+x2 -> rain G=yl+.y2 -» max
xl-x2>l yl-y2<l
-xl+x2>l -yl+y2<l
xl,x2>0 yl,y2>0
Видим, что офаничения первой задачи несовместны: сложив первые два
неравенства, получим о>2. Эта задача ЛП не имеет допустимых планов.
Для второй задачи, если положить yi=yj=t, то при любом t>o точка у
удовлетворяет всем неравенствам, а значение целевой функции G=2*t может
стать сколь угодно большим. Видим, что целевая функция этой задачи не
ограничена сверху на множестве допустимых планов.
Испытаем MATLAB на этих задачах. Для первой задачи получим:
х = [7.2795 8.2795], fval = 15.5591
Найденный вектор, однако, не удовлетворяет неравенствам задачи:
OR'*x = [-1.0000 1.0000]
Впрочем, MATLAB выдает предупреждение:
Exiting: One or more of the residuals, duality gap,
or total relative error has stalled:
the primal appears to be infeasible (and the dual unbounded).
(The dual residual < TolFun=1.00e-008.)
Для второй задачи получим более осмысленный результат, не
противоречащий нашему предварительному анализу (значения переменных и целевой
функции весьма велики):
у = 1.0еЮ10* [1.2747 1.2747]
gval = --2.5495е+010
Найденный вектор удовлетворяет неравенствам задачи:
CR*y = [0 0]
MATLAB выдает такое же предупреждение.
666
Глава 16
С задачами этого рода (v=o) можно справиться очень простым приемом:
надо прибавить ко всем элементам матрицы платежей некоторую константу с.
Цена такой модифицированной игры v=c, оптимальные стратегии
участников исходной и модифицированной игр одинаковы (пример 16.6).
| Пример 16.6. Модифицированная матричная игра - ^.1^ ;р. ■]
Рассмотрим этот прием на примере игры "Разоблаченный жулик". Лох,
игравший с Жуликом, разобрался, что к чему, и предложил отменить
исключительное правило, касающееся двух двоек — именно оно давало Жулику
преимущество. В соответствии с общим правилом, поскольку цвета двоек
различны, 2 очка в этой ситуации выигрывает бывший Лох.
Платежная матрица теперь станет такой: a=[1 -l -2,--1 1 1,-2 -1 -2], пена
игры v=o, так что непосредственно получить удовлетворительные результаты
с помощью MATLAB не удастся. Поэтому предварительно добавим ко всем
элементам матрицы а по 1 и обратимся к функции linprog:
» [x,fval] = linprog(ones(3,1),-(A+l)',-ones(3,l),[],[],zeros(3,l})
Optimization terminated successfully,
k =
0.0000
0.6667
0.3333:
fval =
1.0000
Цена модифицированной игры (a+i) равна l, а исходной — о, оптимальная
смешанная стратегия разоблаченного Жулика р=[0 2/3 1/3].
А теперь решим двойственную задачу:
» [y,gval] = linprog(-ones(3,1},A+l,ones(3,1},[],[].zeros(3,1))
Optimization terminated successfully.
У =
0.5000
0.0000
0.5000
g.val =
-1.0000
Оптимальная смешанная стратегия поумневшего Лоха q=[l/2 о 1/2].
Математическое программирование
667
16.4. Квадратичное программирование
Для решения задачи квадратичного программирования предназначена
функция quadprog. Область поиска для нее задается так же, как при
решении задачи линейного программирования (см. разд. 16.1).
Целевая функция задачи квадратичного программирования имеет вид
0.5*x'*H*x+f • *х и в обращении к quadprog представлена двумя
параметрами — симметричной матрицей н и вектором f.
х = quadprog(Н,f,А,Ь)
х = quadprog(H,f,А,b,Aeq,beq)
х = quadprog(H,f,A,b,Aeq,beq,lb,ub)
x = quadprog(H,f,A,b,Aeq,baq,lb,ub,xO)
x = quadprog (H, f, A, b,Aeq,beq, lb, ub,xO, options)
x = quadprog(H,f,A,b,Aeq,beq,lb,ub,xO,options,pi,p2,...)
|x,fval] = quadprog(...)
[x,fval,exitflag] = quadprog(...)
[x,fval,exitflag,outpjt] = quadprog(...)
[x,fval,exitflag,output,lambda] = quadprog(...)
Если в обращении к функции quadprog заданы только верхние и нижние
границы или только линейные уравнения, то используется метод Ньютона с
доверительным интервалом и метод сопряженных градиентов. В противном
случае применяется метод активного набора, для которого нужна стартовая
точка хО. Однако если стартовая точка не задана, она выбирается
автоматически. То же самое происходит, если в параметрах options было
установлено 'LargeScale'='off'.
Рассмотрим пример 16.7.
I Пример 16.7. Задача квадратичного программирования
Найдем минимум положительно определенной квадратичной функции
х2! 4 Xj в треугольнике, ограниченном прямыми xi=2, х2=1, xi+2x2=2. С
учетом коэффициента 0.5 в определении квадратичной целевой функции (см.
выше) введем матрицу н=2*еуе(2) и вектор f=zeros(2,i>. Неравенства хт<2
и х2<1 отнесем к ограничениям на координаты, положив ub=[2;i], а
неравенство xi+2x,.>2 представим в виде а*х<ь с матрицей а=[-1 -2] и вектором
Ь=[-2]. Обратимся К фунКЦИИ quadprog:
»Н=2*еуе(2); f=zeros(2,1); ub=[2;l];
» A=[-l -2]; Ь=[-2];
:» [x,fval] = quadprog(H,f,A,b,[J,[J,[],ub)
668
Глава 16
Warning: Large-scale method does not currently solve this problem
formulation, switching to. medium-scale method.
Optimization terminated successfully,
x =
0.4000
0.8000
fval =
0.8000
Причина предупреждения заключается в том, что были заданы верхние
границы, а также линейное неравенство, поэтому произошло переключение на
метод активного набора, для которого была нужна стартовая точка х0. Хотя
стартовая точка и не была задана, функция успешно выполнила работу.
Геометрическая интерпретация полученного, результата достаточно очевидна.
Допустимая область изменения переменных xi, х2 задана прямоугольным
треугольником (рис. 16.2), а минимизируемая функция цели представлена
концентрическими окружностями с центром в начале координат. Постепенно
увеличивая радиус этих окружностей, мы находим первую точку встречи с
ребром допустимой области, в которой функция цели достигает минимума.
При последующем увеличении радиуса функция цели достигает самой
удаленной вершины треугольника, где достигается максимум. Рисунок 16.2
получен с помощью функции qp_tst.m, текст которой приводится ниже.
function qp_tst
sq5=sqrt(5) ;
hold, on; axis equal
t.= -0.1:0.05:pi/2+0.1;
cost^cos(t); sint=sin(t);
r - [l/sq5 2/sq5 1 3/sq5 2 sq5];
for i=length(r):-1:1
rc=r(i)*cost; rs=r(i)*sint;
plot(re, rs);
end
plot([0 2 2 0), [1 0 1 l],'k-');
text(0.3,-0.1,'0.2'};
text(0.75,-0.1, '0.8'};
text(l.0,-0.1,'1.0');
text(l.35,-0.1, 4.8');
text(2.05,-0.1, '4');
text(2.3,-0.1,'5') ;
line -(0.4,0.8, 'Marker', ' . ', 'MarkerSize', 20) ;
Математическое программирование
669
text(0.3,0.7,'min');
line (2,1, 'Marker', '. ', 'MarkerSize', 20} ,-
text(2.05,l.l,'max'};
xlabel('xl'}; ylabel('x2');
title('Линии уровня функции х1л2+х2л2, ее min и max в треугольнике',
'FontName','Courier');
,, 2
4L
^ as
Динии уровня функции х1 +х22, ее min и щах .в треугольнике
-0.5
Рис. 16.2. Геометрическая интерпретация
задачи квадратичного программирования
Теперь найдем максимум той же функции. Для этого в обращении к
quadprog перед именем матрицы н и вектора f поставим знак минус:
» [x,fval] = quadprog(-H,-f,A,b,[],[],[],ub}
Warning:
Optimization terminated successfully,
x =
2
1
fval =
-5
Рассмотрим пример 16.8.
670
Глава 16
Пример 16.8. Задача о ритмичных поставках ■ • ->-? ^¾¾¾^ . ^"-.v v^lK;
На склад от поставщиков поступает некоторый однородный продукт
(например, горючее). Со склада этот продукт передается на, производство
(например, тепла и/или электроэнергии). От поставщиков продукт может
поступать не очень ритмично, но на производство он должен передаваться
как можно более равномерно.
Рассмотрим эту задачу в дискретной постановке, т. е. будем считать, что все
акты приема-передачи продукта происходят по тактам в моменты t=l, 2, ...
Введем величины, характеризующие функционирование склада (табл. 16.3).
Таблица 16.3
№ п/п Параметр Обозначение
1 Число тактов п
2 Вектор поставок продукта р= [ р,, р2,. -, р„ ]
3 Емкость склада maxV
4 Минимальное нормативное количество продукта minV
на складе
5 Начальная загрузка склада v0
OfininVSVofinaxV
6 Вектор передачи продукта на производство х= [ xi, хг, - ■ ■, хп]
Первые пять параметров — входные (их значения должны задаваться),
вектор х — выходной параметр (должен вычисляться при решении задачи).
Будем считать, что суммарное количество продукта, поступившего на склад,
должно быть примерно равно суммарному количеству продукта,
переданного со склада:
1=1 i=l
Максимально равномерная передача продукта на производство (с учетом
оговоренного примерного равенства) достигается, если целевая функция
V (x.i - мр)2 —> min (здесь мр — среднее по всем компонентам вектора р,
i=i
которое может быть найдено с помощью функции mean(p)).
Целевую функцию преобразуем, раскрыв скобки и приведя подобные члены:
xl + xl + . . . + х2 - 2 ■ Мр • (хх. + х, + . . . + х„} + п ■ (Мр)? .
Математическое программирование
671
В матричном виде квадратичную часть этого выражения запишем так:
о.5*х'*н*х, где матрица н=2*еуе (п); линейная часть равна f *х, где вектор
f=-2*Mp*ones(n, 1). Свободный член n- (Mp)z не может быть включехг в
обращение к функции quadprog, его придется учитывать отдельно.
Офаничения задачи заключаются в том, что в любой момент t количество
продукта на складе vt удовлетворяет неравенствам rainv<vt^uaxv. Это
количество выражается простой формулой
Vt = Ч + £ Pi " X *i-
Подставим это выражение в двойное неравенство и разрешим его относи-
телыю \ х±, получим ограничения задачи:
t t t
+ ]jT Pl - maxV < £ Xi < V0 + >T Pi -
Vt = l,n
minV .
Вектор s, содержащий суммы ^ pi5 можно получить, выполнив команду
i = l
s=cumsum(p). Поступить таким же образом с вектором х невозможно,
поскольку заранее он неизвестен. Вместо этого введем новые переменные:
ус = У^х1- В матричной форме это соотношение можно записать так:
у=ь*х, где матрица
l =
10 0
110
111
111
111
1 о
1 1
Ее можно создать, выполнив команду L=tril (ones (n)). Старые переменные
выражаются через новые с помощью обратной матрицы: х=ъ_1*у. Через
новые переменные квадратичная часть целевой функции выражается так:
0.5*y'*Hnew*y, где Hnew = inv(L)'*H*inv(L).
Линейная часть целевой функции равна fnew'*x, где вектор fnew=inv(L.) ■ *f.
672
Глава 16
Ограничения для новых переменных можно представить в форме ib<y<ub,
где векторы lb, ub задаются формулами:
lb = (V0-maxV)+s
ub = (V0-minV)+s
(скаляры vo-maxv и vo-minv прибавляются к каждому элементу вектора s).
Зададим конкретные данные:
» п=5; р=[10,25,5,10,30]; maxV=40; minV=0; V0=5;
С помощью приведенных выше формул подготовим данные для обращения
К функции quadprog:
» Mp=mean(p)
Мр =
16
» s=cumsum(p) ;
» lb=(V0-maxV}+s;
» ub=(V0-minV)+s;
» L=tril(ones(n)};
» invL=inv(L);
» TinvL=invL';
» H=2*eye(n);
» Hnew=TinvL*H*invL;
» f=-2*Mp*ones(n,1);
» fritew=TinvL*f;
Найдем решение задачи для новых переменных у:
» [у, fval] = quadprog (Hnew, fnew, [],[],[],[] ,1b, ub}
Optimization terminated successfully:
Relative function value changing by less than OPTIONS.TolFun
У =
13.7500
27.5000
41.2500
55.0000
71.0000
fval =
-1.2598e+003
Аномально большое (к тому же отрицательное) значение целевой функции
fval объясняется очень просто. Когда формировалось выражение целевой
функции, были учтены квадратичная и линейная части, а для свободного
Математическое программирование
673
члена п*(Мр)г в обращении к функции quadprog не нашлось места. На
самом деле это слагаемое £0=п*мрЛ2=12во надо добавить к fval — получится
скромное значение 20.25.
Вернемся к вектору старых переменных х:
» x=invL*y
X =
13.7500
13.7500
13.7500
13.7500
16.0000
» Mx=enean(x)
Мх =
14.2000
Теперь можно восстановить значение целевой функции, равное
» sum((x-Mp).Л2}
ans =
20.2500
Дополнительно найдем остаток продукта на складе после каждого такта:
» V=V0+cumsum(p)-cumsum(x) '
V =
1.2500 12.5000 3.7500 0.0000 14.000.0
По этому результату видно, что емкость склада (maxv=40) ни разу не была
превышена, но на четвертом такте склад полностью опустошался.
Глава 17
Метод Монте-Карло
В математике существует целое направление, связанное с методом Монте-
Карло. Оно занимается использованием случайных чисел для решения
различных математических задач: интерполяции, вычисления интегралов,
решения дифференциальных и интегральных уравнений, решения систем
линейных уравнений, поиска экстремума, моделирования процессов и т. д.
Преимущества недетерминированных методов особенно ярко проявляются
при решении задач большой размерности, когда применение традиционных
детерминированных методов затруднительно или совсем невозможно.
Границы между простым и трудным, возможным и невозможным с развитием
вычислительной техники сдвигаются вдаль, но существуют всегда. Основной
недостаток недетерминированных методов — их медленная сходимость, что
вынуждает искать компромисс между невысокой точностью результатов и
большим расходом машинного времени.
Вначале для получения случайных чисел использовались заранее
составленные таблицы и физические датчики. Очевидным недостатком таблиц
является их ограниченный объем, а использование физических датчиков
наталкивается на сложность реализации, медлительность датчиков, их
капризность и невоспроизводимость полученных результатов.
Поэтому вместо чисто случайных чисел стали использовать псевдослучайные
числа, генерируемые с помощью той или иной программы. Случайность при
таком подходе заменяется непредсказуемостью для неосведомленного
пользователя: наблюдая некоторое время "хорошую" последовательность
псевдослучайных чисел, он не в состоянии предсказать, каким будет следующий
член этой последовательности, хотя на самом деле все они вычисляются по
- довольно простой формуле. Прежде чем использовать для решения задач тот
или иной датчик случайных чисел (табличный, физический или
программный), его подвергают разнообразным тестам: на равномерность (или
согласие с другим предписанным законом распределения), на независимость и т. д.
Наиболее полный анализ алгоритмов генерации псевдослучайных чисел и
методов их тестирования имеется в книге [58].
676
Глава 17
Одно из преимуществ метода Монте-Карло заключается в его своеобразной
"локальности": этим методом можно, например, искать одну составляющую
решения системы линейных уравнений, не интересуясь другими
компонентами, или искать значение функции, являющейся решением
дифференциального уравнения, в одной точке и т. п. Если, например, трудоемкость
прямых методов вычисления определенных интегралов с ростом
размерности п пространства переменных возрастает как kn (к — число шагов, на
которое разбивается интервал интегрирования по каждой оси), то
трудоемкость алгоритма Монте-Карло возрастает как kn/z.
Основной недостаток метода Монте-Карло — сравнительно медленная
сходимость, для получения более или менее надежных результатов требуется
большое число повторений.
17.1. Генерация случайных данных
Функция rand используется для генерации псевдослучайных чисел,
равномерно распределенных в интервале от 2"53 до 1-2"53 (примерно — [о; i]).
Теоретически функция rand позволяет без повторений сгенерировать 21092
псевдослучайных чисел. Обратившись к этой функции без аргумента, мы
получаем очередное случайное число. Если у функции задается один
скалярный аргумент, то функция rand(n) возвращает квадратную матрицу п-го
порядка, элементами которой являются случайные числа из интервала [о; 1].
Функция rand(n,m) возвращает прямоугольную матрицу размерности nxm со
случайными числами. Обращение rand (size (А)} позволяет сгенерировать
матрицу случайных чисел, размерность которой совпадает с размерностью
массива а.
Для перехода от чисто дробных случайных чисел к случайным числам из
произвольного диапазона [а; ь] достаточно воспользоваться
преобразованием a+(b-a)*rand.
В большинстве алгоритмических языков существует средство для
возмущения датчика случайных чисел, в С и Pascal — это функция или процедура
randomize. Она позволяет избежать повторения результатов при
многократных запусках программ, использующих датчик случайных чисел. В системе
MATLAB тоже имеется аналогичное средство:
rand('state',sum(100+clock))
Первый аргумент такого обращения обозначает служебный массив,
определяющий состояние датчика случайных чисел. Формирование некоторых
полей этого массива в зависимости от даты и текущих показаний машинного
таймера приводит к случайной перенастройке параметров, влияющих на
работу программы генерации случайных чисел.
Метод Монте-Карло
677
Состояние датчика случайных чисел можно сохранять и восстанавливать с
помощью следующих обращений:
s = rand('state');% запоминание состояния в массиве s
rand{'state',s) % восстановление состояния по массиву s
rand('state',0) % восстановление начального состояния датчика
Функция randn позволяет генерировать случайные числа, распределенные
но нормальному закону со следующими параметрами:
П среднее значение случайной величины равно о;
О дисперсия a2=i;
П средняя квадратическая ошибка (стандарт) о=1.
Форматы обращения к функции randn такие же, как и к функции rand.
Если вам потребуются случайные числа, распределенные по нормальному
закону со смещенным центром m и заданной дисперсией s, то достаточно
воспользоваться преобразованием тч-sqrt (s)*randn.
Кроме функций rand и randn, MATLAB предлагает и другие функции, с
помощью которых можно создавать различные случайные объекты.
Для генерации случайных перестановок из целых чисел 1, 2, ..., п
используется функция randperm(n):
» p=randperm(6)
Р =
2 4 3 6 5 1
Целую галерею матриц с различными свойствами позволяет генерировать
функция gallery. В ее состав входит и несколько матриц, элементы
которых выбираются случайным образом.
17.2. Элементы
математической статистики
В математической статистике используются различные числовые
характеристики случайных величин. Различают генеральные и выборочные
характеристики. Первые относятся ко всей (обычно бесконечной) совокупности
значений случайной величины, их можно найти только путем теоретических
рассуждений и аналитических вычислений. Характеристики второго типа
находятся путем обработки наблюдений за случайной величиной.
Наиболее важными характеристиками являются среднее значение и
дисперсия. Генеральное среднее обозначим а, генеральную дисперсию — о2.
678
Глава 17
- i-B
х
N .
1=1
Выборочное среднее по выборке [xi, х3, .. ., xN]:
N
выборочная дисперсия:
В методе Монте-Карло используются выборки одинаково распределенных
случайных величин с конечными дисперсиями, для которых известно, что
величина ———— при больших n имеет распределение, близкое к
станет
дартному нормальному. Это позволяет оценить величину отклонения
выборочного среднего от генерального: для любого вещественного к верно
соотношение
Р |х - а| < к-р=г = Ф(к).
2 Г t2/
Здесь Ф(к)=-?= е /2dt — один из вариантов интеграла вероятностей. Его
о
значение в данном контексте называют доверительной вероятностью. Чаще
всего берут:
П к=з — тогда доверительная вероятность равна 0.997 (правило "трех
сигм");
П к=1.96 — тогда доверительная вероятность равна о. 95;
П к=о .6745 — тогда доверительная вероятность равна о. 5.
Если зафиксировать к (и тем самым доверительную вероятность Ф(к)), то с
ростом числа наблюдений N верхняя граница отклонения выборочного
среднего от генерального среднего будет стремиться к нулю с вероятностью,
сколь угодно мало отличающейся от 1. Скорость сходимости метода Монте-
Карло невелика, она пропорциональна -;=, т.е. для уменьшения погреш-
VN
ности, скажем, в 10 раз надо увеличить число испытаний в 100 раз.
17.3. Линейная интерполяция
в многомерном кубе
Рассмотрим такую задачу. Пусть для функции f (xi,x2,...,xn) известны лишь
ее значения в вершинах е единичного куба е", т. е. при Xi=o или 1. Требуется
Метод Монте-Карло
679
путем линейной интерполяции найти значение функции в произвольной
точке (xi, х2, ..., хп), лежащей внутри или на границе единичного куба.
Формулы линейной интерполяции:
при n=i: f (xi) = (i-xi)-f <0)+xi-f (i),
при n=2: f (xl,x2) = (l-xl)-(l-x2)-f {0,0}+xl-(l-x2)-f (1,0)+
+ (l-xl)-x2-f (0,l)+xl-x2-f (1,1)
И Т. Д.
Проблема заключается в том, что количество слагаемых каждой такой
формулы равно количеству вершин куба еп, т. е. 2", и уже при п=ю становится
больше юоо.
Идея упрощения заключается в том, чтобы использовать не все 2П вершин, а
лишь какие-то из них, но делать это не один раз, а несколько, используя
всякий раз новый набор вершин, взятых случайным образом. Результаты по
всем использованным случайным наборам вершин усредняются.
Более конкретно метод Монте-Карло для интерполяции в многомерном
кубе выглядит так. Пусть дана точка (xj, хг, ..., хп)еЕг'. Построим случайный
вектор e=(el,e2,...,en), компоненты которого принимают только значения
о и 1 с заданными вероятностями: р(е,=0)=1-хь p(ei=i)=Xi, Это можно
сделать, ВЫПОЛНИВ команды r=rand(l,ri) и е=(г<=х).
Значение функции f (хг, х2,...,х„> = Mf (ei,ei,...,en) (среднее значение
функции в случайных вершинах единичного куба e=(ei,ei,...,en) при
повторении эксперимента).
Рассмотрим пример 17.1.
! Пример 17.1. Линейная интерполяция в многомерном кубе ;'' .¾5¾ ,,Шф^^ЖШ^Ц
Определим функцию, f, значение которой в любой вершине единичного
куба ег- равно квадрату веса этой вершины (весом o-i-вектора называется
количество входящих в него единиц). На рис. 17.1 для случая п=2 приведены
значения функции в вершинах единичного квадрата, а также линии уровня
функции f (Xi,x2)=xi+x2+2-xi-x2, полученной путем линейной интерполяции
при указанных значениях в вершинах (взяты уровни с=1/4:1/4:15/4).
function progl7_l
Xmin=0; Xmax^l; h=0.1;
axes ('Xlim',[Xmin-h Xmax+h],'Ylim', [Xmin-h Xmax+h));
axis equal; hold on;
x=[0 0 1 1 0]; y=[0 1 1 0 0J;
plot(x,y,'к-');
text (0.03,-0.05,'f(0 0)=0');
2л Зак. «59
680
Глава 17
text (0..03,1. 05,'f (0 1)=14,-
text(1.03,-0.05, 'f(1 0)=1')?
text(1.03,1.05,'f(1 1)=4');
% уравнение xl+x2+2*xl*x2=c
for c=l/4:l/4:l
xx=0:0.05:c;
yy=(c-xx)./(l+2*xx);
plot(xx,yy);
end
for c=5/4:1/4:15/4
xx=[(c-l)/3:0.05:l 1];
yy= (c-xx) . / (l+2*xx) ,-
plot(xx,yy);
end
xlabel('xl'); ylabel('x2' •);
title ('Единичный квадрат с линиями уровня',
•FontName','Courier');
1
0.8
0.G
9J
0-4
0.2
0
-
.
-
■
-0.2. (
Единичный квадрат с линиями уровня ..
f(0 1)=1
\ XVXXVxSSSS^
\\XNvyxvnN4
\\\v^^
v^^§
v^§^
f(oo)=q
f(1 1)=4 ГА/Г
-.,5
iff
1
1¾;
f(10)=1 ";/"■
] 0:2 0.4 0.6 0.8 1 .-,1,2
xl ' •'" ':'" ■
Рис. 17.1. ^циничный квадрат
Ниже приводится текст функции rand interp, выполняющей случайную
интерполяцию. Ее первым входным параметром является vert_func —
Метод Монте-Карло 681
функция, вычисляющая значение в произвольной вершине единичного куба
е. Единственный аргумент функции vertfunc — вектор, содержащий
координаты вершины. Остальные входные парамегры rand_interp это: х —
вектор координат заданной точки в кубе и n — количество случайных наборов
вершин куба. Выходные параметры: Mf — выборочное среднее значение
функции по всем вершинам всех случайных наборов вершин, Df —
выборочная дисперсия.
function [Mf,Df] = rand_interp(vert_func,-x,N)
sumF=0 ;
sumD=0;
for s=l:N
r=rand[size(x));
e=(r<=x);
fe=feval(@vert_func,e};
sumF=sumF+fe;
sumD=sumD+feA2;
end
Mf=sumF/N;
K2=sumD/N;
D.f=M2-MfA2;
Приведенная ниже рекурсивная функция unitcube дает точное решение
задачи об интерполяции в единичном кубе. Первые два ее входных
параметра те же, что у randinterp, третий аргумент к — текущая глубина
рекурсии. При обращении следует задавать k=i.
function f=unix:_cube (vert_func, x, k)
if k>length(x)
f=feval(@vert_func,x);
elseif (x(k}=0) | (x(k)==l}
f=unit_cube (@verx:_func,x, k+1) ;
elseif (0<x(k)} К (x(k)<l)
y=x;
y(k)=0;
fO=unit_cube(Gvert_func, y, k+1);
y(k}=l;
fl=unit_cube(@vert_func,y,k+1);
f=(l-x(k))*fO+x(k)*fl;
end
682
Глава 17
В качестве vertfunc взята функция weight2, вычисляющая квадрат веса
вершины.
function w2=weight2(е)
w=sum(e);
w2=w~2;
Для проведения машинных экспериментов была использована следующая
программа:
% Rand_interp_tst
х=[0:.5 0.5]
%х=[0.5 0.5 0.5 0.5 0.5]
%х=(0.5 0.5.0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5]
%х=0.1:0.1:1.0
N=100;
iMf,Df]=rand_interp(@weight2,x,N);
k=l;
fc=unit_cube(@weight2, x, k);
s3=3*sqrt(Df/N);
d=abs((Mf-fc)/fc);
[Mf fc s3 d] % вывод результатов
Для желающих воспроизвести эксперименты отметим, что перед их началом
была выполнена команда rand с state', 0), все б экспериментов
проводились один за другим в указанном порядке.
В описании результатов экспериментов используются следующие
обозначения:
П х — заданная точка;
О Mf — приближенное значение функции;
П 1 с — точное значение функции;
П s3 — "три сигма";
О d=|Mf-fc|/fc — относительная погрешность.
Количество повторений во всех случаях было n=ioo. Следует заметить, что
это значение, принятое также и в последующих машинных экспериментах,
является очень маленьким и годится только для иллюстративных примеров.
Для более серьезных целей следует брать N на два-три порядка больше.
Результаты этих экспериментов описаны ниже.
При х=ю.5 0.5] получено:
Mf=1.53, fc=1.5, s3=0.4559, d=0.02.
Метод Монте-Карло
683
В соответствии со сделанной выше оценкой генеральное среднее с
вероятностью 0.997 лежит в интервале [1.07; 1.99]. Видим, что для столь высокой
доверительной вероятности этот интервал слишком широк. Если уменьшить
коэффициент доверия до 0.5, то интервал сузится до [1.42; 1.63], но все
еще останется достаточно широким. Реальная точность интерполяции по
методу Монте-Карло, характеризуемая величиной d, гораздо выше.
При втором эксперименте с тем же х получилось:
Mf=1.42, fc=1.5, s3=0.4 413, d=0.0533.
Третий эксперимент с х= [о.5 о.ь 0.5 0.5 0.5] дал следующие результаты:
Mf=7.41s fc=7.5, s3=1.9196, d=0.Q12.
В четвертом эксперименте с х=[0.5, о.5,...] были получены следующие
значения:
М£=29.22, £с=27.5, s3=4.4 510, d=0.0625.
Пятый и шестой эксперименты проводились с вектором x=o.i:0.. 1:1.о:
Mf=30.38, fc=31.9, 53-4.1957, d=0.0476.
Mf=31.66, fc=31.9, s3=4.4065, d=0.0075.
Замечание 1
Конечно, при n=length(x)=2 (эксперименты 1 и 2) применение метода Монте-
Карло нецелесообразно: гораздо проще вычислить значение функции по
формулам, приведенным выше. Однако при п=5 (эксперимент 3) такие формулы еще
надо вывести (они содержат 32 слагаемых), а при п=10 и п=11
(эксперименты 4—6) формулы содержат соответственно 1024 и 2048 слагаемых, что
существенно больше, чем количество повторений N=100, дающее вполне
удовлетворительные результаты.
Замечание 2
Относительная погрешность вычислений по методу Монте-Карло во всех
экспериментах ни разу не превысила 0.0 625.
17.4. Вычисление кратных интегралов
Простейшая формула вычисления определенного интеграла методом Монте-
Карло:
J f(x)dx = ——^flx,,,
где случайные числа xi равномерно распределены в интервале [а; ь].
В многомерном случае область интегрирования gcr'1, которую будем считать
ограниченной, необходимо заключить в n-мерпый прямоугольный паралле-
684
Глава 17
лепипед ai<xi<bi. Для генерации случайных точек х, равномерно
распределенных в этом параллелепипеде, можно воспользоваться командой
х=а+(Ь-а).*rand (1, п)
Здесь a=[ai...an], b=[bi...bn] и rand(i,n) — векторы-строки, операция .* —
покомпонентное умножение строк.
Если сгенерировать n случайных точек х в этом параллелепипеде и
обозначить через ng количество точек xeG, то "объем" области m(G)=m(nn) *ng/n, где
объем параллелепипеда т(Пп) = (bi-ai) *...* (Ьг-аГ1),. а интеграл
m(G)
XjEG
( Замечание J
Методом Монте-Карло можно легко найти интегралы по одной и той же области
сразу от нескольких функций — для этого надо просто накапливать суммы
£fk (xi) для всех нужных функций fk.
Рассмотрим пример 17.2.
Пример 17.2.]Ищефирование.м;^одом,МокгеУ<арло..'" /^к'т-^Г ?ЙЙ«й^,'^v. I
Найдем методом Монте-Карло объем v и положение центра тяжести ho
однородного шарового сегмента. Для удобства будем считать, что его
"южный полюс" лежит на плоскости х3=о, а отсекающая плоскость ей
параллельна. Обозначим радиус шара г, высоту сегмента h. Тогда
неравенства, задающие шаровой сегмент х? + у?г + х3г < 2 ■ г ■ х3, х3 < ь. Его объем
v = ГГГ
- яь
2^^3 1
высота центра тяжести над плоскостью х3=о
G
Здесь интегралы берутся по области, задаваемой неравенствами, другие две
координаты центра тяжести — нули.
Исходными данными для вычислений являются:
□ радиус круга, лежащего в основании шарового сегмента r0 = V2rh - ь2;
□ параллелепипед, включающий шаровой сегмент и задаваемый
неравенствами: al<xl<bl, а2<х2<Ь2, аЗ<хЗ<ЬЗ, ГДе al=a2=-r0, а3=0, Ы=Ь2=гО, b3=h.
Метод Монте-Карло
685
Из этих данных можно сформировать векторы a=[-r0,-r0,0], b=[rD,r0,h] и
с помощью следующей программы вычислить параметры шарового сегмента:
function [V,MhO,DhO] = spherical_segment(r,h,N)
sumF=0;
sumDf=0 ;
NG=0;
r0=sqrt(h*[2*r-h));
a=[-rO,-rO,0];
b =[r0, rO,h];
VP=4*rCT2*-h;
for s=l:N
x=a+(b-a).*rand(size(aJ J;
if (х(1)Л2+х(2)Л2+х(3)"2<=2*г*х(3)) & (x(3)<=h)
NG=NG+1;
fx=x(3);
sumF=sumF+ f x;
.sumDf =sumDf+fхЛ2 ;
end
end
V=VP*NG/N;
MhO=sumF/NG;
M2=sumDf/NG;
DhO=M2-MhO"2;
Для вызова данной функции и вычисления точных значений vprec и норгес
использовалась следующая программа:
% Spher_segm_tst
rand['state' ,0) ;
r=10; h=r;
N=100;
[V,Mh0,Dh0] = spherical_segment(r,h,N)
Vprec.=pi* {r-h/3) *пЛ2
H0prec=h*(2*r-0.75*h)/(3*r-h)
s3-3-sqrt(DhO/N)
Для полусферы (h=r) радиуса г=ю при n=ioo получены следующие
результаты: v=2320, мьо=5.8081, s3=o.708. Последнее означает, что с
доверительной вероятностью 0.997 истинная высота центра тяжести находится в
диапазоне [5.100; 6.516]. Для сравнения точные значения: vprec=2094.4,
норгес=б.25. Заметим, что высота центра тяжести, найденная методом Мон-
686
Глава 17
те-Карло, достаточно точна, относительная погрешность ее вычисления 5н
равна 0.07. Точность вычисления объема несколько хуже: относительная
погрешность 5v равна о. и.
В соответствии с замечанием нетрудно было бы одновременно найти и
какую-нибудь другую характеристику шарового сегмента, например, момент
инерции.
17.5. Решение уравнений в частных
производных
Рассмотрим решение методом Монте-Карло дифференциальных уравнений
в частных производных. Для примера возьмем хорошо известное уравнение
Лапласа (считаем, что размерность пространства п=2):
Эх* + Эх*
Это уравнение описывает многие скалярные физические поля:
П температурное поле в изотропной пластине при отсутствии источников и
поглотителей тепла;
П потенциал скорости установившегося плоского течения несжимаемой
жидкости;
□ потенциал электростатического поля в области, не содержащей зарядов;
□ потенциал ньютонова гравитационного поля в области, не содержащей
тяготеющих масс.
Решение и этого уравнения ищется для любой точки (х;, х2) определенной
области g пространства R2. Должны задаваться условия в каждой точке
границы области g одного из следующих видов:
П значение функции и;
П значения производных 1-го порядка функции u по xi и/или х2;
П линейная комбинация значений производных и самой функции.
Функции, удовлетворяющие уравнению Лапласа, называются
гармоническими. Основное свойство гармонической функции: ее значение в любой
внутренней точке области равно среднему арифметическому по окружности
любого радиуса с центром в этой точке, не пересекающей границу области. На
этом основан метод Монте-Карло для решения уравнений Лапласа,
называемый методом случайных блужданий. Его суть, вкратце, такова: начиная с
точки х0, в которой мы хотим найти значение функции и, строится
последовательность случайных точек xD, xi, хг, ..., называемая случайной траекто-
Метод Монте-Карло
687
рией. Когда траектория достигает границы, фиксируется заданное граничное
значение функции и в этой точке (мы ограничимся граничными условиями
1-го рода), и начинает строиться другая случайная траектория из точки хо,
и т. д. Все зафиксированные граничные значения суммируются. После
построения достаточно большого количества траекторий сумма делится на
число траекторий, полученное среднее значение принимается за значение
функции и(хО). Кроме среднего значения можно также найти дисперсию и
оцепить полученный результат с помощью критерия "трех сигм".
Варианты метода случайных блужданий отличаются друг от друга способом
построения случайной траектории. Для каждого из них доказано, что выход
на границу ограниченной области произойдет за конечное число шагов.
Простейший вариант, который пригоден только для выпуклой области,
строит одношаговую траекторию (двухточечная схема). Он заключается в
том, что из начальной точки проводится луч, угол луча с осью Ох\ —
случайная величина, равномерно распределенная в интервале (о; 2тс). Точка xi
пересечения луча с границей области — последняя точка случайной
траектории.
Рассмотрим пример 17.3.
! Пример 17^3. Метод Монте-Карло для решения ура!вне.ний в нартных*^-^-.
| ПРОИЗВОДНЫХ .^ tw-J.-■*«-■ .1 ,. .,.. .- -у ._ *-!.__ ;ч.^ ^- ^ |
В качестве области g возьмем единичный квадрат, ограниченный прямыми
Xi=o, xi=i, х2=о, х2=1. Граничные условия примем такие: на сторонах
квадрата, лежащих на осях координат, граничное значение и=0, на двух других
сторонах граничные значения задаются линейными функциями: и=х2 при
xi=i, u=xi при х2=1. Значение в любой точке границы можно представить
как и=х!*х2.
Функция и, если продолжить ее на весь единичный квадрат (а фактически —
на всю плоскость), удовлетворяет уравнению Лапласа. Это позволяет
сравнивать решение, полученное методом Монте-Карло, с точным,
вычисленным по формуле u=xi*x2.
Функция, реализующая метод случайных блужданий по двухточечной схеме,
имеет вид:
function [Mu,Du]=laplas_two_points(xO,N)
5umU=0; sumD=0;
twopi=2*pi;
for i=l:N
phi=twopi *rand;
cs=cos(phi);
688
Глава 17
sn=sin(phi);
omega=[cs sn];
t=-xO. /omega;
if abs(t(l))<=1
T0=t(l);
else
T0=t(2);
end
t=(l-xO)./omega;
if abs(t(l))<=1
Tl=t (lb-
else
Tl=t(2);
end
if T0>0
T=T0;
else
T=T1;
end
xbord=x0+T*omega;
ubord=bordfunc(xbord);
sumU=s umU+ubord ;
зитО=гитО+иЬогдл2;
end
Mu=sumU/N;
M2=sumD/N;
0и=М2-МГл2;
Здесь bordfunc — функция, вычисляющая граничные значения (без
контроля принадлежности точки границе области).
function ub=bordfunc(х)
ub=prod(x);
Возьмем х0=[0.5 0.5], имеем точное значение иргес=0.2500. При 4-х
запусках программы были получены следующие результаты (всюду n=io.o):
Mu=0.20"61, За=.0.0830, 5=0.1757.
Mu=0.2447, 30=0.0920, 5=0.0213.
Mu=0.1873, 30=0.0867, 8=0.2507.
Mu-0.1974, 30=0.0853, 5=0.2103.
Метод Монте-Карло
689
Здесь обозначено:
□ Ми — приближенное значение гармонической функции;
П Зо=з ■ JD^ —доверительный интервал;
П 5=|Mu-uprec| /Uprec — относительная погрешность.
Анализ результатов показывает, что во всех случаях Upr.ec укладывается в
интервал Mu±3o, относительная погрешность варьируется от 2% до 25%,
причем приближенное значение во всех 4-х случаях меньше точного.
Для другой точки х0=[0.1 0.9] результаты получились гораздо хуже: в 4-х
просчетах относительная погрешность принимала значения от 18% до 63%, хотя
по-прежнему во всех случаях иргес=о.09 укладывалось в интервал ми+за.
Рассмотрим пример 17.4.
ЙП^)й©р^^Мё;^.с1^^йнь1хблуждшйЩ с1тквадр^тной реткой ^.¾^
I ;.йП"К".ЬЙ:.Т,.,
В другом варианте метода случайных блужданий используется квадратная
сетка с некоторым шагом h, так что координаты узлов xi=i-h, x2=j-h (по-
прежнему считаем, что область g — единичный квадрат). Случайная
траектория состоит из узлов сетки, переход от узла (i,j) к любому из соседних с
ним узлов (i+i,j), (i-i,j), (i,j+i) и (i,j-l) происходит с вероятностью
0.25, обрыв траектории возникает при выходе на границу.
В функции laplas_grid, реализующей этот метод, параметр L — число
шагов h, укладывающихся на стороне квадрата, так что h=i/L.
function [Mu,Du]=laplas_grid(xO,LfN)
sumU=0; sumD=0; h=l/L;
for k=l:N
i=round(x0(1) +L); j=round(x0(2)*L);
while (i~=0) & (i~=L) & (j~=0) £ (j~=L)
r=rand;
if r<0.25
i=i+l;
elseif r<0.5
i=i-l;
elseif r<0.75
else
end
end
690
Глава 17
xfoord=[i*h j*h] ;
ubord=bordfunc(xbord);
sumU=sumU+ubord;
sumD=sumD+ubord',2;
end
Mu=sumU/N;
M2=sumD/N;
Ои=М2-Мил2;
Возьмем хО-юл 0.9], имеем uprec=o.09. При 4-х запусках программы
были получены результаты (всюду n=ioo, l=io):
Mu=0.0800, Зст=0.0285, 6=0.1111.
Mu=0.0960, 30=0.0400, 5=0.0667.
Mu=0.0830, 30=0.0363, 8=0.0778.
Ku=0.0870, За-0.0419, 5=0.0333.
Анализ результатов показывает, что во всех случаях ирсес=0.09 укладывается
в интервал ми±зо, относительная погрешность варьируется от 3% до 11%,
причем приближенное значение в двух случаях меньше точного, а в других
двух — больше.
Рассмотрим теперь пример 17.5.
рЬр^нер: 17:5. Метод случайных блужданий по.i^gRae^^c^^'ijg^^T^'^-l
Третий вариант метода случайных блужданий называется блужданием по
сферам (в двумерном случае получается по окружностям). Случайная
траектория строится так. Находясь в очередной точке траектории х, проводим
сферу (окружность) некоторого радиуса r с центром в этой точке, которая
не пересекает границу области. На ней берем следующую случайную точку
х ■, распределение точек на сфере (окружности) равномерное. Процесс
прекращается, когда очередная точка оказывается достаточно близко к границе.
Чтобы как можно скорее выйти к границе, радиус сферы (окружности)
всякий раз будем брать максимально возможный, т. е. равный расстоянию от
центра до границы.
Вспомогательна;! функция nearstborder ищет радиус r и точку границы
xborder, ближайшую к центру.
function [R,xborder]=nearst_border(x)
хх=[х 1-х];
R=min(xx);
if R=x-(1)
xbprder=[0 x(2)];
Метод Монте-Карло
691
elseif R==x(2)
xborder=[x(l) 0];
elseif R=l-x(l)
xborder=[l x(2)];
else
xborder=[x(l) 1];
end
В функции lapiascircie, реализующей метод случайных блужданий по
окружностям, параметр г — расстояние точки до границы, при котором
последняя считается достигнутой.
function [Mu,Du]=laplas_circle(xG,r,N)
sumU=0; sumD=0;
twopi=2*pi;
for i=l:N
x=xO ;
while 1
[R,xbord]=nearst_bord(x);
if R<r
break
end
phi=twopi * rand;
cs=cos(phi);
sn=sin(phi);
omega=[cs sn];
x=x+R* omega;
end
ubord=bordf utic (xbord) ;
sumU=sumU+ubord;
sumD=sumD+ubordA2;
end
Mu=sumU/N;
M2=sumD/N;
Du=M2-MuA2;
Возьмем x0=[0.i 0.9], имеем uprec=o.09. При 4-х запусках программы
получены результаты (всюду n=ioo, г=о.05):
Ми=0.0742, Зст=0.0366, 5=0.1751.
Mu=0.0S56, Зо=0.0262, 5-0.3810.
692
Глава 17
Mu=0.0981, За=0.0377, 5=0.0900.
Mu=0.0664, Зо=0.0281, 5=0.2620.
Анализ результатов показывает, что иргес=о.оэ укладывается в интервал
Mu+Зст во всех случаях, кроме второго, относительная погрешность
варьируется от 9% до 38%, причем приближенное значение в трех случаях меньше
точного, а в одном — больше.
Общий вывод по трем реализациям метода случайного блуждания для
решения уравнения Лапласа (не очень основательный ввиду недостаточности
экспериментального материала): наилучшие результаты дает метод
блуждания по квадратной сетке.
Применим этот метод для решения уравнения Пуассона (пример 17.6):
_- + -_ = f(x,y).
ох; the.
Для этого уравнения метод Монте-Карло несколько видоизменяется: вдоль
траектории суммируются значения функции f и,у), взятые с
коэффициентом — o.25-h2 (h — шаг сетки). Когда траектория достигает границы, к
сумме добавляется граничное значение функции и.
; Пример 17.6. Решение уравнения Пуассона методом блуждании ~Я . ]
; по квадратной сетке й . *ч* - - , .-. Ц»ф:~.< $*-\ *..ю;.% ■*'*■- \
Для примера в качестве области опять возьмем квадрат, граничные условия
будем считать однородными (т. е. нулевыми), правую часть примем
f (х, у) =-1. В такой постановке эта задача имеет интересную физическую
интерпретацию: функция и(х,у) (решение уравнения Пуассона)
представляет собой скорость течения вязкой жидкости в каждой точке нормального
сечения трубы. Нулевые граничные значения описывают прилипание
вязкой жидкости к стенкам трубы. Физический смысл правой части уравнения
Пуассона (у нас — константа, равная -1) — это градиент давления вдоль
трубы. Для случая трубы с квадратным сечением точное решение уравнения
Пуассона выражается в виде двойного ряда Фурье. При желании можно
было бы сравнить с ним решение, подученное методом Монте-Карло. Вместо
этого мы сравниваем его с решением, полученным классическим методом
сеток (см. разд. 12.8.4).
В функции poissongrid, построенной, в основном, по образцу функции
lapiasgrid, реализующей метод случайных блужданий по квадратной
сетке, смысл входных и выходных параметров тот же. Случайной величиной,
математическое ожидание и дисперсию которой находит функция
poisson_grid, является сумма, накопленная вдоль отдельной траектории (в
программе — переменная т). Функция right_func вычисляет значение пра-
Метод Монте-Карло
693
вой части (в примере эта константа равна -1), функция bordfunc вычисляет
граничное значение (в примере эта константа равна о).
function [Mu, Du]= poisson_grid(xO,L,N)
sumU=0; sumD=0,- h=l/L; coeff=-0.25*h"2;
for k=l:N
i=round(xO(l)*L); j=round(xO(2)*L); T=0;
while (i~=0) s (i-=L) & (j~=0) & (j~=L)
sumP=sumP+l;
r=rand;
if r<0.25
i=i+l;
elseif r<0.5
i=i-l;
elseif r<0.75
else
end
x=[i j]*h;
f=coeff*right_func(x);
T=T+f;
end
T=T-f;
ubord=bordfunc(x);
T=T+ufoord;
sumU=sumU+T;
sumD=sumD+T"2;
end
Mu=sumU/N;
M2=suuiD/N;
Du=M2-Mu~2;
Возьмем x0=[0.5 0.5]. При 4-х запусках программы получены результаты,
приведенные ниже (всюду n=ioo, l=io). Для сравнения, значение Ми,
найденное методом сеток (см. разд. ]2.8.4), равно о.0731. С учетом этого
значения выбиралась относительная погрешность 5.
Ми=0.0743, 30=0.0160, 6=0.0164.
Ми=0.0725, Зо=0.0154, 6=0.0082.
694
Глава 17
Mu=0.0660, Зо=0.0187, 5=0.0971.
Mu=0.0723, 30=0.0148, 6=0.0109.
Возьмем х0=[0.1 0.9]. При 4-х запусках профаммы получены результаты
(всюду ы=юо, ь=ю). Метод сеток для этих же данных дал ми=о.0128.
Ми=0.0057, 30=0.0047, 6=0.5547.
Ми=0.0124, 30=0.0119, 6=0.0313.
Ми=0.0122, 30=0.0068, 5=0.0469.
Ми=0.014'8, 30=0.0081, 5=0.1563.
Значения Ми были вычислены и для всех остальных внутренних точек
решетки (для фаничных точек взято значение ми=0), после чего были
построены линии уровня ми для значений v=o.oi:0.oi:0.07 (рис. 17.2).
function poisson__graph
rand ('state',0);
N=100; L=10;
Xmin=0; Xmax=l; h=0.1;
X0=Xmin:h:Xmax;
Ymin=0; Ymax=l;
Y0=Ymin:h:Ymax;
[X Y]=meshgrid(X0,Y0>;
s=size(X);
Z=zeros (s.) ;
for i = 2:s(1)-1
for j = 2:s (2)-1
xO = lX(i,j); Y(i,j)];
[Mu, Du] = poisson_grid(xO,L,N);
Z(i,j) = Mu;
end
end
V=0.01:0.01:0.07;
contour (X, Y, Z,V) ;
hold on;
grid;
xlabel('xl')
уlabel('x2')
title. {'Решение уравнения Пуассона методом Монте-Карло',...
'FontName',•Courier')
Метод Монте-Карло
695
Рис. 17.2. Линии уровня в задаче Пуассона
Рекомендуется сравнить этот рисунок с более "регулярным", приведенным в
разд. 12.8.4, где решение той же задачи найдено методом сеток.
17.6. Моделирование
случайных процессов
Иногда метод Монте-Карло позволяет изучать процессы, в которых
большую роль играет случайность и для которых затруднительно построить
математическую модель стандартными методами теории вероятностей. Подход
заключается в том, что строится имитация изучаемого процесса и
многократно разыгрывается с использованием датчика случайных чисел
(пример 17.7).
{ Пример 17.7: Прогнозирование случайного процесса ■'-- u *-*■*'''\%&^г1У. W'4
Рассмотрим случайный процесс, являющийся примером процесса рождения
и гибели (скорее "гибели и восстановления"). Мы построим модель, с
помощью которой можно делать прогнозы о ходе этого случайного процесса и
подбирать значения параметров, обеспечивающие его устойчивость. Время,
определяющее течение процесса, будем считать дискретным, так что все
величины, характеризующие состояние процесса, маркируются моментами
времени t=i, 2, ... Перечислим эти величины.
696
Глава 17
В цехе имеется п однотипных станков, из них в любой момент t исправных
mt, остальные n-mt — неисправные. Любой исправный станок к следующему
моменту с вероятностью р может выйти из строя, т. е. стать неисправным.
Имеется и рабочих, каждый из которых может заниматься ремонтом одного
неисправного станка. В любой момент времени в ремонте находится
rc=min(u,n-int) станков и любой из них к следующему моменту с
вероятностью q может быть отремонтирован, т. е. стать исправным.
В функции workshop описанные процессы моделируются методом Монте-
Карло.
function m=workshop(n,u,p,q,re)
X=0;
for i=l:m
if rand<p
m=m-l;
end
end
r=min[[u n-m]);
Y=0;
for i=l:r
if rand<q
Y=Y+1;
end
end
m=m+(Y-X);
Возьмем n=ioo, m=ioo, u=io, p=0.05, q=o.2. Возвратим датчик случайных
чисел в начальное состояние — rand( 'state' , 0) и, выполнив 99 раз
команду m=workshop(n,u,p,q,m), получим 100 значений переменной т".
100, 95, 90, 88, 87, 84, 82, 78, 77, 77, 72, 71, 73, 73, 72, 67, 63, 62, 58, 59,
58. 56, 53, 53, 52, 49, 48, 47, 47, 48, 45, 41, 39, 41, 41, 40, 41, 42, 42, 43,
44. 44, 44. 45, 42, 45, 48, 47, 46. 48, 49, 47, 46, 43, 41, 40, 39, 37, 38, 36,
34, 34, 35, 36, 31, 33, 32, 32, 34, 35, 34, 31, 33, 33, 35, 39, 41, 42, 41, 41,
43, 42, 41, 41, 39, 40, 40, 43. 43. 43, 45, 46, 42, 38, 40, 38, 39, 38, 35, 35.
Видим, что количество исправных станков медленно, но верно убывает, так
что за 99 тактов их осталось примерно треть. Очевидно, 10 ремонтников
недостаточно для поддержания работоспособности цеха.
Попробуем теоретически оценить количество ремонтников, необходимое
для того, чтобы процесс был стационарным, т. е. чтобы среднее количество
исправных станков оставалось неизменным в течение большого (потен-
Метод Монте-Карло
697
циально неограниченного) числа тактов. Рассмотрим случайную величинух —
количество станков, которые за один такт выходят из строя. Если число
исправных станков к началу такта было ш, вероятность выхода из строя за
один такт любого станка равна р, а выход из строя отдельных станков —
независимые случайные события, то математическое ожидание случайной
величины х равно тр. Рассмотрим случайную величину y — количество
станков, отремонтированных за один такт. Пусть количество ремонтников
u&i-m, где n-m — количество станков, неисправных к началу такта. Тогда все
неисправные станки находятся в ремонте. Если завершение за один такт
ремонта каждого отдельного станка — независимые случайные события с
вероятностью q, то математическое ожидание случайной величины y равно
(n-m)q.
Случайная величина приращение количества исправных станков равна
разности y-x, ее математическое ожидание равно (n-m)q-mp. Условие
стационарности процесса заключается в том, что это математическое ожидание равно о.
Отсюда получаем m(p+q)=nq. Таким образом, стационарное количество
исправных станков m0=nq/ (p+q), а количество ремонтников, минимально
необходимое для поддержания стационарного количества исправных станков,
u>Uo=n-mo=np/ (p+q) -
Рассмотрим численный пример. Пусть, как прежде, п=юо, p=o.os,
q=0.2. Тогда стационарное значение количества исправных станков
mp=tiq/(p+q)=80, минимально необходимое количество ремонтников u0=n-
-mo=np/(p+q)=20.
Будем считать, что начальное количество исправных станков равно
стационарному: m=m0-80, количество ремонтников равно минимально
необходимому: u=Uo=20.
Зададим randСstate',0) И, ВЫПОЛНИВ 99 раз команду m=workshop(n,..u,p,q,m),
получим 100 значений переменной т.
80, 81, 79, 77, 78, 79, 79, 60, 77, 81, В1, 82, 83, 86, 83, 86, 84, 88, 83, 83,
85, 82, 82, 79, 74, 74, 76, 75, 74, 71, 73, 74, 76, 73, 73,' 77, 76, 73, 75, 74,
69, 69, 69, 67, 70, 72, 73, 74, 78, 81, 84, 83, 81,. 83, 84, 85, 88, 78, 78, 78,
77, 74, 76, 78, .83, 82, 83, 82, 84, 82, 77, 78, 80, 7В, 81, 80, 81, 77, 79, 81,
77, 78, 77, 75, 77, 81, 83, 80, 81, 81, 81, 77, 73, 69, 71, 69, 65., 62, 59, 56.
Среднее значение, которое легко подсчитать в процессе эксперимента,
равно 77.55, оно не так уж сильно отличается от математического ожидания
то=80, однако разброс значений случайной переменной т весьма велик:
пъах=8В, ^„^=56. Это объясняется тем, что на каждом шаге стартовым
значением переменной m является не ее математическое ожидание т0, а то, что
получено на предыдущем такте.
698
Глава 17
Более развитая вероятностная модель процесса порчи и восстановления,
позволяющая оценить не только математическое ожидание, но и дисперсию
(т. е. разброс), основана на аппарате цепей Маркова. Мы ее рассматривать
ие станем, а вместо этого проведем еще один вычислительный эксперимент
С функцией workshop.
Увеличим число ремонтников, взяв и=25 (значения остальных величин
оставим прежними). Снова зададим rand С state", о) и получим другие 100
значений переменной ш:
80, 81, 79, 78, 79, 81, 82, 80, 79, 83, 80, 80, 82, 81, 80, 81, 77, 80, 80, 82,
79, 76, 80, 77, 73, 78. 82, 85, 83, 80, 84, 82, 83, 84, 83, 80, 79, 83, 80, 75,
77, 72, 75, 78, 72, 72, 74, 77, 79, 79, 81, 77, 79, 78, 80, 68, 69, 75, 72, 70,
67, 70, 70, 68, 70, 72, 73, 76. 80, 79, 78, 78, 83, 81, 82, 80, 78, 77, 78, 79,
82, 86, 86, 87, 8'7, 80, 78, 78, 83, 73, 75, 78, 75, 78, 75, 78, 74, 75, 82, 82.
Среднее значение 78.26 стало немного ближе к математическому
ожиданию, разброс несколько уменьшился: itwx=87, itiain=67.
Рассмотрим пример 17.8.
| Пример 17.8. Имитационная модель матричной игры
В разд. 16.3 рассматривалась игра "Жулик" с тремя чистыми стратегиями у
каждого участника и с платежной матрицей, воспроизведенной в табл. 17.1
(содержательные наименования стратегий заменены их римскими номерами).
Таблица 17.1
I
II
III
I
1
-1
2
II
-1
1
-1
III
-2
1
0
Методами линейного программирования в разд. 16.3 были найдены: цена
этой ипэы v=i/5 и оптимальные смешанные стратегии игроков р=[0 3/5
2/5], q=[2/5 3/5 0].
Теперь построим имитационную модель игры, которая позволит на деле
оценить эти и другие стратегии.
function v=trickster(p,q,N)
R=[l -1 -2
-111
2-1 0];
Метод Монте-Карло
699
sumA=0;
P=oumsuzn(p) ; Q=cumsum(q);
for k=l:N
r=rand;
if r<P(l)
i=l;
elseif r<P(2)
i=2;
else
i=3;
end
r=rand;
if r<Q(l)
j-i;
elseif r<Q(2)
j=2;
else
j=3;
end
sumA=sumA+A(i, j) ;
end
v=sumA/K;
Зададим число повторений игры n=ioo, и пусть игроки придерживаются
своих оптимальных стратегий. Первый игрок получит выигрыш v=o.2.
Пусть первый игрок придерживается той же стратегии р, а второй —
стратегии q=[i/3 1/3 1/3]. В этих условиях первый игрок получит выигрыш
v=6.42. Вывод: попытка второго игрока отклониться от оптимальной
стратегии увеличила его проигрыш.
С функцией trickster можно провести и другие эксперименты.
17.7. Случайный поиск
Имеются два основных направления применения метода Монте-Карло для
поиска минимума функции.
Первое направление, которое мы подробно рассматривать не будем, —
локальный поиск, во многом аналогичный детерминированному (например,
градиентному) поиску, который представляет собой последовательный
переход от одной точки к другой, близкой точке. Отличие от детерминирован-
700
Глава 17
иого поиска заключается в том. что каждый шаг делается с той или иной
степенью случайности. Например, достигнув очередной точки, делают из
нее несколько небольших пробных шагов в случайных направлениях и для
перехода к следующей точке выбирают из этих шагов тот, который дат
наименьшее значение целевой функции в пробной точке. Если все пробные
шаги приводят к увеличению значения функции — минимум достигнут.
Второе направление — глобальный поиск, обычно являющийся
подготовительным этапом перед локальным спуском (случайным или
детерминированным). Этот этап особенно актуален для мпогоэкстремальных функций,
когда результат локального поиска кардинально зависит от выбора
начальной точки — именно эти точки (при отсутствии информации о "глобальном
строении" целевой функции) полезно выбирать случайным образом.
Более конкретно этот алгоритм (его иногда называют набросовым)
заключается в следующем. На область предполагаемого поиска "набрасывается"
некоторое количество случайно выбранных точек хд (i=i, ..., n), затем из
каждой точки Xi делается локальный спуск в точку х±'. В качестве точки
глобального минимума принимается та точка х**, для которой значение
целевой функции f (xi'l минимально:
f (х") = min f(x^).
i-l N
Рассмотрим пример 17.9.
I Пример 17.9. Минимизация функции методом Монте-Карло .■"--.■ ,/e%Jf "*"-;:
Рассмотрим задачу о минимизации функции, являющейся взвешенной
суммой абсолютных величин комплексной переменной z и многочлена 7-й
степени w=z (z2+l) (Cz-2)z-hJ) ((z+2)2+4):
function y=abspoly7(x,pl,p2)
z=coraplex (x (1) , x (2) ) ;
w=z+{гл2+1)* ((z-2)л2+4)* ((z+2)л2+4);
y=pl*abs(z)+p2*abs(w);
Эта функция имеет семь локальных экстремумов, один из них с нулевым
значением функции в точке х-[о,-0] — глобальный. Будем исходить из того,
что известна область, в которой расположены все локальные экстремумы, —
это квадрат 4X4 с центром в начале координат. Определим массив из n пар
случайных чисел, равномерно распределенных в этом квадрате: г=-4+8*
*rand(2,N). Например, при N=4 получится
г =[3.6010 0.8547 3.1304 -0.3483
-2.1509 -0.1121 2.0968 -3.8520]
Метод Монте-Карло 701
В компьютерном эксперименте на этот квадрат было набросано 20
случайных точек, и от каждой из них, как от начальной, был выполнен поиск
минимума путем обращения к функции
[х,fval]=fminsearch(Eabspoly7,xO, options, pi,p2)
(значения коэффициентов в abspoly7 взяты pi=o.oi, p2=o.oi).
В табл. 17.2 представлены все найденные локальные минимумы, в
последней строке — глобальный минимум.
Таблица 17.2
к1
2.0000
2.0000
-2.0000
-2.0000
х2
2.0000
-2.0000
2.0000
-2.0000
fval
0.028 4
0.0284
0.0284
0.0284
xl
0.0000
0.0000
0.0000
| х2
| 1.0000
| -1.0000
1 0.0000
fval
0.0101
D.0101
0.0000
Случайный выбор начальных точек. "£
4
-" 3
2
■: 1
Ч 0
т1
-2
-3
-А
-4 " -2:. 0 - 2 .4. Б
х1
Рис. 17.3. Случайный поиск минимумов
На рис. 17.3 представлены линии уровня функции abspoly?, n=20
случайных точек (изображены маленькими кружками), найденные от каждой из
702
Глава 17
них, как от начальной точки, локальные минимумы (изображены большими
кружками).
Переход от каждой начальной точки к локальному минимуму изображен
отрезком прямой. Реально перемещение шло по зигзагообразным
траекториям, но их изображение загромоздило бы рисунок.
function Rand^search
Xmin=-4.5; Xmax=4.5; h=0.2;
XO=Xmin:h:Xmax;
Y0=X0;
axes ('Xlim',[Xmin Xmax],'Ylim',[Xmin Xmax]);
axis equal;
[X Y]=meshgrid(XO, YO);
s=size(X);
Z=zeros(s);
p]=0.01; p2=0.01;
for i = l-.s(l)
for j = l:s(2)
x = [X(i,j); Y(i,j)];
z = abspoly7(x,pl,p2) ;
Z(i,j) = z;
end
end
%M=max(.max(Z)) ;
v=D:h:0.9;
V=l:10;
hold on;
contour(X,Y,Z,[v V]);
xlabel{'xl'); ylabel('x2');
title ('Случайный выбор начальных точек'f'FontName','Courier');
N=20;
r=-4+8*rand(2,N);
options = [] ;
globalnu.n= [0;0;Inf ];
localmin=zeros(3, N);
for j=l:M
x0=r<:, j );
Метод Монте-Карло
703
plot ([хО(1)Ь [х0(2)], 'Marker1, '.*, 'MarkerSize', 10);
[х,fval]=fminsearch(Sabspoly7,x0,options,pi,р2);
localmin (:, j ) = [x; fi/al] ;
if fval<globalmin(3)
globalmin=[x;fval];
end
plot([x(l)1,[x(2)], 'Marker', '.', 'MarkerSize', 20);
plot([x0(l) x(l)],[x0(2) x (.2) J );
end
localmin'
globalmin'
Приложения
Приложение 1
Помощь в системе MATLAB
Система MATLAB снабжена довольно подробным справочным файлом,
который позволяет получить информацию как по собственно пакету MATLAB,
так и по всем его приложениям. Комплект документации, включая файлы в
PDF-формате, занимает полный CD-ROM.
*Jk Preferences
©General :
itl- Fonts
[- Colors |
i+bCommand Window
— Command History
IB Editortoebugger
\~Ш
\ ■ Web
i—Current Directory
у Workspace
- Array Editor
- GUIDE
l+bFigure Copy Template
й-Stmulink
Help Preferences
i Product tiller
' -iftWw4:-.&:iJi
Enabling the product filter allows you to select the
products displayed in the Help Navigator.
! Select products...
| P Enable product filter
~~ -jfeHelp Product Filter|
Select the products to display In the Help Navigator.
General
p Keep confer
P Release Notes
P Installation
P MATLAB
P Excel Link
P MATLAB Builder for COM
P MATLAB Builder for Excel
P MATLAB Compiler
P Bioinformatics Toolbox
P Curve Fitting Toolbox
^J;
Select All (
OK
OK J
Cancel
Clear All j
Cancel j
Apply
h'efp.
Help
Рис. П1.1. Отбор пакетов расширения,
включаемых в текущую справочную базу
708 Приложение 1
Справочная система MATLAB 7 может быть настроена на любой перечень
установленных пакетов. Чем меньше пакетов нам понадобится в очередном
сеансе, тем меньшей по объему будет сформирована текущая справочная
база. И тем быстрее будут находиться интересующие вас термины.
Настройка осуществляется по цепочке команд File | Preference | Help (Файл |
Предпочтения | Справка). В появившемся диалоговом окне следует отметить
флажок Enable product filter (Разрешить фильтр пакетов) и нажать кнопку
Select products (Выбор пакетов). В очередном диалоговом окне имеется
возможность быстро выделить все установленные на нашем компьютере пакеты
(кнопка Select All (Выбрать все)) или метить только те флажки, которые нам
понадобятся в ближайшее время (рис. П1.1).
Поиск по ключевым словам
Существует несколько способов получить ответ по интересующему вас
термину.
П Набрать в окне Command Window (Окно команд) команду help, задав ей в
качестве параметра искомое ключевое слово, например, double:
» help double
DOUBLE Convert to double precision.
DOUBLE(X) returns the double precision value for X.
If X is already a double precision array, DOUBLE has
no effect.
DOUBLE is called for the expressions in FOR, IF, and WHILE loops
if the expression isn't already double precision. DOUBLE should
be overloaded for all objects where it makes sense to convert it
into a double precision value.
Ответ по такому запросу будет получен только в том случае, если среди
системных файлов MATLAB обнаружит файл double.m. Текст выдаваемой
справки представляет собой начальный комментарий соответствующего
m-файла.
П Набрать в окне Command Window (Окно команд) команду lookfor с
искомым ключевым словом Или набором ключевых слов, заключенных в
апострофы:
» lookfor 'hyperbolic sine'
ASINH Inverse hyperbolic sine.
SINH Hyperbolic sine.
Помощь в системе MATLAB
709
ASINH Symbolic inverse hyperbolic sine.
SINH Symbolic hyperbolic sine.
»
Ответ по такому запросу содержит имена га-файлов и строки, в которых
встречается указанный набор ключевых слов. Искать, например,
ключевое слово double по команде lookfor особого смысла не имеет, т. к.
встречается оно в довольно большом количестве файлов:
■» lookfor double
DBLQUAD Numerically evaluate double integral.
HEX2NUM Convert IEEE hexadecimal to double precision number.
STR2D0UBLE Convert string to double precision value.
DOUBLE Convert to double precision.
PNDANIM2 S-function for animating the motion of a double pendulum.
PNDANIM3 S-function for animating trie motion of a double pendulum.
AX_BLOCK_DCLK Callback file for ActiveX Block's double click event.
FINARGDBLE Format an argument into a double array of NaN padded rows.
□ Набрать в окне Command Window (Окно команд) команду doc, задав ей в
качестве параметра искомое ключевое слово, например, sinh:
» doc sinh
1^ Help
File Edit View Go -Favorites Desktop Window Help
Help H.avi gator _ x
.Corielnls§ Imlex|-S«arch | Demm | "
—О Begin Here -^
Э> Ф Release Notes
'№0 Installation
fe^ MATLAB
4 О Getting Started
! 9*-Ф Examples
ss-JJll Desktop Tools and Development
1 $-¾ Mathematics
| a ©Programming
1 ^1-¾ Graphics
зд-IQ 3-D Visualization
1 >) © Creatin Gra hical User Ihterfac
:-+-¾ Functions - Gate onca! List
i
1
1
as-Desktop Tools and Development
b-Mathematics —'
Si-Programming and Data Types
ijsFiIel/O
^-Graphics
Чг-3-Т) Visualization
man
•v
^■♦O'i i»
Tlllffi | snh (MATLAB Fumaions)
MATLAB Function Reference
sinh
Hyperbolic sine of an argument in radians
Svntax
Y = sinh(X)
Description
z\
L2 El-
The si nh function operates element-wise on arrays.- |
The function's domains and ranges include
values. All angles are in radians.
complex j
Рис. П1.2. Результат выполнения команды doc sInn
710
Приложение 1
В результате удачного поиска произойдет переход в окно Help (Справка), в
правой части которого будет открыта первая страница документа с
указанным заголовком (рис. П1.2).
Команды help и doc позволяют организовать поиск информации о термине,
у которого мы помним только начальные буквы. После их набора следует
нажать клавишу <ТаЬ> и в окне команд появится список терминов,
начинающихся с указанной последовательности букв (рис. П1.3).
». help sin
Ч1ЯН^1НН ж
sine
Sincosexp
sind
single
singleMath
sinh
sinint ▼
Рис. П1.3. Выбор термина по начальным буквам
Использование Help-навигатора
Левая часть окна справочной системы представлена Help-павигатором, с
помощью которого можно сравнительно просто добраться до интересующей
вас информации. В нем расположены 4 вкладки:
□ Contents (Содержание) — оглавление доступных разделов;
□ Index (Указатель) — набор ключевых слов, относящихся к выделенному
подразделу и упорядоченных по алфавиту;
П Search (Поиск) — окно поиска ключевого слова, набираемого
пользователем;
□ Demos (Примеры) — оглавление тестовых примеров;
На вкладке Contents (Содержание) находится перечень тех пакетов
расширений, которые вы отметили при настройке справочной системы (рис. П1.4).
Раскрывая соответствующий раздел оглавления и перебирая появляющиеся
подразделы, мы можем перейти на нужный фрагмент справочной
информации. На рис. П1.5 продемонстрирован переход в кадр ео справкой о
магических квадратах. Конечно, такой поиск имеет смысл только тогда, когда мы
точно знаем, где находится интересующая нас информация.
Помощь в системе MATLAB
711
Help Havigator
Contorts J index | Search I Ретм|
■~ ъ& Release Notes
f-ф Installation
£-<3* MATLAB
:*- 6^ Excel Link
f& MATLAB Builder for COM
if:-*§> MATLAB Builder for Excel
;ii <3? MATLAB Compiler
'i ^Biomformatics.Toolbox
iv ф Curve Fitting Toolbox
■?'■ c^ Fixed-Point Toolbox
k: & Fuzzy Logic Toolbox
$ Ф Genetic Algorithm and Direct Search T
f'-ф Image Processing Toolbox
:j"Tsi> Mapping Toolbox
it Ф Neural Network Toolbox
!;-■ t3> Optimization Toolbox
■•?■ c3*Partial Differential Equation Toolbox
■;i ^ Signal Processing Toolbox
i* Ф Spline Toolbox
■ft <ф Statistics Toolbox
■r.-t& Symbolic Math Toolbox
£-<& Simuhnk
fc <3> Simulink Fixed Point
if^Stateflow
Т>-Ф Signal ProcessingBIockset
0 Support and Web Services
Л1 I ±1
*• *+
\&\k
~3
Tils [Release 14: Begin Нею
Begin Here ,¾..^¾ й
Release 14
If You Are Upgrading from a
Previous Reiease...
• Release Notes
Summarizes new features, bug fixes,
upgrade issues, etc.
Video Tutorials
Seven audio-video tutorials are the best way
to learn the new features in MATLAB.
If You Are Using MATLAB for the
First Time...
At the heart of MATLAB is a new language that
you must learn before you can fully exploit its
Dower. This isn't as hard as it miaht sound: vpu Zi
-iJ I ^.. Л
Рис. П1.4. Оглавление из отобранных пакетов расширений
Чаще всего нам бывает известен только некоторый термин или сочетание
терминов. В этом случае может помочь поиск по индексу (вкладка Index)
или по контексту (вкладка Search). На рис. П1.6 отображены результаты
поиска словосочетания Magic Squares. В левой части навигатора отображаются
названия всех разделов, где был обнаружен заданный контекст.
При поиске по индексу разумно набрать в поле ввода Title (Заголовок)
первый символ нужного термина, а спустя некоторое время продолжить набор.
При этом в справочной базе все разделы отсортировываются по первой
букве, что ускоряет последующий поиск. На рис. П1.7 показаны результаты
поиска по индексу, равному qr.
Вкладка Demos (Примеры) выдает в левой части окна список пакетов
расширений, снабженных демонстрационными примерами. Как правило, в
каждом из разделов содержится не по одной демонстрационной программе.
34 За* 899
712
Приложение 1
Help JS aydgafcoE:
cotttrts | к-йих| s*atch| Овтая|
Г
"Л
Begin Here j
Release Notes
Installation
MATLAB
О Getting Stated
j] Introduction
^i-Matrices and Arra s
3-1 atnces and Ma. u? S ' _s
■Entering Matrices
sum, transpose, and diag
-Subscripts
The Colon Operator
The magicFunctton
Э Expressions
to-Working "with Matrices
"t-More About Matrices and Arr
S-Controlling Command Windo''
Й-Graphics
ij-j Programming
■p-Creating Graphical Userlnterfac
Ti-Desktop Tools and Development
Ф Examples
-¾ Desktop Tools and Development
*• <* C!&|M.
THlff-1 Metrites and Ms#c Squares -- M«urtces end Arrays (Getting Started)
z]
Getting Started
Matrices and Magic Squares
S Sl-
Li MATLAB, a matrix is a rectangular array of
numbers. Special meaning is sometimes attached to
1-by-l matrices, which are scalers, and to matrices
with only one row or column, which are vectors.
MATLAB has otlier ways of storing both numeric and
nonnumeric data, but in the beginning, it is usually
best to think of everything as a matrix. The operations
in MATLAB are designed to be as natural as
possible. Where other programming languages work
with numbers one at a time, MATLAB allows you to
work with entire matrices quickly and easily. A good
example matrix, used throughout this book, appeal's in
the Renaissance engraving Melencolia I by the
German artist and amateur mathematician Albrecht
Diirer.
Рис. П1.5. Перелистывание оглавления
Help Navigator
Contorts| Index Search | Demos |
Search lor. j MbqIc Squares
I Tflla
Matrices andMa'eic S.ciuares Matrices and.
magic
The magic Function
pinv
Square Systems
Arrays
Matrices and Array's
Other Data Structures
Cell Arrays
Scripts
Flow Control
switch and case
Creating the User Interface
Simple Example
MATLAB Func
Matrices and Ai
MATLAB Func
Matrices and Li
Matrices and Ai
Getting Started
Programming
Programming
Programming
Programming
Programming
Usage Example
Stand-Alone Ap
♦» ■» С i a | ft
Title: j МаЫсэз and Mage Squares:; Matrices end Arrays (Getting Started) ^»J
Getting Started Ш ffl—
Matrices and Magic Squares
In MATLAB, a matrix is a rectangular array of
numbers. Special meaning is sometimes attached to
1-by-l matrices, which are scalers, and to matrices
with only one row or column, which are vectors. —
MATLAB has other ways of storing both numeric and
nonnumeric data, but in the beginning, it is usually
best to think of everything as a matrix. The operations
in MATLAB are designed to be as natural as
possible. Where other programming languages work
with numbers one at a time, MATLAB allows you to
work with entire matrices quickly and easily. A good
example matrix, used throughout this book, appears in
the Renaissance engraving Melencolia I by the
German artist and amateur mathematician Albrecht
Diirer. _____
Рис. П1.6. Поиск контекста
Помощь в системе MATLAB
713
Help; Navigator __ *
Conterts Шейк | Saorch I Demos |
; iStiiEtsiiiciii ■ !
' ii о £. Q B. 3¾ T U. X.W& "r Z. ■
Search hdex tor. |qr
Name I Product |
ipin Signal Pr... -»■
qrar MATLAB
qqplot Statistics...
a MATLAB
QR decomposition Statistics...
QR decomposition Curve Fitt .
QR -fecomposition 1AATLAB
«- -f С jS'M
Tflle: | qr (MATLAB Functions)
qr
Orthogonal-triangular decomposition
Sviitax
[Q,R] = qr(A) (/uiZ
[Q,R] = qr(A,0) (full
fO.R.El = or(A) /full
,j.
I
I
I
I
and spar: I
and spar: i
matrices, i
Рис. П1.7. Поиск по индексу qr
Кнопки-стрелки в верхней и нижней частях кадров помощи позволяют
перемещаться вперед и назад по заголовкам разделов или по. кадрам помощи.
Кроме того, над правым окном навигатора расположен раскрывающийся
список Title (Заголовок), в котором фиксируются разделы, просмотренные
во время текущего сеанса. Его можно использовать для повторного входа в
один из предыдущих разделов справочной базы (рис. ГЛ.8).
Help Mayigatpjr;
Conterts | index | Search | Demos |
— О Begin Here •<
i;)- & Release Notes
el t-S* Installation
■k $ MATLAB
fji- О Getting Stated
■Introduction
-Matrices and Arrays
j- Entering Matrices
[•-sum, transpose, ani
! Subscripts
l-The Colon Operate
I '- The magic Functiot-
*■ •* С | m i #*
THIk | Matrices ornl Magic Squares:: hlertrlces end Atrays (Getting Started)
Л41,№11М1-'«ШШ1Ш4и'№1-1Д
Mpsrices end Arrey$ (Getl^g Started)
CeHing Started:: (GettiTg Started
MATLAB
Rdeaj£ N; Begirt hfgrc ^_^__^_
zl
N
In
Special meaning is sometimes attached to 1-by-l matrices,
which are scalars, and to matrices with only one row or
column, which are vectors. MATLAB has other ways of
storing both numeric and nonnumeric data, but in the
beginning, it is usually best to think of everything as a matrix.
The operations in MATLAB are designed to be as natural as
possible. Where other programming languages work with
Рис. П1.8. Перечень справочных разделов,
активизированных в текущем сеансе
Поиск функций
Для ускорения поиска сведений о функции в файлах помощи
предусмотрены два систематизированных каталога — список функций, упорядоченных
по алфавиту и расклассифицированных по категориям (Functions — Cate-
714
Приложение 1
gorical List) и общий список всех функций, упорядоченных по алфавиту
(Functions ~ Alphabetical List) — рис. Ш.9.
Help. Bayi.gatqr.
Corterts|m»s| searetiJDOTosl
i-O Begin Here
'?■■ Ф Release Notes
ЧИФ Installation
' ^MATLAB
^1 О Getting Started
*■ & Examples
8-(¾ Desktop Tools and Development Environment
■»-© Mathematics
S- lb Programming
ifi (¾ Graphics
:•>■ Щ} 3-D Visualization
?!-© Creatin Gra ical User Interfaces
i ;!-1Й Functions — Cate orical List
t-Desktop Tools and Development Environment
s-Mathematics
^-Programming and Data Types
5 File I/O
Ift Graphics
&--3-D Visualization
ffi Creating Graphical User Interfaces
3jb Functions — Alphabetical List
* ■* С ! © ' *» '
T«W. | Fundions - Categorical List ffMTLAB Fimctlnis)_^
MATLAB Function Reference Ш —
Functions —
Categorical List
The MATLAB Function Reference
contains descriptions of all MATLAB
commands and functions.
Select a category from the following table
to see a list of related functions.
Desktop
TjoolsjJid.
Development
Startup, Command
Window, help, editing
and debugging, tuning,
Рис. П1.9. Поиск функций MATLAB
Приложение 2
Указатель свойств
графических объектов
В данном приложении приведен указатель свойств графических объектов,
используемых в книге.
Свойство Раздел
■ALim 7.3
ALimMode 7.3
AlphaData 7.7, 7.7
AlphaDataMapping 7Ji 7J
Alphamap 7.2
AmbientLightc.olor 7.3
AmbientStrength 10.2.1
BackFaceLighting- 10.2.1
BackgroundColor 8,8.1.1
BackingStore 7.2
BeingDeleted 8
Box 7.3
BusyAction 7.1, 8
ButtonDownFcn 7.1, 8, 8.1.1
Callback 7.1,8,8.1.1,8.1.3
CallbackObject 7.1
CameraPosition 7.3, 10.13
CameraPosi tionMode 7.3
716
Приложение 2
(продолжение)
Свойство
Раздел
CameraTarget
CameraTargetMode
CameraUpVector
Came raUpVe с to rMode
CameraViewAngle
CameraViewAngleMode
CData
CDataMapping
Children
CLim
CLimMode
Clipping
CloseRequestFcn
Color
Colormap
ColorOrder
CoiranandWindowSi ze
CreateFcn
CurrentAxes
CurrentCharacter
CurrentFigure
CurrentObject
CurrentPoint
Curvature
DataAspectRatio
DataAspectRatioMode
DeleteFcn
Diary
DiaryFile
7.3
7.3
7.3
7.3
7.3
7.3
7.7,8,8.1.2, 10.26
7.7, 10.26
7.1, 7.11
7.3
7.3
7.1,8
7.2
7.2, 7.4
7.2, 7.7
7.4
7.1
7.1, 8, 8.1.1
7.2
7.2
7.1
7.1
7.2
7.5
7.3, 7.7
7.3
7.1, 8, 8.1.1
7.1
7.1
Указатель свойств графических объектов
Свойство
Diffusestrength
Dithermap
DoubleBuffer
DrawMode
Echo
EdgeAlpha
EdgeColor
EdgeLighting
Editing
Enable
EraseMode
Extent.
FaceAlpha
FaceColor
FaceLighting
Faces
FaceVertexAlphaData
FaceVertexCData
FileMame
FixedColors
FixedWidthFontName
FontAngle
FontName
FontSize
FontUnits
FontWeight
Foreg roundColo r
Format
FormatSpacing
717
(продолжение)
Раздел
10.2.1
7.2
7.2
7.3
7.1
10.2.1
7.5, 10.26
10.2.1
7.6
8
7.4, 7.7
7.6
10.3.1
7.5, 10.26
10.20
10.25
10.3.1
10.27
7.2
7.2
7.1
7.3,8
7.3, 8
7.3,8
7.3,8
7.3,8
8, 8. 1. 1
2.4, 7.1
7.1
718 Приложение 2
(продолжение)
Свойство
GridLineStyle
HandleVisibility
HitTest
HorizontalRlignment
IntegerHandle
Interpreter
Interruptible
InvertHardcopy
KeyPressFcn
Language.
Layer
LineStyle
LinestyleOrder
LineWidth
ListBoxTop
Margin
Ma rker
MarkerSize
MarkerEdgeColor
MarkerFaceColor
Max
MenuBar
MeshStyle
Min
MinColormap
MinorGridLineStyle
More
Name
NextPlot
Раздел
7.3
8, 8.3.2
7.1,8
7.6,8,8.1.4
8.3.2
7.6
7.1,8
7.2
7.2
7.1
7.3
7.4
7.3, 7.4
7.3, 7.4
8
7.6
2.6.1, 7.4
7.4
7.4, 10.26
7.4, 10.26
8,8.1.5,8.1.6
7.2
10.2.1
8, 8.1.5,8.1.6
7.2
7.3
7.1
7.2
7.2
Указатель свойств графических объектов
719
(продолжение)
Свойство
NormalMode
■NumberTitle
PaperUnits
PaperOrientation
PaperPosition
PaperPositionMode
PaperSize
PaperType
Parent
PlotBoxAspectRatio
PlotBoxAspectRatioMode
Pointer
PointerLocation
PointerShapeCData
PointerShapeHotSpot
PointerWindow
Position
Projection
Recurs ionLimit
Renderer
RendererMode
Resize
BesizeFcn
Rotation
ScreenDepth
Screen'Size
Selected
SelectionHighlight
SelectionType
Раздел
10.3.1
7.2
7.2
7.2
7.2
7.2
7.2
7.2
7.1, 7.2
7.3
7.3
7.2
7.1
7.2
7.2
7.1, 7.2
7.2, 7.3,
7.3
7.1
7.2
7.2
7.2
7.2, 8.3.
7.6
7.1
7.1
7.1, 7.6
7.1,8
7.2
720
Приложение 2
(продолжение)
Свойство
Раздел
ShareColors
ShowHiddenHandles
SliderStep
SpecularColorReflectance
SpecularExponent
EpecularStrength
String
Style
Tag
TickLength
TickDir
TickDirMode
Title
TooltipString
Type
UIContextMenu
Units
UserData
Value
VertexNormals
VerticalAlignment
Vertices
View
Visible-
WindowB'uttonDownFcn
WindowButtonMotionFcn
WindowButtonUpF'cn
WindowStyle
XAxisLocation
7.2
7.1
8, 8.1.6
10.2.1
10.2.5
10.2.1
7.6.8,8.1.5,8.3.7
8.1.1
7.8,8, 8.3.7
7.3
7.3
7.3
7.3
8, 8.1.1
7.1
7.1, 8, 8.2
7.1, 8, 8.1.3
7.1,8
8, 8.1.5
10.3.1
7.6
10.25
7.3
7.1,8
7.2
7.2
7.2
7.2
7.3
Указатель свойств графических объектов
721
(продолжение)
Свойство
XColor
XData
XDir
XGrid
XLabel
XLim
XLimMode
XMinorGrid
XMinorTick
XScale
XTick
XTickLabel
XTickLabelMode
XTickMode
YAxisLocation
YColor
YData
YDir
YGrid
YLabel
YLim
YLiraMode
YMinorGrid
YMinorTick
YScale
YTick
YTickLabel
YTickLabelMode
YTickMode
Раздел
7.3
7.4, 7.6, 7.7
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.4, 7.6, 7.7
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
722
Приложение 2
(окончание)
Свойство
ZColor
ZDir
ZData
ZGrid
ZLabel
ZLim
ZLimMode
ZMinorGrid
ZMinorTick
ZScale
ZTick
ZTickLabel
ZTickLabelMode
■ZTickMode
Раздел
7.3
7.3
7.4, 7.6, 7.7
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
7.3
Литература
и интернет-источники
MATLAB
1. Андриевский Б. Р. Избранные главы теории автоматического
управления с примерами па языке MATLAB. — СПб.: Наука, 1999. — 467 с.
2. Андриевский Б. Р., Фрадков А. Л. Элементы математического
моделирования в программных средах MATLAB 5 и Scilab. — М.: Наука, 200 L —
286 с.
3. Ануфриев И. Е. Самоучитель MATLAB 5.3/б.х. — СПб.: БХВ-Петербург,
2004. - 736 с.
4. Герман-Галкин С. Г. Компьютерное моделирование полупроводниковых
систем в MATLAB 6.0. — СПб.: КОРОНА принт, 2001. — 315 с.
5. Глушаков С. В., Жакин И. А., Хачиров Т. С. Математическое
моделирование: MathCad 2000, MATLAB 5.3: Учебный курс. — М.: РОДИНА-
ФОДИО, 2001.-524 с.
6. Говорухин В. Н., Цибули и В. Г. Компьютер в математическом
исследовании: Maple, MATLAB, LaTex. — СПб.: Питер, 2001. — 624 с.
7. Гультяев А. К. MATLAB 5.2. Имитационное моделирование в среде
Windows. — СПб.: КОРОНА принт, 1999. — 288 с.
8. Гультяев А. К. MATLAB 5.3. Имитационное моделирование в среде
Windows. Практическое пособие. — СПб.: КОРОНА принт, 2001. — 432 с.
9. Гультяев А. К. Визуальное моделирование в среде MATLAB. — СПб.:
Питер, 2000. — 430 с.
10. Дьяконов В. П. MATLAB 5.0/5.3. Система символьной математики. —
М.: Нолидж, 1999. — 633 с.
11. Дьяконов В. П. MATLAB 6/6.1/6.5 + Simulink 4/5 в математике и
моделировании. Полное руководство пользователя. — М.: Солон, 2003. —
576 с.
12. Дьяконов В. П. MATLAB 6/6.1/6.5 + Simulink 4/5. Основы применения.
Полное руководство пользователя. — М.: Солон, 2002. — 768 с.
13. Дьяконов В. П. MATLAB 6: Учебный курс. — СПб.: Питер, 2001. —
592 с.
724
Литература и интернет-источники
14. Дьяконов В. П. Simulink 4. Специальный справочник. — СПб.: Питер,
2002. - 528 с.
15. Дьяконов В. П. Справочник по применению системы PC MatLab. — М.:
Физматлит, 1993. — 112 с.
16. Дьяконов В. П., Абраменкова И. В. MATLAB 5. Система символьной
математики. — М.: Нолилж, 1999. — 633 с.
17. Дьяконов В. П., Абраменкова И. В. MATLAB. Обработка сигналов и
изображений. Специальный справочник. — СПб.: Питер, 2002. — 608 с.
18. Дьяконов В. П., Абраменкова И. В., Круглов В. В. MATLAB 5.3. L с
пакетами расширений. — М.: Нолидж, 2001. — 1296 с.
19. Дьяконов В. П., Круглов В. В. MATLAB. Анализ, идентификация и
моделирование систем. Специальный справочник. — СПб.: Питер, 2002. —
448 с.
20. Дьяконов В. П., Круглов В. В. Математические пакеты расширения
MATLAB. Специальный справочник. — СПб.: Питер, 2001. — 480 с.
21. Дэбни Дж., Хартман Т. Simulink 4: Секреты мастерства. — М.: БИНОМ,
2003. - 403 с.
22. Кетков Ю. Л., Кетков А. Ю., Шульц М. М. MATLAB 6.x:
Программирование численных методов. — СПб.: БХВ-Петербург, 2004. — 672 с.
23. Кондратов В. Е., Королев С. Б. MATLAB как система
программирования научно-технических расчетов. — М.: Мир, 2002. — 350 с.
24. Лавров К. Н., Цыплякова Т. П. Финансовая аналитика. MATLAB 6. —
М.: Диалог-МИФИ, 2002., - 368 с.
25. Лазарев Ю. Ф. MATLAB 5.x. — Киев: BHV, 2000. - 384 с.
26. Леоненков А. В. Нечеткое моделирование в среде MATLAB и fuzzyTECH. —
СПб.: БХВ-Петербург, 2003. — 736 с.
27. Мартынов Н. Н. Введение в MATLAB 6.x. — М.: КУДИЦ-ОБРАЗ, 2002. -
352 с.
28. Мартынов Н. Н., Иванов А. П. MATLAB 5.x. Вычисления, визуализация,
программирование. — М.: КУДИЦ-ОБРАЗ, 2000. — 332 с.
29. Мартынов Н. Н., Иванов А. П. MATLAB 5.x. Пособие по
программированию в системе MATLAB. - М.: Изд. МГУ, 2000. — 336 с.
30. Медведев В. С, Потемкин В. Г. Control System Toolbox. MATLAB 5 для
студентов. — М.: Диалог-МИФИ, 1997. — 287 с.
31. Медведев В. С, Потемкин В. Г. Нейронные сети. MATLAB 6. — М.:
Диалог-МИФИ, 2002. — 496 с.
Литература и интернет-источники
725
32. Мэтьюз Дж. Г., Финк К. Д. Численные методы. Использование MATLAB:
Пер. с англ. — М.: Изд. дом "Вильяме", 2001. — 713 с.
33. Новгородцев А. Расчет электрических цепей в MATLAB. — СПб.: Питер,
2004. - 250 с.
34. Потемкин В. Г. Система инженерных и научных расчетов MATLAB 5.x:
В 2-х кн. - М.: Диалог-МИФИ, 1999. - Кн. 1. - 366 с.
35. Потемкин В. Г. Система инженерных и научных расчетов MATLAB 5.x:
В 2-х кн. — М.: Диалог-МИФИ, 1999. - Кн. 2. - 304 с.
36. Потемкин В. Г. MATLAB 5 для студентов / Новая редакция. 2-е изд.,
испр. и доп. — М.: Диалог-МИФИ, 1999. — 447 с.
37. Потемкин В. Г. MATLAB 6: Среда проектирования инженерных
приложений. — М.: Диалог-МИФИ, 2003. — 448 с.
38. Потемкин В. Г. Введение в MATLAB. - М.: Диалог-МИФИ, 2000. —
350 с.
39. Потемкин В. Г. Вычисления в среде MATLAB. — М.: Диалог-МИФИ,
2004. - 720 с.
40. Потемкин В. Г. Инструментальные средства MATLAB 5.x. — М.:
Диалог-МИФИ, 2001. - 324 с.
41. Потемкин В. Г. Система MATLAB: Справочное пособие. — М.: Диалог-
МИФИ, 1997. - 350 с.
42. Рудаков П. И., Сафонов В. И. Обработка сигналов и изображений.
MATLAB 5.x. — М.: Диалог-МИФИ, 2000. — 416 с.
43. Семененко Н. Г. Введение в математическое моделирование. Maple,
Mathematica, MATLAB. - М.: СОЛОН, 2002. - 112 с.
44. Чен К., Джиблин П., Ирвинг A. MATLAB в математических
исследованиях: Пер. с англ. — М.: Мир, 2001. — 346 с.
Методы вычислений
45. Абрамов Л. М., Капустин В. Ф. Математическое программирование. —
Л.: Изд. ЛГУ, 1976. - 183 с.
46. Бахвалов Н. С. Численные методы. — М.: Наука, 1973. — 631 с.
47. Беклемишев Д. В. Дополнительные главы линейной алгебры. — М.:
Наука, 1983. — 335 с.
48. Березин И. С, Жилков Н. П. Методы вычислений: В 2-х т. — М.: Изд.
физ.-мат. литературы, 1959. — Т. 1. — 464 с.
49. Березин И. С, Жидков Н. П. Методы вычислений: В 2-х т. — М.: Изд.
физ.-мат. литературы, 1959. — Т. 2. — 620 с.
726
Литература и интернет-источники
50. Гасс С. Линейное программирование (методы и приложения). — М.:
Гос. изд-во физико-математической литературы, 1961. — 303 с.
51. Гилл Ф., Мюррей У., Райт М. Практическая оптимизация.— М.: Мир.
1985. — 509 с.
52. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые
задачи: Пер. с англ. — М.: Мир, 1982. — 416 с.
53. Деккер К., Вервер Я. Устойчивость методов Рунге—Кутты для жестких
нелинейных дифференциальных уравнений: Пер. с англ. — М.: Мир,
1988. - 332 с.
54. Демидович Б. П., Марон И. А. Основы вычислительной математики. —
М.: Изд. физ.-мат. литературы, 1960. — 659 с.
55. Демидович Б. П., Марон И. А., Шувалова Э. 3. Численные методы
анализа. — М.: Изд. физ.-мат. литературы, 1962. — 307 с.
56. Завьялов Ю. С, Квасов Б. И., Мирошниченко В. Л. Методы сплайн-
функций. — М.: Наука, 1980. — 352 с.
57. Икрамов X. Д. Численное решение матричных уравнений. — М.: Наука,
1984. - 190 с.
58. Кнут Д. Искусство программирования для ЭВМ: В 2-х т. /
Получисленные алгоритмы. — М.: Мир, 1977. — Т. 2. — 724 с.
59. Копченова Н. В., Марон И. А. Вычислительная математика в примерах
и задачах. — М.: Наука, 1972. — 367 с.
60- Кронрод А. С. Узлы и веса квадратурных формул. Шестнадцатизначные
таблицы. — М.: Наука, 1964. — 143 с.
61. Михлин С. Г., Смолицкий X. Л. Приближенные методы решения
дифференциальных и интегральных уравнений (Справочная математическая
библиотека). — М.: Наука, 1965. — 383 с.
62. Ракитский Ю. В., Устинов С. М., Черноруикий И. Г. Численные методы
решения жестких систем. — М.: Наука, 1979. — 208 с.
63. Соболь И. М. Численные методы Монте-Карло. — М.: Наука, 1973. —
311 с.
64. Справочник программиста. — Л.: Изд. судостр. промышленности,
1983.— Т. 1. —628 с.
65. Стренг Г. Линейная алгебра и се применения: Пер. с англ. — М.: Мир,
1980. — 454 с.
66. Форсайт Дж., Молер К. Численное решение систем линейных
алгебраических уравнений: Пер. с англ. — М.: Мир, 1969. — 167 с.
Литератора и интернет-источники
727
67. Форсайт Дж., Малькольм М., Моулер К. Машинные методы
математических вычислений: Пер. с англ. — М.: Мир, 1980. — 279 с.
68. Химмельблау Д. Прикладное нелинейное программирование: Пер. с англ. —
М.: Мир, 1975. — 534 с.
Интернет
В январе 2004 г. на сайте фирмы MathWorks (http://www.mathworks.com/
moler) появилась прекрасная книга се научного руководителя — "Numerical
Computing with MATLAB" в формате PDF. Вы можете скачать книгу
полностью или отдельные главы с указанного сайта. Ниже приводятся названия
глав и размеры соответствующих файлов.
Номер Название главы
главы
Файл
Размер
файла,
байт
Предисловие (Preface)
1 Введение (Introduction)
2 Линейные уравнения (Linear equations)
3 Интерполяций (Interpolation)
4 Решение уравнений (Zero finding)
5 Метод наименьших квадратов (Least
squares)
6 Вычисление интегралов (Quadrature)
7 Обыкновенные дифференциальные
уравнения (Ordinary differential equations)
8 Случайные числа (Random numbers)
9 Анализ Фурье (Fourier analysis)
10 Собственные вектора и собственные
значения (Eigenvalues and singular values)
11 Уравнения в частных производных (Partial
differential equations)
preface.pdf
intro.pdf
lu.pdf
interp.pdf
zeros.pdf
leastsquares pdf
quad.pdf
odes.pdf
random.pdf
fourier.pdf
eigs.pdf
95 090
635 159
390 467
228 895
211 420
220 873
221 404
561 005
159 831
414 646
681 055
pdes.pdf
420 288
Предметный указатель
Ambient light 426
Anonymous function 136
Array Editor 14, 119
В
Bookmark 153
Breakpoint 150
Camera position 437
Cell 104
Code Composer Studio 10 .
Code Division Multiple Access
(CDMA) 8
D
Diffuse reflection 425
Digital Signal Processing (DSP) 11
E
Esc-1 юслежшател ьмость 233
G
General Aiitoiegressive Conditional
Heteroscedasticity (GARCH) 9
Graphic User Interface (GUI) 258
H
Handle 105, 258
I
Indent 149
Linear Matrix Inequality (LMI) 10
Logical arrays 106
N
Nested function 136
О
OLE for Process Control (OPC) 11
Overloaded function 137
Flash 211
Flashing 211
Function handle 105
P-code 126
Pieceweise polinomial form 543
Primary M-File Functions 135
Private function 137
Предметный указатель
729
S
Script 123
Shininess coefficient 426
Simulink 7
Single arrays 98
Specular reflection 425
Subfunction 126, 135
T
Truncate 210
A
Абсолютное зеркальное
отражение 425
Ачгоритм:
закраски Гуро 436
прямо-двойственный 654
симплексного поиска 614
Аналоговая вычислительная машина
(АВМ) 6
Б
Банан Розенброка 615
Белый пробел 142, 177, 198, 237
В
Вектор:
евклидова норма 528
норма 483, 528
ориентированный угол 485
символьный 90
скалярное произведение 481, 483
смешанное произведение 486
собственный 522
Вектор-столбец 33
Вектор-строка 33
Визуализация 273, 421
V
View point 437
Virtual Reality Modeling Language
(VRML) 12
w
Wire frame 432
Workspace 20, 119
Г
Градиент функции 562
График 43
в декартовых координатах 43
включение в отчет 76
логарифмический масштаб 52
на заданном интервале 52
д
Данные:
двоичные 208
текстовые 207
Декартов лист 619
Дескриптор 105
Деструктор 257
Диаграмма:
круговая 83
объемная столбиковая 81
плоская столбиковая 77
площадная 86
3
Задача:
бинарного линейного
программирования 658
(окончание рубрики см. па с. 730)
730
Задача (окончание):
квадратичного программирования
653, 667
Кош и для обыкновенного
дифференциального уравнения 573
краевая для обыкновенного
дифференциально! о уравнения 5S0
линейного программирования 653
математического
программирования 653
Закладка 153
Закон Ламберта 426
Знак переноса строки 19
И
Изолиния 442
К
Класс 255
Axes 274
Figure 266
Image 298
Line 283
Rectangle 287
Root 260
Text 291
базовый 257
производный 257
Команда:
clear 21
help 129
load 21
save 20
who 20
whos 13, 20
Комментарий 129
многострочный 131
Компонент:
Button Group 316, 336
Checkbox 316, 336
Edit Text 316, 342
Lislbox3l7, 345
Panel 316, 336
Popup Menu 317
Предметный указатель
Push Button 316, 32S
• Radiobutton 316, 336
Slider 316, 347
Static Text 316, 341
Toggle Button 316, 335
защищенный 258
личный 258
общедоступный 258
Конкатенация строк 171
вертикальная 173
горизонтальная 171
Константа:
cps 30
false 106
pi 30
real max 30
realmin 30
tnie 106
литеральная 226
Конструктор 256
Координаты, однородные 422
Коэффициент резкости бликов 426
Л
Лексема 181
Линия уровня 442
м
Массив:
логический 106
пустой 24
символьный 90
строковый 23
Матрица 479
Адамара491
блочная 100
Вапдермоида 493, 536
Ганкеля 492
Гессе 618
Гильберта 490
единичная 487
индекс 34
ленточная 100
магический квадрат 494
Предметный указатель
731
нулевая 487
обратная 5 JI
объединение 36
операции 479
ортогональная 490
Паскаля 491
перестановки 501
покомпонентное умножение 480
преобразование 488
псевдообратная 511
псевдоподобная 503
разложение 494
LU 498
QR500
Жордана 509
полярное 504
сингулярное 503
скелетное 496
треугольное 499
Хессенберга 507
Холецкого 500
Шура 505
Эрмита 495
разреженная 100
ранг 481
символьная 90
собственные числа 495
Теплица 492
унитарная 490
Фробениуса 523
характеристический полипом 522
хранение в оперативной памяти 36
число обусловленности 52S
Матрицы:
кососимметричные 490
косоэрмитовые 490
самосопряженные 490
симметричные 490
эрмитовы 490
Метод 255
Адамса 574
активного набора 667
Гаусса 527
Гаусса—Ньютона 600, 624
Грама—Шмидта 500
деления пополам 595
дихотомии 595
доверительного интернала 618
Куртиса и Хиршфельдера 574
Левенберга—Марквардта 600, 624
Монте-Карло 675
наименьших квадратов 515
Ньютона 618
с доверительным интервалом 667
обратной квадратичной
интерполяции 595
Розенброка 573
Рунге—Кутты 574
секуших 595
сопряженных градиентов 667
Минимизация:
безусловная 614, 637
условная 614, 637
Модуль полинома 608
н
Начало текущей строки 18
Номер файла 209
О
Объект 255
Image 460
Light 440
Patch 448
Surface 427
Окно диалоговое 393
выбора:
из списка 399
имени файла для записи 412
имени файла для чтения 409
параметров страницы 405
параметров шрифта 415
цвета 413
для ввода строк 397
запроса 408
настройки параметров страницы 403
общего назначения 394
параметров печати 406
с полосой прогресса 417
с сообщением 402
с сообщением об ошибке 395
со справочной информацией 396
732
Предметный указатель
Оператор:
break 128
end 124
function ч125
global 125
return 129
switch 128
try 128
Лапласа 563
присваивания 128
условный 128
цикла:
for 128
while 128
Операция:
and 97
cmp 97
or 97
set 97
xor97
арифметическая 37
специальная 37
сравнения 175
Отступ 149
Ошибка п файловой операции 23S
п
Первичные т-файлы 135
Переменная 20
глобальная:
nargin 138, 142
nargoi.it 142
локальная 125
правила именования 20
удаление 21
Подфункция 126, 135
Позиция камеры 437
Поиск:
фрагментов текста 200
шаблон 198
Полином 465
интерполяционный 535
Полное диффузное рассеяние 425
Преобразование аффинное 421
Приведение типов 38
Приведенный индекс 23
Приложение:
консольное 315
окопное 315
Присваивание множественное 132
Пробел литеральный 197
Проблема собственных значений 522
Проволочный каркас поверхности 432
Программа:
explore 108
lint 158
M-Lint 158
Profiler 160
Производная функции 560
Процедура:
feval 105
pcodc 126
Псевдокод 126
Р
Рабочее пространство 20, 119
Растеризация 423
Регулярные выражения 198
Редактор массивов 14, 119
Рендеринг 273, 421
С
Свойство 257
Сингулярное число 503
Система:
квадратная крамеровская 512
крамеровская 536
неопределенная 512
совместная 515
Скрипт 123
Случайная траектория 687
Спецификаторы формата 194
Сплайн 539
Ссылка 259
Сценарий 123
т
Тип данных 89
char 90
double 25
Предметный указатель
733
functionjiandle 105
logical 106
single 98
запись 101
структура 101
Точка зрения 437
Точка прерывания 150
Триангуляция Делоне 555
Узел 535
Указатель 259
на функцию 105
Уравнение:
Вейссинджера 589
дифференциальное 572
матричное 606
Пуассона 520
Усечение 210
Ф
Файл:
двоичный 213
запись 220
чтение 214
закрытие 212
контроль конца данных 212
открытие 209
текстовый 223
создание 250
чтение 224, 234, 239
Фоновая подсветка 426
Формула:
Гаусса 571
Симпсона 566
Фонга 426
Функция 125
abs 32
alpha 462
and 39
angle 32
area 77, 86
atan2 486
axes 326
axis 281
bar 77
ЬагЗ 77
bar3h 77
barn 77
base2dec 190
bin2dec 190
bintprog 659
bitand 97
bitemp 97
bitget 97
bitor 97
bitset 97
bitshift 97
bitxor 97
blanks 170
blkdiag 36
bvp4c 581
bvpinit 581, 585
camlight 441
ceil 41, 231
char 166
chol 500
clabel 442, 444
colormap 77, 306
compan 523
complex 32
cond 52S
conj 32
contour 442
contotir3 442, 447
contourc 442, 446
contourf 442, 444
conv 468
cos 39
cross 484
csaps 545
cumtrapz 566
dbclear 155, 156
dbcont 155
dbdown 155, 158
dbquit 155, 158
dbstack 155
dbstatus 155, 156
dbstep 155, 157
(продолжение рубрики см. на с. 734)
734
Предметный указатель
Функция (продолжение):
dbstop 155, 156
dblype 155
dbup 155, 158
deblank 170
dec2base 190
dec2bin 188
dec2licx 189
decic 589, 590
deconv 468
del2 563
delaunay 555
dialog 394
difT 474, 559
disp 134
dlmread 251
dlnnvriie 250
dot 482
eig 524
error 134, 138
errordlg 395
eval 144
expand 474
expml 42
eye 35, 95, 530
factor 477
false 106
fclosc 212
feof212
ferror 238
feval 144. 145
fgcll 224
fgets 224
fieldnames 102
figure 266, 326
findull 313
findobj 313
findstr 178
fix 41, 231
floor 41, 231
f'miiibud 611
fmincon 638
fniinimax 629, ¢46, 647
fminsearcli 614
fminunc 618
fnder 544
fnint 544
fnval 544
fopen 209, 412
fplot 52.
fprintr225
fread 214
frewind 213
fscanf 234
fseek 213
fsolve 599
ftell 213
fwrite 220
fzero 595
gallery 677
gca 259
gcbo 331
gcd 41
gcf 55, 259
gco 259
get 259
gelfield 104
gradient 563
grid on 47
griddata 557
guidata 386
guihandles 385
hadamard 491
liankcl 493
helpdlg 396
hess 507
Iiex2dec 190
hex2iuim 191
hilb 490
hinges 623
hold on 45
imag 32
imread 305, 335
imwrite 312
input 133
inpiitdlg 397
hit 475
int2str 183,
interpl 540
interp2 554
intmax 94
intmin 94
185
Предметный указатель
735
intwarning 94
inv 511, 533
invhilb 490
isa 113
iscell 116
iscellstr 116
ischar 115
isempty 116
isfinite 117
isinf 117
isletter 106, 117, 177
islogical 115
isnan 117
isnumeric 115
isprime 106, 118
isreal 114
issorted 118
isspace 106, 177
issparse 116
isstruct 116
Jordan 509
Icm 41
legend 47
length 91, 170
light 440
lightangle 440
line 283
linear 554
linprog 653
listdlg 399
log 569
loglp 42
loglog. 52
lower 183
Isqnonlin 624, 646
In 498
magic 494
mat2str 191
mean 565
mesh 429, 432
meshc 432
meshgrid 428, 553
meshz 432
mod 41
msgbox 402
nargchk 138
nargoutclik 138
nchoosek 42
ndims 91
nextpow2 42
norm 528
not 39
null 514
iuim2str 183
ode 113 575
odel5i 588
ode 15s 575
ode23 575
ode23s 575
ode23t 575
ode23lb 575
ode45 575
odesel 577
ones 34. 95, 530
opti nisei 649, 659
or 39
pagedlg 403
pagesctiipdlg 403, 405
pascal 491
patch 448
pchip 540
peaks 399
perms 42
pie 77, 83
pie3 77, S3
pinv512, 517
plot 43, 270
plolyy 48
poly 471, 523
poly2sym 465
polyder 469
polyf]t 537
polyint 470
polyline 158
polysum 467
polyval 322, 466, 537
polyvalm 467
pow2 42
ppval 540, 544
primes 42
prinldlg 406
putfield 104
qr500
quad 566
quad] 571
(окончание рубрики см. на с. 736)
736
Предметный указатель
Функция (окончание):
quadprog 667
quadstep 566
questdlg 408
rand 35, 676
randn 35, 677
randperm 677
rank 481
real 32
reallog 42
real max 100
realmin 100
realsqrt 42
rectangle 287
regexp 200
regexpi 200
regexprep 200, .203
rem 41
repmat 104, 171
reshape 519
residue 471
mifield 104
roots 322, 470, 523 -
round 231
rref 525
rsOcsf 507
schur 506
semilogx 52
semilogy 52
set 259, 322, 326, 348
sign 42
simplify 473
sin 39
size 91
solve 476
sphere 439
spline 540
sprintr 28, 135, 192, 238
sqrt 39
sscanf 196, 238
str2double 186
str2mat 191
str2num 186, 398
strcat 171
stremp 175
strempi 175, 183
strfind 178
slrjust 170
strmatch 179
strnemp 175
strnempi 175
strrep 180
strtok 142, 181
struct 102
strvcat 173
subplot 49
subs 471
sum 482, 532
surf 429, 436
surfc 436
sym 466
sym2poly 465
text 291
textread 239
title 47
toeplitz 492
trace 533
trapz 564
trimesh 557
true 106
uiconextmenii 350
uicontrol 321
uigetfile 409
uimenii 350
uiputfile 412
uisetcolor 413
uisetfont 415
upper 183
vander 493, 536
view 438
waitbar 417
warndlg 416
warning 134
xlabel 47
xor 39, 127
ylabel 47
zeros 34, 95, 530
анонимная 136
Предметный указатель
737
аргумент, заданный вектором 36
вложенная 136
гармоническая 686
перегружаемая 137
Розенброка 625
унимодальная 611
частная 137
ц
Цифровая вычислительная машина
(ЦВМ) 6
Число:
вещественное 25
комплексное 25
собственное 522
формат вывода 25
целое 25
Я
Ячейка 103, 104
как повысить отдачу от вложений
в инмо»ма ионн ю инм »acTi кт •
компании?
обучить специалистов в учебном
ц е нт ре s о f 11 i п е *!
Даже грамотный специалист, занятый текущей работой, не в состоянии самостоятельно
повышать свою квалификацию. Для этого у него нет ни времени, ни методических
материалов. Только авторизованное обучение под руководством опытного инструктора
позволяет эффективно на 100% использовать все возможности как ГГ-инфраструктуры, так и
персонала компании.
непрерывное обучение.'Информационные.- технология быстро меняются- Также быстро устаревают
линия сотрудников, Мм предлшуем экономичный и э<|кректши-1ЫП способ непрерывного ОбуЧСНИЯ. Мы
(Тутояы разработать кпртшрцтицнук! программу обучении слсциальнс! длн сотрудников Нашей компании.
Широкий выбор курсов длн npot|K:i4pin>Hjj|u]i ihi(vi:il-ih IT, которые хотят понмеить сноп уровень. Большое
пншшпк: уделяется гиццнк'ИМ гохлроеиия пршильцпЛ Л'-нпфркетрукгурЫ современной кпчлапин —
вопросам бсэипаеншти, защиты длшых реэсрнниму копированию, адмтшетрнровлнию сети и др.
Авторизованное обучение. SofiLinc-" Нплистгл апторплопанимм учебным центром кимпаннп Microsoft,
Symantec, f-lirix. VT.RJ ГА.Ч н др.
Высокое качество обучения. Обучение недугсертифицированные преподанзтелн поофициальным
методическим материалам. Высокое качество обучения пидтверядастси откликами крупнейших компаииП,
входящих в ТОТ! lOOpocciifhsonj рынки.
Корпоративные программы обучения. sonLinc* ориентируется на лолшеречнкс отношении с корпорз-
'111ННМ.ЧИ КПИСН'ш'мИ МЫ ripCA'iarJL'M рЭЯрЯбглку ItLTipcpiJHIIOM ПРОГРАММЫ ОСуЧСИИН CO'ipy/UillKUU, КОТО-
р:1я попнолит --экономить ресурсы, Т1ыдс-!ясмые 1м обучение.
Обратитесь к консультантам учебного центра Анне Дмитраковой или Нине Доминго
по тел.: +7(055)231-39-39 и закажите бесплэтный каталог учебных курсов,
sortlne
программное обеспечение — лицензирование, обучение, консалтинг
^-'7 ( О 9 5 ) 2 3 1-3 9 -- 3 9 WWW.Softline.ru
www.bhv.ru
Иглин С.
Математические расчеты на базе MATLAB.
(+CD-ROM)
Математические расчеты
««6« MATLAB
Магазин "Новая техническая книга"
СПб., Измайловским пр., д. 29, тел. (812) 251-41-10
Отдел оптовых поставок
e-mail: opt@bhv.spb.su
В учебном пособии рассмотрены отдельные
математические курсы: вариационное исчисление,
математическая статистика, теория графов, соответствующие
государственному образовательному стандарту
общепрофессиональной дисциплины «Математика».
Изучение материала книги ориентировано на активное
применение MATLAB и других математических
пакетов, в том числе разработанного автором Graph
Theory Toolbox, размещенного на сайте компании Math-
works — производителя MATLAB. Наличие в каждой
главе теоретической части, вопросов для
самопроверки, примеров решения задач и вариантов домашних
заданий позволит студенту, работая в интерактивном режиме за
компьютером, пе только изучать математику, но и осваивать работу с современным
математическим пакетом. Преподавателям книга будет полезна при
проведении лабораторных и практических работ в компьютерном классе, без
которых сегодня невозможно представить изучение математики и различных
ее спецкурсов. Книга рассчитана на студентов всех форм обучения,
аспирантов и преподавателей технических, компьютерных и экономических
направлений.
- H..IIH щц» ПМПДа. Ont«Hte
учевнов посходле
CD-ROM содержит интерактивный Web-документ, позволяющий
осуществить прямой доступ к пакету MATLAB и произвести расчеты приведенных в
книге задач.
Сергей Иглин, кандидат технических наук, доцент кафедры прикладной
математики Ниционалы-юго технического университета «Харьковский
политехнический институт», член экспертной комиссии при редколлегии
журнала «Exponenta Pro. Математика в приложениях», автор более 60
научных и методических работ.
" e * . Ануфриев И., Смирнов А., Смирнова Е.
" я" MATLAB 7
www.bhv.ru (+CD-ROM)
Магазин "Новая техническая книга"
СПб., Измайловский пр., д. 29, тел. (812) 251-41-10
Отдел оптовых поставок
e-mail: opt@bhv.spb.su
<j*-
MATLAB I
Вам нужно визуализировать данные несколькими щелчками
мыши или быстро написать приложение с графическим
интерфейсом и широкими возможностями? Вы хотите
использовать современные численные алгоритмы для решения
различных задач и избежать скрупулезного
программировала-* v"^----^-^---1. ния мелких деталей или желаете овладеть основами про-
IMatS '■ 'jfUw'*"*-* граммирования в современном пакете? Вам требуется
мощный инструмент для научных исследований и практических
разработок или среда для обучения информатике и
вычислениям? Тогда эта книга по MATLAB 7 — лля вас. Она
адресована читателям различного уровня подготовки, в том
числе и не имеющим опыта программирования и работы в
пакетах.
Значительный объем материала отведен вычислительным задачам: решению
уравнений, систем линейных и нелинейных уравнений, интегрированию, аппроксимации
функций, решению систем обыкновенных дифференциальных уравнений и
уравнений в частных производных, задачам оптимизации и работе с разреженными
матрицами. Изложены основы программирования на встроенном языке и принципы
эффективного написания приложений в MATLAB, вопросы интеграции с MS Word и
MS Excel. Рассмотрена работа с массивами и графикой, описаны возможности
расширений Toolbox.
Авторы сопроводили изложение примерами и заданиями для самостоятельной
работы. Для удобства работы с книгой тексты программ собраны "на прилагаемом
компакт-диске.
Ануфриев Игорь, к. ф.-м. н., доцент кафедры «Прикладная математика» Санкт-
Петербургского государственного политехнического университета, автор книги
«Самоучитель MATLAB 5.3/б.х», ряда пособий по информатике и более 20 работ по
вычислительной математике.
Смирнов Александр, к. ф.-м. н., доцент кафедры «Прикладная математика» Санкт-
Петербургского государственного политехнического университета, преподаватель
математических и компьютерных дисциплин с более чем 27-летним стажем, автор
шести пособий по информатике и более 15 научных работ.
Смирнова Елена, к. т. н., доцент кафедры «Прикладная математика* Санкт-
Петербургского государственного политехнического университета, преподаватель
математических и компьютерных дисциплин с более чем 26-летним стажем, автор
четырех пособий по компьютерной тематике и более 16 научных работ.
ШВЕСЬ МИР
компьютерных книг
Уважаемые господа!
Издательство "БХВ-Петербург" приглашает специалистов в области
компьютерных систем и информационных технологий для
сотрудничества в качестве авторов книг по компьютерной тематике.
Если Вы знаете и умеете то, что не знают другие,
если у Вас много идей и творческих планов,
если Вам не нравится то, что уже написано...
напишите книгу
вместе с "БХВ-Петербург"
Ждем в нашем издательстве как опытных, так и начинающих авторов
и надеемся на плодотворную совместную работу.
С предложениями обращайтесь к главному редактору
Екатерине Кондуковой
Тел.:(812)251-4244.591-6243
E-mail: kat@bhv.ru
Россия, 199397, Санкт-Петербург, а/я 194,
www.bhv.ru
В магазине представлена литература по
компьютерным технологиям
радиотехнике и электронике
физике и математике
экономике
медицине
и др.
Низкие цены
Прямые поставки от издательств
Ежедневное пополнение ассортимента
Подарки и скидки покупателям
Магазин работает с 10.00 до 20.00
без обеденного перерыва
выходной день - воскресенье