ОСНОВЫ ТЕОРИИ И ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ Пышкин Евгений Валерьевич к.т.н., доцент ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ ВЫСОКОГО УРОВНЯ Блок 2. Типы данных и алгоритмы Понятие типа данных Предпосылки из математики вещественные отличаются от комплексных действительные отличаются от рациональных и трансцендентных целочисленные вычисления отличаются от алгебры логики Предпосылки из теории множеств логические парадоксы (антиномии) Логические парадоксы и типы Пусть имеется множество A всех множеств X, не содержащих себя в качестве одного из элементов. Содержит ли множество A себя в качестве элемента? (Рассел, 1902) Разрешение введением понятия типа элементы множества приписываются некоторому типу Type1 сами множества – типу Type2 множества множеств – типу Type3 Понятие типа по Ч. Хоару 1. 2. 3. 4. 5. 6. Тип определяет класс значений, которые могут принимать переменная или выражение. Каждое значение принадлежит одному и только одному типу. Тип значения константы, переменной или выражения можно вывести либо из контекста, либо из самого операнда, не обращаясь к значениям, вычисляемым во время работы программы. Каждой операции соответствует некоторый фиксированный тип ее операндов и некоторый фиксированный (обычно такой же) тип результата. Разрешение систематической неопределенности в случае, когда один и тот же символ применяется к операндам разного типа, производится на стадии компиляции. Для каждого типа свойства значений и элементарных операций над значениями задаются с помощью аксиом. При работе с языком программирования знание типа позволяет обнаруживать бессмысленные конструкции и решать вопрос о методе представления данных и преобразования их в ЭВМ. Типы и языки программирования Не все языки являются строго типизированными Встроенные типы числовые логические (булевские) символьные другие Интегральные типы В C++: int, short, long, char, bool Составные (производные) типы структуры, массивы, объединения… Конструирование составных типов Точка на плоскости Структура Point Абсцисса : double double x; double y; Ордината : double Цвет геометрического объекта Структура Red-составляющая : char Green-составляющая : char Blue-составляющая : char RGBColor char red; char green; char blue; Окружность на плоскости Структура Центр : Point Радиус : double Толщина : int Цвет : RGBColor Circle Point double int RGBColor center; radius; thickness; color; Стандартные типы данных Целые типы Символьные типы Плавающие типы Булевский тип Спецификаторы целых типов со знаком char для работы с 8-разрядными числами со знаком в диапазоне -128..127 short для работы с 16-разрядными числами со знаком в диапазоне -32 768..32 767 long для работы с 32-разрядными числами со знаком в диапазоне -2 147 483 648..2 147 483 647 int (стандартный целый тип), размер которого зависит от архитектуры компьютера (С99) long long для работы с 64-разрядными числами со знаком в диапазоне - 9 223 372 036 854 775 808.. 9 223 372 036 854 775 807 См. заголовочный файл limits.h Цепочки битов (целые без знака) unsigned char для работы с 8-разрядными векторами битов в диапазоне 0..255 unsigned short для работы с 16-разрядными векторами битов в диапазоне 0..65 535 unsigned long для работы с 32-разрядными векторами битов в диапазоне 0..4 294 967 295 unsigned int для работы с 16- или 32разрядными векторами битов в зависимости от архитектуры компьютера (C99) unsigned long long для работы с 64разрядными векторами битов в диапазоне 0.. 18 446 744 073 709 551 615 unsigned int u; if( u > -1 ) ... Microsoft Visual C++ __int8 для работы с 8-разрядными числами со знаком в диапазоне -128..127 __int16 для работы с 16-разрядными числами со знаком в диапазоне -32 768..32 767 __int32 для работы с 32-разрядными числами со знаком в диапазоне -2 147 483 648..2 147 483 647 __int64 для работы с 64-разрядными числами со знаком в диапазоне от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 Целочисленные литералы десятичный-литерал ::= первая-цифра десятичная-цифра 0 первая-цифра ::= 1 2 0 110 2570 3 4 00 5 6 0110 7 8 257A 9 Целочисленные литералы восьмеричный-литерал ::= восьмеричная-цифра ::= 0 1 070 00110 восьмеричнаяцифра 0 02560 2 3 110 4 5 0258 6 7 Целочисленные литералы шестнадцатеричный-литерал ::= x шестнадцатеричная-цифра 0 X шестнадцатеричная-цифра ::= 0 1 0x70 ... 0Xffff 9 A B 0X2EF7 ... F a 0 b ... ffff f 0xG Операции над данными целых типов Одноместные операции взятие с обратным знаком short a = 127; a 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 -a 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 -127 Операции над данными целых типов Одноместные операции увеличение на 1 (префиксная форма) short a = 127; a 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 ++a 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 128 Операции над данными целых типов Одноместные операции уменьшение на 1 (префиксная форма) short a = 127; a 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 --a 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 126 Операции над данными целых типов Одноместные операции увеличение на 1 (постфиксная форма) short a = 127; short b = a++; a++ b 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 128 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 Операции над данными целых типов Двуместные операции сдвиг влево short a = 127; short b = a << 2; a a << 2 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 508 Операции над данными целых типов Двуместные операции сдвиг вправо short a = 127; short b = a >> 2; a a >> 2 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 127 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 31 Операции над данными целых типов Двуместные операции мультипликативные (умножение, деление, остаток от деления) int int int int a = 7; b = 3; c; rem; c = a / b; rem = a % b; a 7 b / c a 3 b 7 % = 1 rem = 2 2 1 3 Операции над данными целых типов Двуместные операции аддитивные (сложение, вычитание) int int int int a = 7; b = 3; c; d; c = a + b; d = a - b; a 7 b + c a 3 b 7 - = 4 d = 10 10 4 3 Понятие типа по Ч. Хоару 1. 2. 3. 4. 5. 6. Тип определяет класс значений, которые могут принимать переменная или выражение. Каждое значение принадлежит одному и только одному типу. Тип значения константы, переменной или выражения можно вывести либо из контекста, либо из самого операнда, не обращаясь к значениям, вычисляемым во время работы программы. Каждой операции соответствует некоторый фиксированный тип ее операндов и некоторый фиксированный (обычно такой же) тип результата. Разрешение систематической неопределенности в случае, когда один и тот же символ применяется к операндам разного типа, производится на стадии компиляции. Для каждого типа свойства значений и элементарных операций над значениями задаются с помощью аксиом. При работе с языком программирования знание типа позволяет обнаруживать бессмысленные конструкции и решать вопрос о методе представления данных и преобразования их в ЭВМ. Когда возникает необходимость преобразования типа Типы отличаются только разрядностью кода, и возможно строго определенное преобразование значения одного типа в другой за счет изменения разрядности Типы отличаются структурой кода, и возможно строго определенное преобразование за счет изменения структуры кода Типы отличаются семантически и преобразование возможно только в виде иной «интерпретации» кода, образуемого цепочкой двоичных разрядов, результат в общем случае непредсказуем Неявные преобразования типов short i = 12; long l = 65535; l = l + i; знак 0 0000000 00001100 i знак значение то же, но представлено длинным кодом 0 0000000 00000000 00000000 00001100 i' 0 0000000 00000000 11111111 11111111 l 0 0000000 00000001 00000000 00001011 l + до присваивания после присваивания Неявные преобразования типов short i = -12; long l = 65535; l = l + i; знак 1 1111111 0000000 11110100 i знак происходит «размножение» знакового разряда 1 1111111 11111111 11111111 11110100 i' 0 0000000 00000000 11111111 11111111 l 11110011 l + 0 0000000 00000000 11111111 до присваивания после присваивания Неявные преобразования типов short long short l = l res = i = 12; l = 65535; res; + i; l; // ??? 0 0000000 00000001 потеря значащих разрядов! 00000000 00001101 l=l+i копирование 0 0000000 00001101 res Явные преобразования типов res = (short) l; res = static_cast <short> ( l ); Когда результирующее приведение типа достигается неявным преобразованием, явное преобразование использовать НЕ НУЖНО! Общефилософский принцип: «Не все то, что можно сделать, нужно делать» Резюме Целые типы для точных вычислений В результате выполнения операции над операндами целого типа получается результат целого типа При выполнении вычислений возможны преобразования типов Многие операции над целыми данными могут быть применены и к данным других типов Решение многих задач связано с обработкой данных целых типов Символьные типы спецификация-символьного-типа ::= unsigned char signed wchar_t Символьные литералы символьный литерал ::= литера или литеры ' L ' восьмеричный-код \ управляющая-литера x ′A’ ′\0101’ ′\x41’ шестнадцатеричный-код L′ab’ 65 ′65’ Символьные литералы Литералы специального вида // Литерал '\0' // '\a' // '\b' // // // '\t' // '\n' // '\r' // '\f' // '\"' '\'' '\\' DEC 000 007 008 HEX 0x00 Null 0x07 Alert 0x08 Backspace NUL BEL BS 009 010 013 014 0x09 0x0A 0x0D 0x0E HT LF CR FF // 034 // 039 // 092 Tab New line Return Formfeed 0x22 Quotation mark 0x27 Apostrophe 0x5C Backslash Нуль-символ Звуковой сигнал Удаление предшествующего символа Табуляция Новая строка Возврат каретки Прогон формата Кавычка Апостроф Обратная косая черта Резюме В разных языках символьные данные могут поддерживаться различным образом Однобайтовый и двухбайтовый форматы представления кодов символов В С++ обработка данных символьных типов практически не отличается от действий над целыми кодами Дополнительную наглядность тексту придает использование символьных литералов Особый случай использования обработки последовательностей символов – строки символов (обсуждаются позднее) Понятие алгоритма Алгоритм – однозначно определенная на некотором языке конечная последовательность предписаний (инструкций, команд), задающая порядок исполнения элементарных операций для систематического решения задачи Любое разумное определение алгоритма, которое может быть предложено в будущем, окажется эквивалентным уже известным определениям Формы записи алгоритма Текстуальная форма записи 1. 2. 3. 4. 5. 6. 7. Скопировать значение X во вспомогательную переменную x. Скопировать значение Y во вспомогательную переменную y. Если x≠y, перейти к п. 4, иначе – к п. 7. Если x>y, перейти к п. 5, иначе – к п. 6. Записать в x результат вычисления выражения x-y и перейти к п. 3. Записать в y результат вычисления выражения y-x и перейти к п. 3. Конец. x – результат работы. Формы записи алгоритма Схема алгоритма (flowchart) НОД( X, Y ) Алгоритм поиска наибольшего общего делителя X, Y - исходные данные x := X y := Y x не равно y нет да x>y да нет y := y - x x x - искомое число x := x - y Формы записи алгоритма Другие диаграммы Диаграммы Нэсси-Шнейдермана (NSD) NSD-диаграмма алгоритма НОД( X, Y ) Основные элементы NSD NSD-программа Title НОД( X, Y ) x := X y := Y Body Процесс Condition? True False True Clause False Clause x не равно y Ветвление x > y? True False x := x - y Do clause Body Цикл с предусловием вывод x y := y - x Формы записи алгоритма Другие диаграммы Диаграммы Дейкстры НОД( X, Y ) x := X y := Y x не равно y нет да вывод x x>y нет y := y - x да x := x - y Формы записи алгоритма Псевдокод НОД( X, Y ) x:=X; y:=Y; пока( x ≠ y ) повторять если( x > y ) то x:=x-y; иначе y:=y-x; конец цикла вывести x конец Резюме Алгоритмы могут быть определены на базе различных текстовых и тексто-графических формализмов Формальные модели для проектирования различных классов программных систем Современная тенденция: уход от определения алгоритма как первичного этапа проектирования Визуализация самого процесса проектирования