Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Яп

.pdf
Скачиваний:
28
Добавлен:
15.03.2023
Размер:
6.44 Mб
Скачать

Ошибки вычислений с вещественными числами

Младший значащий разряд результата каждой операции с плавающей точкой может быть неправильным из-за ошибок округления.

1.Исчезновение операнда - Операнд может исчезнуть, если он относительно мал по отношению с другим операндом.

Предположим, что мы имеем дело с десятичной арифметикой с пятью цифрами, тогда:

0,1234∙103+0,1234∙10-4= 0,1234∙103.

Второй операнд в данном вычислении просто потерялся.

121

Ошибки вычислений с вещественными числами

Потеря значимости - полная потеря значимости, вызванная вычитанием почти равных чисел. Также возникает, когда результат вычислений невозможно представить в допустимой форме.

Пусть имеется два числа:

 

floatf1= 0,12342;

 

floatf2 = 0,12346;

• B математике

f2 - f1 = 0,00004

Программа, вычисляющая f2 - f1 в четырехразрядном представлении с плавающей точкой, даст ответ:

0,1235∙100-0,1234∙100 = 0,1000∙10-3

Потеря значимости встречается часто, т.к. проверка на равенство обычно реализуется вычитанием и последующим сравнением с 0.

123

2/27/2023

Ошибки вычислений с вещественными числами

Умножение ошибки – многократное увеличение абсолютной погрешности операнда, которая может появиться при использовании арифметики с плавающей точкой, даже если относительная ошибка мала.

Обычно это является результатом умножения и деления.

Рассмотрим вычисление х∙х:

0,1234∙103∙0,1234∙103= 0,1522∙105

и предположим теперь, что при вычислении х произошла ошибка на единицу младшего разряда, что соответствует абсолютной ошибке 0,1:

0,1235∙103∙0,1235∙103= 0,1525∙105.

Абсолютная ошибка теперь равна 30, что в 300 раз превышает ошибку перед умножением.

122

Ошибки вычислений с вещественными числами

Сравнивать два вещественных числа НЕЛЬЗЯ.

«< =» и «<» - нет существенного различия.

Правильный способ проверки равенства с плавающей точкой состоит в том, чтобы ввести малую величину и затем сравнить абсолютное значение разности с малой величиной.

При вычислении вещественных чисел всегда происходит округление результата до разрядной сетки, то

f1=x*y/z

f2=x/z*y

f1!=f2

Практическивсегда будутполучаться различные мантиссы.f1-f2!=0

124

31

Особенности вещественных типов с С++

В большинстве случаев операции над double занимают не больше времени, чем над float - можно использовать double без страха временных затрат.

операции деления, вычисления корня и математических функций быстрее на float, чем на double.

сложение, вычитание, умножение и т.п. одинаково для float и double на большинстве процессоров (без использования векторизации).

для больших массивов лучше использовать float, который занимает меньше памяти, и больше элементов помещается в кэш.

float лучше использовать, если используется векторизация.

125

Символьный тип

Символьныйтип – полныйаналог целочисленного.

Char занимает 1 Байт. Всего 256вариантов.

При использованиинациональных кодировок могут занимать 2и 5 байта (UTF32).

Для того, чтобысопоставить числам символыиспользуются

таблицыкодировки– ASCII, UTF, Windows…

Операциисоответствуют целым числам.

‘a’+5; // пятыйсимвол после a. Результат ‘f’

x < y; // верно если значение, хранящееся в x в таблице кодировки находится раньше значения, хранящегося в y.

127

2/27/2023

Смешанная арифметика

При выполнении арифметических операций компиляторы стараются приводить результаты к более широкому типу, а затем преобразуют результат к типу переменной, в которую он записывается.

Лучше везде где можно делать явное преобразование типов самому.

Следует обращать внимание на типы переменных.

int i=7;

 

double j=i/2;

// j=3

double k=i/2.0;

// k=3.5

126

Перечисления

Представляет собой таблицу перечислений.

Операции выполняются в контексте порядкового номера соответствующих обозначений в таблице

typedefenum {black=0, blue=1, green=2…, white=15} color; color a,b;

a = black;

b = a + 2;// результат = green

