Текст
                    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]); В первом варианте из файла считываются в