Лекция 4 (Лекции (2009) (Саша Федорова))
Описание файла
Файл "Лекция 4" внутри архива находится в папке "Лекции (2009) (Саша Федорова)". Документ из архива "Лекции (2009) (Саша Федорова)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Лекция 4"
Текст из документа "Лекция 4"
13
Лекция 4.
Заметим, что в нашей классификации(см конец предыдущей лекции) отсутствует функциональный(процедурный) Тип Данных. С точки зрения реализации он близок к указательному типу. Мы рассмотрим его в главе процедур и функций.
Пункт 2.1 Арифметический(целочисленный) тип данных.
2.1.1
Целочисленный Тип Данных.
При анализе и введении целочисленного типа данных в ЯП возникают следующие проблемы:
-
Проблема представления
-
знак – в прямом виде
-
проблема рамера => проблема диапазона значений
-
Наличие беззнаковости(беззнаковой арифметики)
ЯП без беззнаковой арифметики существуют, несмотря на то, что беззнаковый тип данных поддерживается архитектурой.
Есть ли нечто в компьютерной архитектуре, у чего беззнаковый диапазн? Да, есть. Это прежде всего адрес(именно из-за адресной проблемы компьютеры поддерживают беззнаковую арифметику).
-
Проблема неявных преобразований(совместимость нескольких целочисленных типов данных)
Все три проблемы тесно связаны, и мы будем говорить обо всех сразу.
Как решают первую проблему?
Возможно 2 ситуации: размеры числа могут быть или не быть фиксированными. Рассмотрим первый случай.
-
Размеры числа зафиксированы(четко и полностью определена семантика) – такое представление очень «благотворно». Примеры ЯП с фиксированным представлением:
-
Turbo Pascal(но не Pascal!)- исключительно под Win32, Вудзош
-
C#
-
Java(байт-код – такая реализация обеспечена виртуальной машиной данного ЯП. Кстати, byte – единственный беззнаковый тип даных в Java)
-
Характерна четкая ориентация на конретную машинную архитектуру
-
Архитектура Intel – байтовая арифметика(отсюда появление байтового типа данных в C#)\
Знаковые | беззнаковые | Размер(в байтах) |
Sbyte | byte | 1 |
Short | ushort | 2 |
int | uint | 4 |
long | Ulong | 8 |
Таблица 1. Типы данных с фиксированным размером.(C#)
byte(единственный беззнаковый тип данных в Java) | 1 |
short | 2 |
int | 4 |
long | 8 |
Таблица 2. Типы данных с фиксированным размером.(Java)
Как такое представвление повлияло на набор операций в Java?
Эталонным считался набор операций, предложенный языком Си. Они есть в любой машинной архитектууре, ими возможно управлять с помощью любого ЯП.
Что есть базисный набор операций?
Глядя сюда, легко сказать, что в Java должно было появиться различие знаковых и безнаковых типов данных.(из существования операции сдвига)
BYTE | 1 |
SHORT INT | 2 |
INTEGER | 4 |
LONGINT | 8 |
Таблица 3. Типы данных с фиксированным размером.(Оберон)
В данном сучае все очень грубо и просто. Семантика поностью определена.
Ведь ЯП должен быть простым с точки зрения основных коцепций, седовательно, с точки зрения базисных типов данных=> наличие фиксированного представления и полностью определенная семантика базисных операций
Операции сдвига
4 мнемоники для операций сдвига:
SHL shift left
SHR shift right
SAL
SAR
Заметим, что мнемоники тут 3, а операций – 4.
Мы знаем, что сдвиг влево удаляет первый знак.
Логический сдвиг вправо должен отличаться от арифметического сдвига вправо(сохранение или потеря знака при делении на 2)
Сдвиг вправо в С++ работает в зависимости от типа операндов(кроме деления пополам, сдвиг используется для выделения байтов, выделения битовой структуры отдельного числа – там как раз требуется логический сдвиг).
Отсюда легко понять, отчего в Java появилась операция >>> - логический сдвиг вправо(технологическая потребность).
Мы рассмотрели целочисленный тип данных с фиксированной точкой. Однко заметим, что во многих ЯП такой «роскоши» нет. Если целочисленный «фиксированный» тип данных присутствует в ЯП, то он должен быть реализован максимально эффективно(а размерность типа данных должна соответствовать размерам регистров)
А в стандарте языка С, к примеру, сказано, что short не длиннее int, а long не короче, чем int(и это все, что сказано!)
Архитектура(совместимость с процессором) обязательно должна поддерживаться.
Нефиксированность размеров целочисленных типов данных делает программы непереносимыми(перенос, конечно же, возможен, но довольно трудоемок).
Замечание.В настоящем десятилетии мы должны были стать свидетелями перехода с 32-битной на 64-битную архитектуру. Появились ли 640битные процессоры? Да, к пример Intel(новая архитектура, процессоры Itanium IA64)/
Казалось бы, через 10 лет мы буде программировать на 64-битных машинах. Но Windows под Itanium очень быстро перестали выпускать. Новая архитектура была весьма посредственно совместима с IA32 – старые программы на ней выполнялись быстрее. Под 64-битную архитектуру писали мало программ, это было довольно дорого.
Переход с 16 на 32-битную архитектуру был необходим – писать программы под 32-битной архитектурой удобнее, и переход, хоть и был болезненным, но свершился.
Когда появился x86-64, все остальное не поменялось. Эта архитектура была прогрессивнее, но не хватило средств, а проблема мобильности программ – одна из самых важных.
(Не случайно переносимые программы не используют тип int).
Проблема представления, таким образом – это прежде всего проблема переносимости. А переносить ПО в полностью 64-битные системы никто не собирался.
Беззнаковая арифметика
Беззнаковая арифметика – это большая проблема.
В 70-е годы господствовала точка зрения, что такие преобразования, как uint->int, делать нельзя.
Создатели языка Java писали по принципу «нет человека – нет проблемы». Однако множество ошибок возникало именно из-за неявных преобразований из знаковых в беззнаковые типы.
Оберон(в нем существовали типы BYTE, INTEGER, CARDINAL-знаковое целое) от такого «за бедностью» отказался. Преобразование из INTEGER в CARDINAL было только явным.
I:INTEGER;
J:CARDINAL;
I=J; //Error!
Кода Страуструп проектировал С++, в первой версии языка Си с классами неявные преобразования были запрещены.(в современной версии они разрешены)
Как в Ада решили разобраться со всеми этими проблемами?
Отступление.
Самый простой вариант – вовсе избавиться от беззнаковых чисел. Но создатели C# хотели разработать полноценный ЯП Для обеспечения совместимость беззнаковые преобразования должны были остаться. => допустима семантика безопасных преобразований. Однако эти преобразования безопасны лишь при фиксированном представлении.
Обратные же преобразования неявно запрещены.
Таким образом, проблема неявных преобразований пропадает, если представление фиксированно.
А Ада была лишена фиксированного представления.
Решение: концепция типы и подтипы.
Все обьекты данных разбивались на независимые классы экивалентности, которые не пересекались между собой.
Согласно коцепциям языка Ада, Тип1 и Тип2 различны у нихэ различны имена.
Type Length is new Integer;
type Width is new Integer;
Ключевое слово new подчеркивает, что мы создали новый целочисленный тип.
У создателей Ады, по их собственным словам, было 3 приоритета:
-
Надежность
-
Эффективность(ввиду ограниченности ресурсов)
-
Читабельность(она решалась многословностью языка Ада)
Таким образом, присвоить обьекту типа Width обьект типа Integer было нельзя.
Ведь Width – это новый тип.(килограммы с тараканами складывать нельзя)
Можно определить новый тип данных на ооснове старого типа, добавив ограничение на Range от 0 до MAXINT
Пример
Type Length is new Integer range 0..MAXLEN
Этот тип данных несовместим с другими ТД
NATURAL
POSITIVE
Если допустимо совместное испльзование типа с другими, используют концепцию подтипа: Subtype T1 is T2 range 0..N;//подтип – это подмножество значений исходного типа (new тут нет: новый тип мы не заводим.)
Все обьекты Т1 одновременно являются обьектами типа Т2.
Естественным образом в зависимости от реализации MAXINT меняются.
Мы допускаем некие пределы, и они работают (если то позволит реализация)
Существенно более гибкие средства управления мобильности вычислений.
С этой точки зрения проблема переносимости в ADA решена. За счет ввода ряда концепций, это помогает писать более мобильные программы.
Что же есть integer? Существует обобщенный INTEGER
(диапазон – MIN_INT ----- MAX_INT)
Такой подход у Ада обеспечивает максимальную переносимость программ.
Пункт 2.
1.2. Вещественные числа
Необходимость вещественной арифметики заставляет вводить соответствующий Тип Данных. Существует несколько представлений.
Вещественные тип данных
-
Плавающий тип данных
-
Фиксированный тип данных.
В чем разница?
Вещественное число отличается от целого наличием ненулевой дробной части. Традиционно оно отображается в виде реалиации плавающей точки(оно есть во всех без исключения ЯП).
Пример
IEEE 754 – некоммерческий стандарт, опрееделяющий правила представления вещественных чисел, соблюдаемый всеми поизводителями железа.
float – 754/32 bits
double – 754/64bit
В Java было зафиксировано представление вещественных чисел:
IEEE выводит еще и некоторые специальные значения.
Нормализованый вид: заключается в том, что любое плавающее число по любому целочисленному основанию может быть представлно в виде M*(B в степени p)
Точная нормализация нам нужна для единственности.
1=0.1*10 в первой
1=1.0*10 в нулевой
1=0.01* 10 в квадрате
Если система счисления В-ичная, то 1/B<=M<B ==> старший разряд всегда отличен от нуля==> его можно не хранить, он будет дописываться автоматически.
0.1....
Точное представление позволяет пользователю легко контролировать ошибки, получающиеся при этом представлении.
Когда возникает ошибка, генерируется число NaN - Not a Number - и программа сама должна реагировать на эту ошибку.
Исключение не генерируется, программист сам должен обработать данную ошибку.
Пример
Деление на ноль может произойти из-за потери точность(точности не хватило)
Пример 1/2<=x<1 - сколько тут может быть чисел? 2 в 23 степени. Расстояние между двумя соседними числами - 2 в -24.
Сколько нужно, чтобы погрешность достигла единицы? 2 в 24 степени.
2 в 10 степени ==1024==1Кб приблизительно равно 1000
То ечть 2 в степени 24 - это приблизительно 16 млн.
Вывод: погрешность - беда плавющих чисел.
Для финансовых операций данные типа float применять нельзя.
ДЛя некоторых целей точности моет быть достаточно, а для некоторых - нет.
В ЯП Ада программист сам определяет точность ==> плавающий тип даных определяется следующим образом:
type FLOAR is digits 6; //указываем количество цифр
Первоначальный стандарт языка Ада
существует международный стандарт, который предусматривает округление до 4-го знака.
Вычисление должно быть со строго фиксированной точностью