Многие ЯП требуют явной типизации

значений типа перечислений при таких операциях.

128

32

Логический тип (булев)

Булев тип – частный случай перечислений, где значению false соответствует 0, а все остальное трактуется как 1.

bool a,b; a = true;

b = a + 1; // b == true

b = a – 1; b == false, хотя лучше этому не доверять

int x = 10;

if (x) … // будет выполняться, т.к. условие – истина

• Логические операции в выражениях вычисляются по принципу ленивых вычислений слева направо.

• Нужно упорядочивать так, чтобы наиболее частых вычислений было меньше – если операнд более хорошо предсказуем или быстрее вычисляется, поместите его в выражении первым.

• При смене мест операндов в логических выражениях следует опасаться побочных эффектов, когда одно из подвыражений в определенных

случаях не должно вычисляться.

129

СОСТАВНЫЕ ТИПЫ ДАННЫХ. МАССИВЫ

131

2/27/2023

Подтипы

Это тип, определенныйна основе уже существующего типа.

Значения просто ограничены некоторомдиапазону.

Pascal:

type Ttemperature= 0 .. 300;

130

Массивы

Массив — это структура данных, которая содержит последовательность элементов одинакового типа.

В состав атрибутов для объекта данных типа массив входят:

Количество элементов — указывается косвенно, путем задания диапазона изменения индексов.

Тип данных для каждого элемента — в данном случае он одинаков для всех элементов.

Список значений индексов, применяемых для выбора элементов — задается в виде набора целых чисел, первое из которых соответствует первому элементу, второе — второму элементу и т. д.

132

33

Массивы

Фундаментальное свойство массива — время доступа к любому его элементу A[i] не зависит от значения индекса i.

Индекс первого элемента называют нижней границей (в С – 0, Fortran – 1, в остальных может задаваться программистом), а индекс последнего элемента — верхней границей массива.

Различают компоновку массива (layout) и размещение массива в памяти (allocation).

При компоновке задаются относительные адреса элементов массива (относительно адреса 1-го элемента), вычисляются формулы для адресации элементов.

При размещении определяются действительные машинные адреса элементов и выделяется память.

Связывание типа индекса массива с переменной массива обычно выполняется статически, но по диапазону индексов связывание происходит иногда динамически.

133

Массивы

Время доступа к элементу массива— константа.Кол-во команд машинной программы,необходимыхдля вычисленияадреса, не зависит от значения i.

Значениетекущего индекса должнонаходитьсяв пределах допустимого диапазона.Такая проверка способствует

повышениюнадежности вычислений.Однакореализована она тольков языках Pascal, Ada, Java и C#. В других языках (например,в С и С++) проверка отсутствует в силу специфики организации массивов.

Некоторыеязыки предусматриваютсредства для инициализациимассивовво времяих размещения в памяти. Языки C, C++, Java и C#:

intlist[]= {3, 4, 8, 79};

заставляет компиляторсамостоятельноустановить длину массива. Это удобно, но вносит ограничения: такая инициализация лишает систему возможностиобнаруживать ошибки выхода индексов за пределыкорректного диапазона.

135

2/27/2023

Массивы

Если base — адрес начала массива, w — длина элемента массива, то адрес i-го элемента массива равен:

A [i] = (base – low × w) + i×w

где (base – low × w) — вычисляется предварительно, а (i ×w) — вычисляется во время выполнения программы (поскольку i изменяется).

В языке С первый элемент массива имеет индекс 0, поэтому адрес i-го элемента массива вычисляется по упрощенной формуле:

A [i] = base + i× w

134

Разновидности массивов. Статические

Статические массивымассив со статическим связыванием по диапазонаминдексов и таким размещениемв памяти, которое происходитдо начала работы программы.

Статические массивы достаточноэффективны,поскольку отсутствуют затраты времени как на динамическое размещение в памяти, так и на удаление из нее.

Недостатком является то, что память ими занимается на все время выполненияпрограммы.

В языках C и C++ статическими являются массивы, которые объявляются в функциях со спецификатором static.

136

34

Разновидности массивов. Явные стековые массивы

