Денормализованные числа

Материал из Википедии — свободной энциклопедии
(перенаправлено с «Субнормальное число»)
Перейти к навигации Перейти к поиску

Денормализованные числа (англ. 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 (процессор Zilog Z80) .

Недостатки[править | править код]

Причина, по которой были введены денормализованные числа, является частью более общей вычислительной проблемы нахождения суммы чисел при использовании ограниченной точности (см., например, алгоритм Кэхэна). Причём проблема, решаемая введением денормализованных чисел, возникает в сравнительно узком диапазоне чисел — вблизи границы потери значимости. Но аналогичная проблема может быть связана и с переполнением: например, если мы захотим сравнить два числа и разного знака, порядок которых максимальный, то условие будет успешно проверено и даст отрицательный результат, а условие может привести к ошибке переполнения. Таким образом, в общем случае денормализованные числа не решают проблему зависимости результата от перестановки слагаемых, и от программиста при работе с плавающей арифметикой всё равно требуется определённая аккуратность. В случае, если программисту приходится работать с числами на грани потери значимости, более целесообразным представляется переход к формату с более широким диапазоном порядков либо использование специальных мер для контроля за величиной порядка, чем рассчитывать на денормализованные числа. К тому же нужно помнить, что денормализованные числа имеют меньше значащих цифр мантиссы по сравнению с обычным для данного формата, а это чревато существенной потерей точности.

Примечания[править | править код]

  1. Немнюгин С. А. Конспекты лекций по курсу «Введение в информатику и системы программирования», Лекция 9. Архитектура ЭВМ: Форматы хранения данных. Машинная арифметика. С. 5 Архивная копия от 25 октября 2018 на Wayback Machine
  2. William Kahan. IEEE 754R meeting minutes, 2002. Дата обращения: декабрь 2013. Архивировано из оригинала 15 октября 2016 года. (англ.)
  3. An Interview with the Old Man of Floating-Point. University of California, Berkeley. Дата обращения: 11 сентября 2016. Архивировано 25 апреля 2016 года. (англ.)

Ссылки[править | править код]