Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3 - Лексические структуры языка. Типы данных. И...docx
Скачиваний:
9
Добавлен:
19.11.2019
Размер:
93.32 Кб
Скачать

6.1 Плавающая точка ieee

Язык Java поддерживает два простых типа с плавающей точкой: float и double, и их прототип - класс-оболочка Float и Double. Они основаны на стандарте IEEE 754, определяющем двоичный стандарт для двоично-десятичных чисел с 32-битовой плавающей точкой и 64-битовой плавающей точкой удвоенной точности.

IEEE 754 представляет числа с плавающей точкой как десятичные числа с основанием 2 в экспоненциальном формате. В IEEE числе с плавающей точкой выделяется 1 бит на знак, 8 бит на порядок и 23 бита на мантиссу, или дробную часть числа. Порядок расшифровывается как целое число со знаком, допускающее как положительный, так и отрицательный экспоненты. Дробь представляется как двоично-десятичное (основание 2) число, где самый старший бит соответствует значению ½ (2-1), следующий бит ¼ (2-2), и так далее. Для плавающей точки с удвоенной точностью на порядок выделяется 11 бит, а на мантиссу - 52 бит. Формат значений плавающей точки IEEE показан на рисунке 1.

Рисунок 1. Формат плавающей точки IEEE 754

Так как любое заданное число может быть представлено в экспоненциальном формате различными способами, то числа с плавающей точкой нормализуются таким образом, чтобы они могли быть представлены как десятичные числа с основанием 2, с 1 слева от десятичной точки, подбирая порядок таким образом, чтобы соблюсти данное требование. Следовательно, например, число 1.25 будет представлено с мантиссой 1.01 и порядком 0:

(-1)

Число 10.0 будет представлено с мантиссой 1.01 и порядком 3:

(-1)

6.2 Специальные числа

Помимо стандартного множества значений, разрешенного кодированием (от 1.4e-45 до 3.4028235e+38 для float), существуют и специальные значения, представляющие бесконечность, минус бесконечность, -0, и NaN (обозначает "не число"). Эти значения существуют для того, чтобы в случае возникновения ошибок, например, арифметического переполнения, извлечения квадратного корня из отрицательного числа и деления на 0, можно было получить результат, представленный в диапазоне значений с плавающей точкой.

У таких специальных чисел есть несколько необычных характеристик. Например, 0 и -0 являются четко различимыми значениями, но при сравнении на тождественность они считаются равными. Деление ненулевого числа на бесконечность дает 0. Специальное число NaN является неупорядоченным, а любое сравнение между NaN и другими значениями с плавающей точкой, с использованием операций ==, < и > выдаст неверно. Даже (f == f) выдаст ложь, если f является NaN. Если Вы хотите сравнить значение с плавающей точкой с NaN, то используйте метод Float.isNaN(). В таблице 1 показаны некоторые особенности бесконечности и NaN.

Таблица 1. Особенности специальных значений с плавающей точкой

Выражение

Результат

Math.sqrt(-1.0)

-> NaN

0.0 / 0.0

-> NaN

1.0 / 0.0

-> бесконечность

-1.0 / 0.0

-> -бесконечность

NaN + 1.0

-> NaN

бесконечность + 1.0

-> бесконечность

бесконечность + бесконечность

-> бесконечность

NaN > 1.0

-> ложь

NaN == 1.0

-> ложь

NaN < 1.0

-> ложь

NaN == NaN

-> ложь

0.0 == -0.01

-> истина

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

Еще более усугубляет положение еще и то, что правила сравнения NaN и -0 у простого типа с плавающей точкой и класса-оболочки Float различаются. Для значений float, сравнение на тождественность двух значений NaN выдаст ложь, но при сравнении двух NaN объектов Float при использовании Float.equals(), будет выдано истина. Обоснованием этому может служить то, что иначе будет невозможно использовать NaN объект Float в качестве ключа в HashMap. Аналогично, хотя 0 и -0 и считаются равными, но в случае представления их в качестве значений с плавающей точкой, сравнение 0 и -0 как объектов Float при помощи Float.compareTo() указывает на то, что -0 является меньшей величиной, чем 0.