Явные стековые массивы - массив со статическим связыванием по диапазонам индексов и таким размещением в памяти, которое происходит по итогам обработки объявления в ходе выполнения программы.

Массив удаляется из стековой памяти по завершению работы программы (подпрограммы).

Повышают эффективность использования памяти: большой массив одной подпрограммы может занимать ту же область памяти, что и большой массив другой подпрограммы, причем так может продолжаться до тех пор, пока обе подпрограммы не окажутся активными одновременно.

К недостатку следует отнести дополнительные затраты времени на размещение и удаление массива из памяти.

Массивы, объявленные в функциях C и C ++ без спецификатора static, считаются явными стековыми

массивами. 137

Разновидности массивов. Явные динамические массивы

Явные динамическиемассивысвязываниеи по диапазонам индексов,и по памятипроисходитпосле размещения в памяти.

Связываниепо индексами памятипроизводитсяпо запросу программыи в течение ее выполнения,но памятьвыделяется в куче, а не в стеке.

Преимуществомявляетсягибкость:изменениеразмера массивавсегдаостаетсяпроблемой.

Недостатокна размещениев кучетратитсявремени больше, чем на размещение в стеке.

ЯзыкиC и C++- используютсястандартныебиблиотечные функцииmalloc и free,которые являютсяоперациямидля размещенияв куче и удаленияиз неесоответственно.

Для управлениякучейприменяютоператоры newи delete

139

2/27/2023

Разновидности массивов. Стековые массивы

Стековыемассивымассив с динамическимсвязыванием по диапазонаминдексов и динамическимразмещениемв памяти, которое происходитв ходе обработки объявления.

Связанность диапазонов индексов и размещение массива в памяти сохраняются в течение всей жизнипеременной.

Главным преимуществом этой разновидности массивов по сравнению с двумя предыдущимисчитается гибкость — не нужно заранее знать (до моментаиспользования)размер массива.

138

Разновидности массивов. Динамические массивы

Динамические массивымассив с таким динамическим связыванием по диапазонаминдексов и размещению в памяти, которое повторяется многократнов течение всего жизненногоцикла массива.

Преимущество: максимальная гибкость. Массив по мере необходимостиможетрасти или сжиматься прямов ходе выполненияпрограммы.

Недостаток: на многократное размещение (удаление) в куче тратится много времени (и все оно приходитсяна период вычислений).

List<String> stringList = new List<String>(); //

С#

stringList.Add("Liza");

C#

Java - ArrayList

 

140

35

Массивы в Perl

Имена всех массивов должны начинаться с символа @

но поскольку элементы массива являются скалярными величинами, их имена предваряются знаком доллара $.

@list

# массив list

$list[1]

# обращение ко второму элементу массива

На элемент массива в Perl можно сослаться при помощи отрицательного индекса. Отрицательное значение индекса обозначает номер позиции элемента с конца. Индекс –1 соответствует последнему элементу массива, –2 — предпоследнему и т. д.

$list[-2] # адресует предпоследний элемент.

Ссылка на несуществующий элемент массива в Perl возвращает значение undef, но сообщение об ошибке не формируется.

push – добавить один и более элементов в конец массива

unshift - добавить один и более элементов в начало массива 141

Прямоугольные массивы

Прямоугольный массив — это многомерный массив, в котором все строки и столбцы имеют одинаковое количество элементов.

143

2/27/2023

Массивы в разных языках

Массивы в JavaScript могут быть разреженными, в которых значения индексов не образуют непрерывную последовательность.

list[70] = 47; list имеет 13 элементов и длину 71.

;Элементы с индексами 12..69 не определены, для их

;хранения память не нужна

Массивы в языках Python, Ruby и Lua увеличивают или с помощью методов для добавления элементов, или путем соединения с другими массивами.

Python – списки. Объекты могут иметь любые типы, массивы здесь неоднородны.

Операции для конкатенации массивов (+) и определения вхождения (членства) элемента (in).

Cодержит две различные операции сравнения: одна определяет, ссылаются ли две переменные на один и тот же объект (is);

другая проверяет равенство всех объектов, входящих в указанные объекты, независимо от глубины вложенности (= =). 142

Массив массивов

