Денормализованные числа
Денормализованные числа (англ. denormalized numbers) или субнормальные числа[1] (англ. subnormal numbers) — вид чисел с плавающей запятой, определённый в стандарте IEEE 754.
Кодируют числа : мантисса начинается с 0, а не с 1 (нет неявной единицы), а порядок — минимально возможный. Денормализованные числа находятся ближе к 0, чем наименьшее представимое нормализованное число. Машинный 0 — также денормализованное число.
При записи в форматах float (одинарная точность), double (двойная точность) в поле порядка будет записан 0.
В 10-байтовом long double (расширенная точность) нет денормализованных чисел как особого класса, так как в нём присутствует явный бит целой части. Однако сходными свойствами обладают числа с наименьшим порядком (в поле порядка 0) и битом целой части 0.
Предпосылки к появлению
Для экономии памяти используется так называемая неявная единица: числа в двоичном стандартном виде записываются как 1,mmm2·2k, и головная единица не сохраняется. В таком формате невозможно записать ноль — потому машинный ноль обязательно будет каким-то особым числом. Для удобства он должен иметь минимальный порядок.
То, что эти особые числа не просто нули, а 0,mmm·2−126 (в 4-байтовом float), даёт дополнительную выгоду: сложение и вычитание не приведёт к антипереполнению (к обнулению результата), если результатом операции не является точный 0. Другими словами, благодаря введению денормализованных чисел условия и эквивалентны, какие бы близкие (по мантиссе) и малые (по порядку) числа мы бы ни вычитали. Без введения денормализованных чисел результатом такой операции мог бы быть 0, даже если числа не равны. То же относится к сложению чисел, близких по модулю, но разного знака. Это может быть нежелательно, например приводить к ошибке деления на ноль, если результат используется в качестве делителя[2].
В противовес, на калькуляторе МК-61 вычитание 1,8·10−99 − 1,2·10−99 даст ноль, хотя числа не равны.
Вопросы реализации
Некоторые[какие?] процессоры и математические сопроцессоры работают с денормализованными числами аппаратным способом с той же скоростью, что и с нормализованными. В других же такая аппаратная обработка не реализована (например, чтобы избежать усложнения реализации FPU), и малые значения либо приводятся сразу к нулю (см. антипереполнение), либо обрабатываются в операционной системе программным способом. Второй вариант приводит к увеличению времени обработки денормализованных чисел.
Денормализованные числа были реализованы в математическом сопроцессоре Intel 8087 в то время, когда стандарт IEEE 754 был в процессе написания. Они были наиболее спорной особенностью предложенной заявки, которая в конце концов была принята[3], но эта реализация продемонстрировала возможность аппаратной работы с денормализованными числами на практике. Некоторые реализации модулей работы с плавающей точкой аппаратно не поддерживают денормализованные числа, выполняя их обработку программно. Хотя такая обработка прозрачна для пользователя, она может приводить к тому, что расчёты, генерирующие или получающие на вход денормализованные числа, будут выполняться намного дольше, чем те же расчёты с нормализованными числами.
В качестве примера системы, где формат представления чисел не включал денормализованные числа, можно привести ZX Spectrum.
Недостатки
Причина, по которой были введены денормализованные числа, является частью более общей вычислительной проблемы нахождения суммы чисел при использовании ограниченной точности (см., например, алгоритм Кэхэна). Причём проблема, решаемая введением денормализованных чисел, возникает в сравнительно узком диапазоне чисел — вблизи границы потери значимости. Но аналогичная проблема может быть связана и с переполнением: например, если мы захотим сравнить два числа и разного знака, порядок которых максимальный, то условие будет успешно проверено и даст отрицательный результат, а условие может привести к ошибке переполнения. Таким образом, в общем случае денормализованные числа не решают проблему зависимости результата от перестановки слагаемых, и от программиста при работе с плавающей арифметикой всё равно требуется определённая аккуратность. В случае, если программисту приходится работать с числами на грани потери значимости, более целесообразным представляется переход к формату с более широким диапазоном порядков либо использование специальных мер для контроля за величиной порядка, чем рассчитывать на денормализованные числа. К тому же нужно помнить, что денормализованные числа имеют меньше значащих цифр мантиссы по сравнению с обычным для данного формата, а это чревато существенной потерей точности.
Примечания
- Немнюгин С. А. Конспекты лекций по курсу «Введение в информатику и системы программирования», Лекция 9. Архитектура ЭВМ: Форматы хранения данных. Машинная арифметика. С. 5 Архивная копия от 25 октября 2018 на Wayback Machine
- William Kahan. IEEE 754R meeting minutes, 2002 (недоступная ссылка). Дата обращения: 1 декабря 2013. Архивировано 15 октября 2016 года. (англ.)
- An Interview with the Old Man of Floating-Point . University of California, Berkeley. (англ.)
Ссылки
- Яшкардин В. Л. IEEE 754 — стандарт двоичной арифметики с плавающей точкой . SoftElectro (2009).