Николай Терновой. Канал с заметками: https://t.me/cpu_design

Сегодня поговорим о таком механизме как NaN boxing, косвенно затронем тему представления значений в формате NaN [Not-a-Number].

Зачем же боксируют между собой значения NaN и что им друг от друга нужно? Давайте вспомним значения битовых полей в представлении чисел в формате IEEE-754 [рассмотрим 32/64-битные случаи].

fp64/32 - это double и float сответственно

fp64/32 - это double и float сответственно

Битовая строка для формата IEEE-754 состоит из трех полей: поле знака, поле экспоненты, поле мантиссы [если будет интерес к тому почему для стандарта выбрали именно такие поля и какой в них математический смысл - пишите, обсудим это в последующих заметках]. Например число записанное в виде 0x40080000, ничто иное как число 2,125. [ссылка на конвертер]

Двоичное представление числа представлено на картинке ниже.

В далеком 1985-м году, когда был утвержден первый стандарт представления чисел с плавающей точкой для ЭВМ, в нем было введены операции с NaN. NaN, в свою очередь, разделяются на 2 подмножества: qNaN [тихие NaN] и sNaN [сигнальные NaN]. В чем же различие между ними? Давайте обратимся к стандарту 1985-го года.

Когда упоминаются годы выпуска стандарта: 1985, 2008 - не стоит это воспринимать, как два абсолютно разных и не зависимых стандарта. IEEE-754 1985/2008/2019 все обратно совместимы друг с другом. В контексте данной статьи год выпуска стандарта не играет какой-либо существенной роли и упоминается он только для того, чтобы показать, что разработка стандарта IEEE-754 не стоит на месте.

Из стандарта следует, что sNaN сигнализирует [он же все таки signaling] о произошедшей недопустимой операции, например, деление на нуль, извлечение квадратного корня из отрицательного числа.

Кстати, а вы никогда не задумывались, а почему корень квадратный? Вы же видели корни деревьев, мне кажется они совсем не квадратные. Крутая этимологическая заметка - тут

Для всех этих недопустимых операций возвращается sNaN, генерирующий прерывания. Сигналы формата qNaN в далеких 80-х служили отладочной информацией для разработчиков, помогали находить проблемные места, ошибки в вычислениях/алгоритмах. На сегодняшний день с современными средствами отладки и моделирования актуальность армии NaN'ов [по крайней мере, в текущем виде] остается под вопросом.

На практике многие разработчики микропроцессоров по своему воспринимают и обрабатывают qNaN/sNaN и отходят от определений стандарта. Как видно из функции ниже, в зависимости от порядка скобок операция minNum в одном случае возвращает 1, а в другом qNaN [в 2019-м стандарте IEEE-754 данная операция была заменена аналогичной, математически корректной функцией].

Ниже приведена сравнительная таблица, где рассматривается скандальная операция fmin [IEEE-754-2008] и как она имплементирована в различных компиляторах, процессорах.

Ранее мы рассмотрели битовые поля стандарта IEEE-754. Теперь рассмотрим, как NaN записываются в битовой строке.