Массив массивов — это многомерный массив, в котором не требуется, чтобы длины у строк были одинаковыми. Еще называют не выровненными массивами.

Например, не выровненная матрица может состоять из трех строк, одна из которых содержит пять элементов, другая — семь элементов, а третья — двенадцать элементов.

int[][] jaggedarray2 = new int[][]

{

new int[] {1,3,5,7,9}, new int[] {0,2,4,6}, new int[] {11,22}

};

Сечение — это подструктура массива, которая сама является массивом.

Сечениедля трехмерногомассива – двумерный,для двумерного– одномерный.

144

36

Ассоциативный массив

Ассоциативный массив — это неупорядоченное множество элементов данных, индексированных таким же количеством величин, которые называются ключами.

Каждый элемент ассоциативного массива несет в себе ключ и значение. Ключ является единственным средством доступа к значению.

Perl:

%age = ( "Liza" => 27, "Alex" => 18, "Nataly" => 30, "John" => 41); $age{"Nataly"} = 33; // обращение к элементу

delete $age{"John"}; // удаление

@age= (); // обнуление хэша

If (exists $age { "Liza"}) ... // проверка существования хэша

Ассоциативные массивы в Python называют словарями.

В PHP применяются как обычные, так и ассоциативные массивы. Язык обеспечивает функции как индексированного, так и

хешированного доступа к элементам.

145

Строки

Строка — это просто последовательностьсимволов.

В языках программирования строки представляются или в виде отдельногоэлементарноготипа, или в виде массивов из элементов символьноготипа.

Различают три разновидностистрок:

1.строки фиксированной длины

2.строки переменнойдлины,не превосходящей заданного максимума(строки с ограниченнойдинамическойдлиной)

3.неограниченныеподлине строки (строкис неограниченнойдинамическойдлиной).

147

2/27/2023

СОСТАВНЫЕ ТИПЫ ДАННЫХ. СТРОКИ

146

Строки фиксированной длины

строки фиксированной длины (строки со статической длиной) - поддержка на аппаратном уровне.

К данной разновидности относятся строки в языке Python, неизменяемые объекты класса String в Java, а также строковые классы из стандартной библиотеки классов C++, встроенный класс String в Ruby, средства из библиотеки классов .NET, доступные в языкахC# и F#.

Правила:

1.значениями могут быть строки символов только этой длины;

2.присваивание строки символов с длиной, отличной от заданной, приводит к ее усечению (если длина больше заданной) или к добавлению пробелов в ее конец (если длина меньше заданной).

148

37

Строки переменной длины

Строки переменной длины, не превосходящей заданного максимума (строки с ограниченной динамической длиной).

Подобные строки приняты в языках C и C++ (строки в стиле C). Правда, вместо объявления длины строки здесь используетсяограничивающий нуль-символ \0, который помещаетсяза последним символом строки.

Правила:

1.в программе указываетсямаксимальная длина строки;

2.фактические строки могут иметь меньшее количество символов;

3.текущая длина строки может меняться,но при превышении максимума лишние символы отсекаются.

149

Операции со строками

Конкатенация(объединение). Конкатенацией называют операцию, объединяющую две короткие строки в одну более длинную.

Операцииотношенийнад строками.К строкам можно применятьобычные операции отношения:равно, больше- чем,меньше-чем.

Операцииосновываются на правиле лексикографического

(алфавитного)упорядочения символов:строка Х меньше строки Y, если первыйсимвол в Х меньше первого символа в Y; если эти символы совпадают, то второй символ Х должен быть меньше второго символа Y.

Выделение подстрокипри помощи индексов. В этом случае предполагается,что строка представляется как символьный массив. Результатомоперации становится набор символов, позиции которых указаны индексами, являющимися аргументамиоперации: первый индекс задает первую позицию, а второй —последнююпозицию подстроки.

151

2/27/2023

Неограниченные по длине строки

Неограниченныепо длинестроки (строкис неограниченнойдинамическойдлиной).

обеспечивается максимальная гибкость, но существенно возрастают затраты на их динамическоеразмещение в памяти, а также на удаление из памяти.

Такие строки применяютв JavaScript, Perl и стандартной библиотекеC++.

