Стандарт ieee 754 представления чисел в формате с плавающей точкой*
*Этот параграф является необязательным и приводится в справочных целях
В каком виде на самом деле хранятся числа в формате с плавающей точкой? Ответ даёт стандарт IEEE 754 (другой вариант названия IEC 60559:1989), разработанный для электронных счётных устройств. В этом стандарте предусмотрены три типа чисел в формате с плавающей точкой, с которыми могут работать процессоры: real*4, real*8 и real*10. Эти числа занимают 4, 8 и 10 байт, соответственно. В Java типу real*4 соответствует float, а типу real*8 соответствует double. Тип real*10 из распространённых языков программирования используется только в диалектах языка PASCAL, в Java он не применяется.
Число r представляется в виде произведения знака s, мантиссы m и экспоненты 2p-d :
r=s*m*2p-d.
Число p называется порядком. Оно может меняться для разных чисел. Значение d, называемое сдвигом порядка, постоянное для всех чисел заданного типа. Оно примерно равно половине максимального числа pmax, которое можно закодировать битами порядка. Точнее, d= (pmax+1)/2-1.
Для чисел real*4: pmax = 255, d= 127.
Для чисел real*8: pmax = 2047, d= 1023.
Для чисел real*10: pmax =32767, d=16383.
Число называется нормализованным в случае, когда мантисса лежит в пределах 1≤m<2. В этом случае первый бит числа всегда равен единице. Максимальное значение мантиссы достигается в случае, когда все её биты равны 1. Оно меньше 2 на единицу младшего разряда мантиссы, то есть с практически важной точностью может считаться равным 2.
Согласно стандарту IEEE 754 все числа формата с плавающей точкой при значениях порядка в диапазоне от 1 до pmax-1 хранятся в нормализованном виде. Такое представление чисел будем называть базовым. Когда порядок равен 0, применяется несколько другой формат хранения чисел. Будем называть его особым. Порядок pmax резервируется для кодировки нечисловых значений, соответствующее представление будем называть нечисловым. Об особом и нечисловом представлениях чисел будет сказано чуть позже.
Размещение чисел в ячейках памяти такое:
Тип | Байт1 | Байт2 | Байт3 | Байт4 | … | Байт8 | Байт9 | Байт10 |
real*4 | sppp pppp | pmmm mmmm | mmmm mmmm | mmmm mmmm |
|
|
|
|
real*8 | sppp pppp | pppp mmmm | mmmm mmmm | mmmm mmmm |
| mmmm mmmm |
|
|
real*10 | sppp pppp | pppp pppp | 1mmm mmmm | mmmm mmmm |
| mmmm mmmm | mmmm mmmm | mmmm mmmm |
Буква s обозначает знаковый бит; p – биты двоичного представления порядка, m – биты двоичного представления мантиссы. Если знаковый бит равен нулю, число положительное, если равен единице – отрицательное. В числах real*4 (float) и real*8 (double) при базовом представлении ведущая единица мантиссы подразумевается, но не хранится, поэтому реально можно считать, что у них под мантиссу отведено не 23 и 52 бита, которые реально хранятся, а 24 и 53 бита. В числах real*10 ведущая единица мантиссы реально хранятся, и мантисса занимает 64 бит. Под порядок в числах real*4 отведено 8 бит, в числах real*8 отведено 11 бит, а в числах real*10 отведено 15 бит.
Тип IEEE 754 | Тип Java | Число бит мантиссы
| Число бит порядка | Сдвиг порядка |
real*4 | float | 23+ подразумевается 1 ведущий бит | 8 | 127 |
real*8 | double | 52+ подразумевается 1 ведущий бит | 11 | 1023 |
real*10 | - | 64 | 15 | 16383 |
Чему равны минимальное и максимальное по модулю числа при их базовом представлении?
Минимальное значение достигается при минимальном порядке и всех нулевых битах мантиссы (за исключением ведущего), то есть при m=1 и p=1. Значит, минимальное значение равно 21-d.
Максимальное значение достигается при максимальном порядке и всех единичных битах мантиссы, то есть при m≈2 и p= pmax-1. Значит, максимальное значение примерно равно
При значениях порядка в диапазоне от 1 до pmax-1 базовое представление позволяет закодировать
числа real*4 примерно от 2.350989E-38 до 3.402824E38,
числа real*8 примерно от 2.225074E-308 до 1.797693E308,
числа real*10 примерно от 3.362103E-4932 до 1.189731E4932.
В случае, когда порядок равен 0 или pmax, используется особое представление чисел, несколько отличающееся от базового.
Если все биты порядка равны 0, но мантисса отлична от нуля, то порядок считается равным 1 (а не 0), а вместо единицы в качестве подразумеваемой ведущей цифры используется ноль. Это ненормализованное представление чисел. Максимальное значение мантиссы в этом случае на младший бит мантиссы меньше 1. Так что максимальное значение числа в особой форме представления равно (1- младший бит мантиссы)*21-d. То есть верхний предел диапазон изменения чисел в этом представлении смыкается с нижним диапазоном изменения чисел в базовом представлении.
Минимальное ненулевое значение мантиссы в особом представлении равно 2-n, где n – число бит мантиссы после двоичной точки.
Минимальное отличное от нуля положительное число для некоторого типа чисел с плавающей точкой равно 21-d-n.
Таким образом, особое представление позволяет закодировать
числа real*4 примерно от 1.401298E-45 до 2.350989E-38,
числа real*8 примерно от 4.940656E-324 до 2.225074E-308,
числа real*10 примерно от 3.6451995E-4951 до 3.362103E-4932.
Специальный случай особого представления – когда и порядок и мантисса равны нулю. Это значение обозначает машинный ноль. В соответствии со стандартом IEEE 754 имеются +0 и -0. Но во всех известных автору языках программирования +0 и -0 при вводе-выводе и сравнении чисел отождествляются.
Нечисловое представление соответствует случаю, когда p=pmax, то есть все биты порядка равны 1. Такое “число” в зависимости от значения мантиссы обозначает одно из трех специальных нечиселовых значений, которые обозначают как Inf (Infinity - “бесконечность”), NaN (Not a Number - “не число”), Ind (Indeterminate – “неопределённость”). Эти значения появляются при переполнениях и неопределённостях в вычислениях. Например, при делении 1 на 0 получается Inf, а при делении 0 на 0 получается Ind. Значение NaN может получаться при преобразовании строки в число, взятии логарифма от отрицательного числа, тригонометрической функции от бесконечности и т.п.
Значение Inf соответствует нулевым битам мантиссы.Согласно IEEE 754 бесконечность имеет знак. Если знаковый бит 0 это + Inf, если знаковый бит 1 это –Inf.
Значение Ind кодируется единицей в знаковом бите и битами мантиссы, равными 0 во всех разрядах кроме старшего (реального, а не подразумеваемого), где стоит 1. Все остальные сочетания знакового бита и мантиссы отведены под величины NaN. Значения NaN бывают двух типов – вызывающие возбуждение сигнала о переполнении (Signaling NaN) и не вызывающие (Quiet NaN). Значения обоих этих типов могут быть “положительными” (знаковый бит равен нулю) и “отрицательными” (знаковый бит равен единице).
В современных языках программирования поддерживается только часть возможностей, реализованных в процессорах в соответствии со стандартом IEEE 754. Например, в Java значения бесконечности различаются как по знаку, так и по типу: имеются Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY.
Но значение Ind вообще не употребляется и отождествляется с NaN, хотя Float.NaN и Double.NaN различаются.
Числа в формате с плавающей точкой занимают следующие диапазоны значений:
Название значения | s (знак) | p (порядок) | m (мантисса) |
-NaN (отрицательное не-число) | 1 | 11..11 | 11..11 : 10..01 |
Indeterminate (неопределённость) | 1 | 11..11 | 10..00 |
Signaling -NaN (отрицательное не-число, возбуждающее ошибку) | 1 | 11..11 | 01..11 : 00..01 |
-Infinity (отрицательное переполнение, плюс бесконечность)
| 1 | 11..11 | 00..00 |
Отрицательное нормализованное
| 1 | 11..10 : 00..01 | 11..11 : 00..00 |
Отрицательное ненормализованное | 1 | 00..00 | 11..11 : 00..01 |
-0 | 1 | 00..00 | 00..00 |
+0
| 0 | 00..00 | 00..00 |
Положительное ненормализованное | 0 | 00..00 | 00..01 : 11..11 |
Положительное нормализованное | 0 | 00..01 : 11..10 | 00..00 : 11..11 |
+Infinity (положительное переполнение, плюс бесконечность) | 0 | 11..11 | 00..00 |
Signaling +NaN (положительное не-число, возбуждающее ошибку) | 0 | 11..11 | 00..01 : 01..11 |
Quiet +NaN (положительное не-число) | 0 | 11..11 | 10..00 : 11..11 |
Имеются методы оболочечных классов, позволяющие преобразовывать наборы бит, хранящихся в ячейках типа int, в значения float, и наоборот – значения типа float в их битовое представление типа int. При этом содержание ячеек не меняется – просто содержащиеся в ячейках наборы бит начинают по-другому трактоваться.
Аналогичные операции существуют и для значений типа long и double:
Float.intBitsToFloat(значение типа int)
Double.longBitsToDouble(значение типа long)
Float.floatToIntBits(значение типа float)
Double.doubleToLongBits(значение типа double)
Например, Float.intBitsToFloat(0x7F7FFFFF) даст значение, равное Float.MAX_VALUE, Float.intBitsToFloat(0x7F800000) – значение Float.POSITIVE_INFINITY,
Float.intBitsToFloat(0xFF800000) – значение Float.NEGATIVE_INFINITY.
Если аргумент метода Float.intBitsToFloat лежит в пределах от 0xF800001 до 0xF800001, результатом будет Float.NaN.
Следует подчеркнуть, что данные операции принципиально отличаются от “обычных” преобразований типов, например, из int в float или из double в long. При “обычных” преобразованиях значение числа не меняется, просто меняется форма хранения этого значения и, соответственно, наборы битов, которыми кодируется это значение. Причём может измениться размер ячейки (скажем, при преобразовании значений int в значения double). А при рассматриваемых в данном разделе операциях сохраняется набор бит и размер ячейки, но меняется тип, который приписывается этому набору.
- Содержание
- Глава 1. Общие представления о языке Java 6
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans 26
- Глава 3. Примитивные типы данных и операторы для работы с ними 78
- Глава 4. Работа с числами в языке Java 95
- Глава 5. Управляющие конструкции 112
- Глава 6. Начальные сведения об объектном программировании 128
- Глава 7. Важнейшие объектные типы 175
- Введение
- Глава 1. Общие представления о языке Java
- 1.1. Java и другие языки программирования. Системное и прикладное программирование
- 1.2. Виртуальная Java-машина, байт-код, jit-компиляция. Категории программ, написанных на языке Java
- 1.3.Алфавит языка Java. Десятичные и шестнадцатеричные цифры и целые числа. Зарезервированные слова Алфавит языка Java
- Десятичные и шестнадцатеричные цифры и целые числа
- Зарезервированные слова языка Java
- 1.4. Управляющие последовательности. Символы Unicode. Специальные символы Управляющие последовательности
- Простые специальные символы
- Составные специальные символы
- 1.5.Идентификаторы. Переменные и типы. Примитивные и ссылочные типы
- Краткие итоги по главе 1
- Задания
- Глава 2. Объектно-ориентированное проектирование и платформа NetBeans
- 2.1.Процедурное и объектно-ориентированное программирование. Инкапсуляция
- 2.2. Работа со ссылочными переменными. Сборка мусора
- 2.3. Проекты NetBeans. Пакеты. Уровни видимости классов. Импорт классов
- 2.4. Базовые пакеты и классы Java
- 2.5. Создание в NetBeans простейшего приложения Java
- 2.6. Компиляция файлов проекта и запуск приложения
- 2.7. Структура проекта NetBeans
- 2.8. Создание в NetBeans приложения Java с графическим интерфейсом
- 2.9. Редактор экранных форм
- 2.10. Внешний вид приложения
- 2.11. Ведение проектов
- 2.11. Редактирование меню экранной формы
- 2.12. Создание нового класса
- 2.13. Документирование исходного кода в Java
- 2.14. Основные компоненты пакетов swing и awt
- 2.15. Технологии Java и .Net
- Краткие итоги по главе 2
- Задания
- Глава 3. Примитивные типы данных и операторы для работы с ними
- 3.1.Булевский (логический) тип
- 3.2.Целые типы, переменные, константы
- 3.3.Основные операторы для работы с целочисленными величинами
- 3.4.Вещественные типы и класс Math
- 3.5.Правила явного и автоматического преобразования типа при работе с числовыми величинами
- 3.6. Оболочечные классы. Упаковка (boxing) и распаковка (unboxing)
- 3.7.Приоритет операторов
- 3.8.Типы-перечисления (enum)
- Краткие итоги по главе 3
- Задания
- Глава 4. Работа с числами в языке Java
- 4.1 Двоичное представление целых чисел Позиционные и непозиционные системы счисления
- Двоичное представление положительных целых чисел
- Двоичное представление отрицательных целых чисел. Дополнительный код
- Проблемы целочисленной машинной арифметики
- Шестнадцатеричное представление целых чисел и перевод из одной системы счисления в другую
- 4.2. Побитовые маски и сдвиги
- 4.3. Двоичное представление вещественных чисел Двоичные дроби
- Мантисса и порядок числа
- Стандарт ieee 754 представления чисел в формате с плавающей точкой*
- Краткие итоги по главе 4
- Задания
- Глава 5. Управляющие конструкции Составной оператор
- Условный оператор if
- Оператор выбора switch
- Условное выражение …?... : …
- Оператор цикла for
- Оператор цикла while – цикл с предусловием
- Оператор цикла do...While – цикл с постусловием
- Операторы прерывания continue, break, return, System.Exit
- Краткие итоги по главе 5
- Задания
- Глава 6. Начальные сведения об объектном программировании
- Наследование и полиморфизм. Uml-диаграммы
- Функции. Модификаторы. Передача примитивных типов в функции
- Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this
- Передача ссылочных типов в функции. Проблема изменения ссылки внутри подпрограммы
- Наследование. Суперклассы и подклассы. Переопределение методов
- Наследование и правила видимости. Зарезервированное слово super
- Статическое и динамическое связывание методов. Полиморфизм
- Базовый класс Object
- Конструкторы. Зарезервированные слова super и this. Блоки инициализации
- Удаление неиспользуемых объектов и метод finalize. Проблема деструкторов для сложно устроенных объектов
- Перегрузка методов
- Правила совместимости ссылочных типов как основа использования полиморфного кода. Приведение и проверка типов
- Рефакторинг
- Reverse engineering – построение uml-диаграмм по разработанным классам
- Краткие итоги по главе 6
- Задания
- Глава 7. Важнейшие объектные типы Массивы
- Коллекции, списки, итераторы
- Работа со строками в Java. Строки как объекты. Классы String, StringBuffer и StringBuilder
- Работа с графикой
- Исключительные ситуации Обработка исключительных ситуаций
- Иерархия исключительных ситуаций
- Объявление типа исключительной ситуации и оператор throw
- Объявление метода, который может возбуждать исключительную ситуацию. Зарезервированное слово throws
- Работа с файлами и папками
- Краткие итоги по главе 7
- Задания
- Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция Проблемы множественного наследования классов. Интерфейсы
- Отличия интерфейсов от классов. Проблемы наследования интерфейсов
- Пример на использование интерфейсов
- Композиция как альтернатива множественному наследованию
- Краткие итоги по главе 8
- Задания
- Глава 9. Дополнительные элементы объектного программирования на языке Java Потоки выполнения (threads) и синхронизация
- Преимущества и проблемы при работе с потоками выполнения
- Синхронизация по ресурсам и событиям
- Класс Thread и интерфейс Runnable. Создание и запуск потока выполнения
- Поля и методы, заданные в классе Thread
- Подключение внешних библиотек dll.“Родные” (native) методы*
- Краткие итоги по главе 9
- Задания
- Глава 10. Введение в сетевое программирование Краткая справка по языку html
- Апплеты
- Сервлеты
- Технология jsp – Java Server Pages
- Краткие итоги по главе 10
- Задания
- Глава 11. Встроенные классы Виды встроенных классов
- Вложенные (nested) классы и интерфейсы
- Внутренние (inner) классы
- Локальные (local) классы
- Анонимные (anonimous) классы и обработчики событий
- Анонимные (anonimous) классы и слушатели событий (listeners)
- Краткие итоги по главе 11
- Задания
- Глава 12. Компонентное программирование Компонентная архитектура JavaBeans
- Мастер создания компонента в NetBeans
- Пример создания компонента в NetBeans – панель с заголовком
- Добавление в компонент новых свойств
- Добавление в компонент новых событий
- Краткие итоги по главе 12
- Задания
- Литература
- Дополнительная литература
- 276 Курс подготовлен при поддержке Sun Microsystems