- •Предисловие
- •Введение
- •1Архитектура эвм
- •1.1 Биты и их хранение
- •1.1.1Вентили и триггеры
- •1.1.2Другие способы хранения битов
- •1.1.3Шестнадцатеричная система счисления
- •1.2 Оперативная память
- •1.2.1Структура памяти
- •1.2.2Измерение емкости памяти
- •1.3 Устройства хранения данных
- •1.3.1Магнитные диски
- •1.3.2Компакт-диски
- •1.3.3Магнитные ленты
- •1.3.4Хранение и поиск файлов
- •1.4 Представление информации в виде двоичного кода
- •1.4.1Представление текста
- •1.4.2Американский национальный институт стандартов
- •1.4.3Iso - международная организация по стандартизации
- •1.4.4Представление числовых значений
- •1.4.5Представление изображений
- •1.4.6Представление звука
- •1.5 Двоичная система счисления
- •1.5.1Альтернатива двоичной системе счисления
- •1.5.2Дроби в двоичной системе счисления
- •1.5.3Аналоговые и цифровые устройства
- •1.6 Хранение целых чисел
- •1.6.1Представление в двоичном дополнительном коде
- •1.6.2Сложение в двоичном дополнительном коде
- •1.6.3Проблема переполнения
- •1.6.4Представление с избытком
- •1.7 Хранение дробей
- •1.7.1Представление с плавающей точкой
- •1.7.2Ошибка усечения
- •1.8 Сжатие данных
- •1.8.1Общие методы сжатия данных
- •1.8.2Сжатие звука
- •1.8.3Сжатие изображений
- •1.9 Ошибки передачи данных
- •1.9.1Контрольный разряд четности
- •1.9.2Коды с исправлением ошибок
- •2Манипулирование данными
- •2.1 Архитектура эвм
- •2.1.1Сложение двух чисел, хранящихся в оперативной памяти
- •2.1.2Кто и что изобрел?
- •2.2 Машинный язык
- •2.2.1Система команд
- •2.2.2Кэш-память
- •2.2.3Арифметико-логические команды
- •2.2.4Команды управления
- •2.2.5Деление двух значений, хранящихся в памяти
- •2.3 Выполнение программы
- •2.3.1Пример выполнения программы
- •2.3.2Команды переменной длины
- •2.3.3Программы и данные
- •2.4 Арифметические и логические операции
- •2.4.1Логические операции
- •2.4.2Сравнение вычислительной мощности эвм
- •2.4.3Операции сдвига
- •2.4.4Арифметические операции
- •2.5 Связь с другими устройствами
- •2.5.1Связь через контроллер
- •2.5.2Строение шины
- •2.5.3Скорость передачи данных
- •2.6 Другие архитектуры
- •2.6.1Конвейерная обработка
- •3Операционные системы и организация сетей
- •3.13.1. Эволюция операционных систем
- •3.1.1Однопроцессорные системы
- •3.1.2Многопроцессорные системы
- •3.2 Архитектура операционной системы
- •3.2.1Программное обеспечение
- •3.2.2Полезное единообразие или вредная монополия?
- •3.2.3Компоненты операционной системы
- •3.2.4Операционная система linux
- •3.2.5Начало работы операционной системы
- •3.3 Координирование действий машины
- •3.3.1Понятие процесса
- •3.3.2Управление процессами
- •3.3.3Модель «клиент-сервер»
- •3.4 Обработка конкуренции между процессами
- •3.4.1Семафор
- •3.4.2Взаимная блокировка
- •3.5 Сети
- •3.5.1Основы организации сетей
- •3.5.2Интернет
- •3.5.3Топология сети Интернет
- •3.5.4Система адресов Интернета
- •3.5.5Электронная почта
- •3.5.6Всемирная паутина
- •3.6 Сетевые протоколы
- •3.6.1Управление правом отправки сообщений
- •3.6.2Сеть ethernet
- •3.6.3Javascript, апплеты, cgi и сервлеты
- •3.6.4Многоуровневый принцип программного обеспечения Интернета
- •3.6.5Комплект протоколов tcp/ip
- •3.6.6Протоколы рорз и imap
- •3.7 Безопасность
- •3.7.1Протокол защищенных сокетов
- •3.7.2Группа компьютерной «скорой помощи»
- •4Алгоритмы
- •4.1 Понятие алгоритма
- •4.1.1Предварительные замечания
- •4.1.2Формальное определение алгоритма
- •4.1.3Определение алгоритма
- •4.1.4Абстрактная природа алгоритма
- •4.2 Представление алгоритма
- •4.2.1Примитивы
- •4.2.2Псевдокод
- •4.3 Создание алгоритма
- •4.3.1Искусство решения задач
- •4.3.2Итеративные структуры в музыке
- •4.3.3Первый шаг в решении задачи
- •4.4 Итеративные структуры
- •4.4.1Алгоритм последовательного поиска
- •4.4.2Управление циклом
- •4.4.3Алгоритм сортировки методом вставок
- •4.5Рекурсивные структуры
- •4.5.1Поиск и сортировка
- •4.5.2Алгоритм двоичного поиска
- •4.5.3Управление рекурсивными структурами
- •4.6 Эффективность и правильность
- •4.6.1Эффективность алгоритма
- •4.6.2Проверка правильности программного обеспечения
- •4.6.3По ту сторону проверки правильности программ
- •5Языки программирования
- •5.1 Исторический обзор
- •5.1.1Ранние поколения
- •5.1.2Интерплатформенное программное обеспечение
- •5.1.3Независимость от машины
- •5.1.4Парадигмы программирования
- •5.2 Основные понятия традиционного программирования
- •5.2.1Культуры языков программирования
- •5.2.2Переменные и типы данных
- •5.2.3Структуры данных
- •5.2.4Константы и литералы
- •5.2.5Операторы присваивания
- •5.2.6Управляющие операторы
- •5.2.7Комментарии
- •5.3 Процедурные единицы
- •5.3.1Процедуры
- •5.3.2Событийно-управляемые программные системы
- •5.3.3Параметры
- •5.3.4Функции
- •5.3.5Операторы ввода-вывода
- •5.4 Реализация языка программирования
- •5.4.1Процесс трансляции программы
- •5.4.2Реализация java
- •5.4.3Компоновка и загрузка
- •5.4.4Пакеты разработки программного обеспечения
- •5.5 Объектно-ориентированное программирование
- •5.5.1Классы и объекты
- •5.5.3Конструкторы
- •5.5.4Дополнительные возможности
- •5.6 Параллельные операции
- •5.7 Декларативное программирование
- •5.7.1Логическая дедукция
- •5.7.2Язык программирования Prolog
- •6Разработка программного обеспечения
- •6.1 Разработка программного обеспечения
- •6.1.1Ассоциация по вычислительной технике
- •6.1.2Институт инженеров по электротехнике и электронике
- •6.2 Жизненный цикл программы
- •6.2.1Цикл как единое целое
- •6.2.2Разработка программного обеспечения на практике
- •6.2.3Этапы разработки программного обеспечения
- •6.2.4Анализ
- •6.2.5Проектирование
- •6.2.6Реализация
- •6.2.7Тестирование
- •6.2.8Современные тенденции
- •6.3 Модульность
- •6.3.1Модульная реализация программы
- •6.3.2Связь модулей системы
- •6.3.3Связность модуля
- •6.4 Методики проектирования
- •6.4.1Нисходящее и восходящее проектирование
- •6.4.2Модели проектирования
- •6.4.3Разработка открытых программных продуктов
- •6.5 Инструменты проектирования
- •6.6 Тестирование
- •6.7 Документация
- •6.8 Право собственности на программное обеспечение и ответственность
- •Часть 3 организация данных
- •7Структуры данных
- •7.1 Основы структур данных
- •7.1.1Опять абстракция
- •7.1.2Статические и динамические структуры
- •7.1.3Указатели
- •7.2 Массивы
- •7.3 Списки
- •7.3.1Непрерывные списки
- •7.3.2Реализация непрерывных списков
- •7.3.3Связные списки
- •7.3.4Поддержка абстрактного списка
- •7.4 Стеки
- •7.4.1Откат
- •7.4.2Реализация стека
- •7.5 Очереди
- •7.5.1Проблема указателей
- •7.6 Деревья
- •7.6.1Реализация дерева
- •7.6.2Сбор мусора
- •7.6.3Пакет бинарного дерева
- •7.7 Пользовательские типы данных
- •7.7.1Пользовательские типы
- •7.7.2Классы
- •7.7.3Описательное и процедурное знание
- •7.7.4Стандартная библиотека шаблонов
- •7.8 Указатели в машинном языке
- •8Файловые структуры
- •8.1 Роль операционной системы
- •8.1.1Таблицы размещения файлов
- •8.2 Последовательные файлы
- •8.2.1Обработка последовательных файлов
- •8.2.2Консорциум производителей программного обеспечения для www
- •8.2.3Текстовые файлы
- •8.2.4Текстовые и двоичные файлы
- •8.2.5Вопросы программирования
- •8.2.6Семантическая сеть
- •8.3 Индексация
- •8.3.1Основные положения индексации
- •8.3.2Вопросы программирования
- •8.3.3Расположение файлов на дисках
- •8.4 Хэширование
- •8.4.1Хэш-система
- •8.4.2Проблемы распределения
- •8.4.3Аутентификация посредством хэширования
- •8.4.4Вопросы программирования
- •9Структуры баз данных
- •9.1 Общие вопросы
- •9.2 Многоуровневый подход к реализации базы данных
- •9.2.1Система управления базой данных
- •9.2.2Распределенные базы данных
- •9.2.3Модели баз данных
- •9.3 Реляционная модель баз данных
- •9.3.1Вопросы реляционного проектирования
- •9.3.2Системы баз данных для персональных компьютеров
- •9.3.3Хронологические базы данных
- •9.3.4Реляционные операции
- •9.3.5Вопросы реализации
- •9.3.6Язык sql
- •9.4 Объектно-ориентированные базы данных
- •9.5 Поддержка целостности базы данных
- •9.5.1Пространственные базы данных
- •9.5.2Протоколы фиксации/отката изменений
- •9.5.3Блокировка
- •9.6 Воздействие технологий баз данных на общество
- •10Искусственный интеллект
- •10.1 Интеллект и машины
- •10.1.1Конечный результат или имитация
- •10.1.2Истоки искусственного интеллекта
- •10.1.3Тест Тьюринга
- •10.1.4Машина для решения головоломки из восьми фишек
- •10.2 Распознавание образов
- •10.3 Мышление
- •10.3.1Продукционные системы
- •10.3.2Интеллект, основанный на поведении
- •10.3.3Деревья поиска
- •10.3.4Эвристика
- •10.4 Искусственные нейронные сети
- •10.4.1Основные свойства
- •10.4.2Приложение теории
- •10.4.3Ассоциативная память
- •10.5 Генетические алгоритмы
- •10.6 Прочие области исследования
- •10.6.1Обработка лингвистической информации
- •10.6.2Рекурсия в естественных языках
- •10.6.3Роботы
- •10.6.4Системы баз данных
- •10.6.5Экспертные системы
- •10.7 Обдумывая последствия
- •10.7.1Сильный искусственный интеллект против слабого
- •11Теория вычислений
- •11.1 Функции и их вычисление
- •11.1.1Теория рекурсивных функций
- •11.2 Машины Тьюринга
- •11.2.1Основы машины Тьюринга
- •11.2.2Истоки машины Тьюринга
- •11.2.3Тезис Черча-Тьюринга
- •11.3 Универсальные языки программирования
- •11.3.1Скелетный язык
- •11.3.2Существуют ли инопланетяне?
- •11.3.3Универсальность скелетного языка
- •11.4 Невычислимая функция
- •11.4.1Проблема останова
- •11.4.2Неразрешимость проблемы останова
- •11.5 Сложность задач
- •11.5.1Измерение сложности задачи
- •11.5.2Пространственная сложность
- •11.5.3Полиномиальные и не полиномиальные задачи
- •11.5.5Детерминированность против недетерминированности
- •11.6Шифрование с открытым ключом
- •11.6.1Шифрование при помощи задачи о ранце
- •11.6.2Популярные системы шифрования
- •11.6.3Модульная арифметика
- •11.6.4Обратно к шифрованию
4.1.4Абстрактная природа алгоритма
Важно подчеркнуть различие между алгоритмом и его представлением, которое аналогично различию между рассказом и книгой. Рассказ по своей природе абстрактен, книга же является его физическим представлением. Если книга переводится на другой язык или переиздается в другом формате, меняется просто представление рассказа, а сам рассказ остается прежним.
Точно так же алгоритм является абстракцией, определяемой его представлениями. Отдельный алгоритм может иметь множество различных представлений. Например, алгоритм преобразования температуры по шкале Цельсия (С) в температуру по шкале Фаренгейта (F) обычно имеет вид алгебраической формулы F = (9/5) С + 32. Но его также можно представить в виде команды: «умножить температуру по шкале Цельсия на 9/-, и прибавить к результату умножения 32» или даже в виде электронной схемы. В каждом случае алгоритм остается прежним, меняется его представление.
Различие между алгоритмом и его представлением является существенным, когда мы пытаемся передать алгоритм. Например, каким должен быть уровень детализации при описании алгоритма. Для метеоролога указания «перевести температуру по шкале Цельсия в температуру по шкале Фаренгейта» может быть достаточно. Но дилетант в этой области, которому требуется более подробное описание, скажет, что эта команда не является однозначной. Однако проблема заключается не в том, что лежащий в основе алгоритм не однозначен, а в том, что представление алгоритма недостаточно подробно. Следовательно, неоднозначность заключается в представлении алгоритма, а не в самом алгоритме. В следующем разделе мы увидим, как для ликвидации проблемы неоднозначности в представлении алгоритма используется понятие примитива.
Наконец, говоря об алгоритмах и их представлении, следует прояснить различие между двумя другими взаимосвязанными понятиями: программой и процессом. Программа является представлением алгоритма. Специалисты в области вычислительной техники используют термин «программа» по отношению к формальному представлению алгоритма, разработанному для прикладной вычислительной системы. В главе 3 мы определили процесс как действия по выполнению программы. Однако обратите внимание на то, что выполнить программу означает выполнить алгоритм, представленный этой программой. Поэтому процесс также можно определить как действия по выполнению алгоритма. Таким образом, программы, алгоритмы и процессы являются разными, хотя и взаимосвязанными сущностями. Программа является представлением алгоритма, а процесс является выполнением алгоритма.
4.2 Представление алгоритма
В этом разделе мы рассмотрим вопросы, касающиеся представления алгоритма. Наша цель состоит в том, чтобы познакомиться с понятиями примитивов и псевдокода, а также создать нашу собственную систему представления.
4.2.1Примитивы
Для представления алгоритма требуется язык представления. Если говорить о человеке, то это может быть естественный язык (английский, русский или японский) или язык картинок (рис. 4.1), описывающий, например, алгоритм создания птицы из квадратного листа бумаги. Однако часто такие естественные средства общения приводят к неправильному пониманию, потому что используемые термины имеют несколько значений. Предложение «Посещение внуков может действовать на нервы» может означать, что внуки, когда они приходят, являются источником проблем или что поход к ним в гости является проблемой. Неправильное понимание также возникает из-за недостаточной степени детализации алгоритма. Немногие читатели смогут сложить птицу, следуя указаниям, данным на рис. 4.1 Однако для человека, занимающегося оригами, сделать это не составит труда. Таким образом, трудности в передаче алгоритма возникают тогда, когда используемое для этого языковое представление не является однозначным или когда данной информации недостаточно.
ПРЕДСТАВЛЕНИЕ АЛГОРИТМА В ПРОЦЕССЕ ЕГО ПОСТРОЕНИЯ
При построении алгоритма человек должен учитывать влияние большого количества связанных идей. Эта задача может выходить за рамки возможностей человеческого разума. Джордж А. Миллер (George A. Miller) в своей статье 1956 года «Психологическое обозрение» (Psychological Review) изложил результаты исследования, которое показало, что человек может манипулировать одновременно только семью элементами. Поэтому разработчику сложных алгоритмов необходимо средство записи частей алгоритма для последующего возвращения к ним.
В 50 и 60-х годах XX века для создания алгоритмов использовались блок-схемы, в которых алгоритм изображается с помощью геометрических фигур, соединенных стрелками. Однако блок-схемы часто становились запутанной паутиной переплетающихся стрелок, что значительно осложняло понимание лежащего в основе алгоритма. Поэтому блок-схемы уступили дорогу другим средствам проектирования алгоритмов. Примером может послужить псевдокод, который используется в этой книге, в соответствии с которым алгоритмы записываются с помощью строго определенных текстовых структур. Однако блок-схемы могут быть полезны, когда целью является изображение алгоритма, а не его построение. Например, на рис. 4.4 и 4.5 используется представление в виде блок-схемы, чтобы наглядно продемонстрировать алгоритмические структуры, представленные операторами управления.
Поиск лучших средств записи все еще продолжается. В главе 6 мы увидим, что сохраняется тенденция использования графики в создании крупных систем программного обеспечения, а псевдокод остается распространенным средством разработки меньших процедурных компонентов системы.
В
вычислительной технике эта трудность
разрешается с помощью строго определенного
набора стандартных блоков, из которых
строится представление алгоритма.
Такие стандартные блоки называются
примитивами (primitive). Строгое определение
примитивов ликвидирует многие сложности,
связанные с неоднозначностью, а
представление алгоритма с их помощью
имеет единый уровень детализации. Набор
примитивов и правил их комбинирования
для представления более сложных идей
составляет язык программирования.
КАК НАЗЫВАТЬ ЭЛЕМЕНТЫ ПРОГРАММЫ
В естественном языке названия элементов часто состоят из нескольких слов, например «стоимость производства прибора» или «предполагаемое время прибытия». Однако когда мы записываем алгоритм в виде программы, такие имена могут осложнить описание алгоритма. Опыт показывает, что лучше присваивать элементу имя, состоящее из неразрывного текста. В течение последних лет использовались разные способы сжатия нескольких слов в одну лексическую единицу для получения имен элементов программы. Один из них состоит в том, чтобы использовать символ подчеркивания для соединения слов, например предполагаемое _время прибытия. При другом способе используются заглавные буквы, чтобы читателю было легче расшифровать имя. Например, можно начинать каждое слово с заглавной буквы ПредполагаемоеВремяПрибытия. Такую технику часто называют паскалевским стилем (Pascal casing), поскольку она была распространена среди тех, кто использовал язык программирования Pascal. Разновидностью формата «паскалевский стиль» является формат «верблюжий стиль» (camel casing), который отличается от паскалевского стиля только тем, что первая буква имени является строчной: ПредполагаемоеВремяПрибытия. Какой формат использовать — это дело вкуса. Каждый примитив состоит из двух компонентов: синтаксиса и семантики. Синтаксис — это символическое представление примитива, а семантика — его значение. Синтаксис слова «воздух» включает в себя шесть символов, а семантика — газообразное вещество, которое окружает планету. Некоторые примитивы, которые используются в оригами, изображены на рис. 4.2.
Д
ля
того чтобы создать набор примитивов,
которые можно использовать в представлении
алгоритма для выполнения его компьютером,
можно обратиться к отдельным командам
машинного языка. Если записать алгоритм
с таким уровнем детализации, то мы
получим программу, которую машина точно
способна выполнить. Однако записывать
алгоритм так подробно — занятие
утомительное, поэтому обычно используются
примитивы более высокого уровня, каждый
из которых является абстрактным
инструментом, построенным из примитивов
более низкого уровня, представленных
в машинном языке. В результате мы
получаем формальный язык программирования,
с помощью которого алгоритм можно
выразить в более абстрактной форме,
чем машинный язык. Мы обсудим языки
программирования в следующей главе.