150

Операции со строками

Выделение подстроки на основе сопоставления с образцом.

Например, она располагается после символа 'a', или после десятичной точки, или после фразы "Пароль".

Аргументы:

1.специальная структура данных, которая определяет вид искомой подстроки – регулярное выражение.

2.исходная строка, в которой будет выполняться поиск подстроки, соответствующей заданному образцу.

Поиск любого адреса электронной почты в доменах yahoo.com, hotmail.com и gmail.com.

(\W|^)[\w.+\-]{0,25}@(yahoo|hotmail|gmail)\.com(\W|$)

152

38

СОСТАВНЫЕ ТИПЫ ДАННЫХ. СТРУКТУРЫ И ЗАПИСИ

153

Структуры и записи

Доступ к элементам структур обеспечивается с помощью:

операции-точки <имя_структуры>.<имя_элемента>;

операции-стрелки <указатель_структуры> –> <имя_элемента>. struct block {

intx; float y; };

intmain (){

struct block a, ptr_a = &a; a.x = 5;

ptr_a –> y= 4.5; }

В памяти запись может храниться в единой области, в которой поля расположены последовательно.

Формула вычисления адреса i-го поля записи R имеет вид:

155

2/27/2023

Структуры и записи

Записи позволяют сгруппировать переменные, относящиеся к объекту, и рассматривать их как единый модуль.

Запись - это неоднородная структура данных, в которой отдельные элементы идентифицируются именами. Атрибуты объекта данных типа:

1)количество полей;

2)тип данных для каждого поля;

3)имя для обозначения каждого поля.

154

Структуры и записи

Допускаетсявзаимноевложение массивови записей: structТипПреподавателя{

int Ид;

int Возраст; float Зарплата; char Кафедра;

} Преподаватель[250];

В языкахPython и Ruby записимогутбыть реализованыкак хеши, которыесами по себе могутбыть элементамимассивов.

В языкахJavaи C#записи могутопределяться как элементы данных в классах,с вложенными записями,которые рассматриваютсякак вложенные классы.Элементы данных в таких классахслужатполямизаписи.

156

39

СОСТАВНЫЕ ТИПЫ ДАННЫХ. МНОЖЕСТВА

157

Множества в Python

A = set('qwerty')

 

users = {"Tom", "Bob", "Alice"}

A = {1, 2, 3}

 

user = "Tom”

for num in A:

 

if userin users:

print(num)

 

users.remove(user)

A.add(4) # {“1”, ”2”, ”3”, ”4”}

print(users) # {"Bob", "Alice"}

 

 

 

A | B

Возвращает множество, являющееся объединением множеств A и B.

A.union(B)

A |= B

Добавляет в множество A все элементы из множества B.

A.update(B)

A & B

Возвращает множество, являющееся пересечением множеств A и B.

A.intersection(B)

A &= B

Оставляет в множестве A только те элементы, которые есть в множестве B.

A.intersection_update(B)

A - B

Возвращает разность множеств A и B (элементы, входящие в A, но не входящие

A.difference(B)

в B).

 

A -= B

Удаляет из множества A все элементы, входящие в B.

A.difference_update(B)

A ^ B

Возвращает симметрическую разность множеств A и B (элементы, входящие

A.symmetric_difference(B)

в A или в B, но не в оба из них одновременно).

A ^= B

Записывает в A симметрическую разность множеств A и B.

A.symmetric_difference_update(B)

A <= B

Возвращает true, если A является подмножеством B.

A.issubset(B)

A >= B

Возвращает true, если B является подмножеством A.

A.issuperset(B)

A < B

Эквивалентно A <= B and A != B

159

A > B

Эквивалентно A >= B and A != B

 

2/27/2023

Множества

Множество — это структура, содержащая неупорядоченный набор различных значений. Все элементы множества должны быть одного и того же простого типа.

Pascal

var A: set of [1 .. 3];

разрешены подмножества: [ ], [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3]

Множество из n элементов реализуется как битовый вектор длины n. Длина этого вектора обычно кратна длине машинного слова.

СОСТАВНЫЕ ТИПЫ ДАННЫХ. КОРТЕЖИ

160

40