Представление IEEE с плавающей запятой

Microsoft C++ (MSVC) поддерживает стандартные числовые форматы IEEE. В стандарте IEEE-754 описываются форматы с плавающей запятой, которые используются для аппаратного представления действительных чисел. Есть как минимум пять внутренних числовых форматов для чисел с плавающей запятой, которые могут быть представлены в оборудовании, предназначенном для компилятора MSVC. Компилятор использует только два из них. В MSVC используются форматы с одиночной (4 байта) и двойной (8 байтов) точностью. Формат одиночной точности объявляется с помощью ключевого слова float. Формат двойной точности объявляется с помощью ключевого слова double. В стандарте IEEE определяются еще форматы половинной (2 байта) и четырехкратной (16 байтов) точности, а также формат расширенной двойной (10 байтов) точности, который реализуется некоторыми компиляторами C и C++ как тип данных long double. В компиляторе MSVC тип данных long double рассматривается как отдельный тип, но в качестве типа хранения с ним сопоставляется тип double. Тем не менее вычисления с использованием других форматов, в том числе расширенной двойной точности, могут поддерживаться некоторым оборудованием на собственном уровне или на уровне языка ассемблера.

Значения хранятся в следующем виде:

Значение Хранение
одиночная точность разряд знака, 8 разрядов показателя степени, 23 разряда значащей части
двойная точность разряд знака, 11 разрядов показателя степени, 52 разряда значащей части

В форматах с одиночной и двойной точностью в дробной части предполагается первый символ 1. Дробная часть называется значащей частью или мантиссой. Это начальное значение 1 не сохраняется в памяти, так что по сути значащая часть имеет длину 24 или 53 бита, из которых хранится на один бит меньше. В формате расширенной двойной точности этот разряд сохраняется в памяти.

Величина показателя степени смещена наполовину относительно возможного значения. Это значит, что для получения фактического значения экспоненты необходимо вычесть это смещение из хранящегося в памяти значения. Если сохраненное в памяти значение экспоненты меньше смещения, значит экспонента отрицательная.

Смещение показателя степени определяется следующим образом:

Exponent Величина смещения
8 разрядов (одиночная точность) 127
11 разрядов (двойная точность) 1023

Эти экспоненты определяют показатели степени для двойки, а не для десятки. Таким образом, для 8-разрядного формата фактические показатели степени в диапазоне от –127 до 127 хранятся в памяти соответственно в виде значений в диапазоне от 0 до 254. Значение 2127 примерно равно 1038 и определяет фактический предел для чисел с одиночной точностью.

Значащая часть хранится в виде двоичной части в форме 1.XXX... Эта часть имеет значение больше 1 и меньше 2. Вещественные числа всегда хранятся в нормализованном представлении. В частности, значение значащей части всегда смещается влево, чтобы ее старший бит имел значение 1. Так как этот разряд всегда равен 1, для форматов одиночной и двойной точности его значение принимается по умолчанию и не хранится в памяти. Двоичная (не десятичная) точка располагается непосредственно справа от начальной 1.

Формат представления с плавающей запятой выглядит следующим образом:

Форматировать байт 1 байт 2 байт 3 байт 4 ... байт n
одиночная точность SXXXXXXX XMMMMMMM MMMMMMMM MMMMMMMM
двойная точность SXXXXXXX XXXXMMMM MMMMMMMM MMMMMMMM ... MMMMMMMM

S представляет разряд знака, X — это разряды смещенного показателя степени, а M — это значащие разряды. В форматах одиночной и двойной точности значение самого левого бита предполагается.

Чтобы правильно определить смещение двоичной точки, необходимо сначала выделить показатель степени, а затем сместить двоичную точку вправо или влево на соответствующее количество разрядов.

Специальные значения

Форматы с плавающей запятой предусматривают некоторые значения, которые обрабатываются особым образом.

Ноль

Значение нуля невозможно представить в нормализованном виде, который используется для форматов одиночной и двойной точности. Таким образом, для определения значения 0 используется специальный шаблон, состоящий из нулей. При необходимости с помощью разряда знака можно представить значение –0, однако оно всегда будет сопоставляться как равное 0.

Бесконечность

Значения +∞ и −∞ представляются с экспонентой из одних единиц и мантиссой из одних нулей. Разряд знака определяет знак бесконечности.

Субнормальные числа

Числа, которые находятся ближе к нулю, чем наименьшее число в нормализованном преставлении, могут быть представлены. Такие числа называются субнормальными или денормализованными. Если показатель степени представлен одними нулевыми значениями, а значащая часть отлична от нуля, старший бит значащей части принимается равным нулю, а не единице. Точность субнормальных чисел снижается по мере увеличения количества начальных нулей в значащей части.

NaN (не число)

В формате IEEE с плавающей запятой могут быть представлены значения, не являющиеся действительными числами, например 0/0. Значения такого вида называются NaN (не число). Значение NaN представляется состоящим из единиц показателем степени и отличной от нуля значащей частью. Существует два вида значений NaN: несигнальные (QNaN) и сигнальные (SNaN). Для несигнальных значений NaN старший разряд значащей части равен единице, и эти значения распространяются через выражения. Они представляют неопределенные значения, например результат деления на бесконечность или умножения бесконечности на нуль. Для сигнальных значений NaN старший разряд значащей части равен нулю. Эти значения используются для недопустимых операций, указывая на аппаратное исключение, связанное с обработкой чисел с плавающей запятой.

Примеры

Ниже приводятся примеры чисел в формате одиночной точности:

  • Для значения 2 знаковый бит имеет значение 0. Сохраняется экспонента 128, то есть двоичное значение 1000 0000, вычисляемое как 127 плюс 1. Хранимый двоичный знак имеет значение (1.) 000 0000 0000 0000 0000, что имеет подразумеваемую ведущую 1 и двоичную точку, поэтому фактический знак является одним.

    Значение Формула Двоичное представление Шестнадцатеричное
    2 1 * 21 0100 0000 0000 0000 0000 0000 0000 0000 0x40000000
  • Значение –2. То же, что и + 2, однако в этом случае задан разряд знака. Таким же образом задаются отрицательные числа во всех форматах IEEE с плавающей запятой.

    Значение Формула Двоичное представление Шестнадцатеричное
    -2 –1 * 21 1100 0000 0000 0000 0000 0000 0000 0000 0xC0000000
  • Значение 4. Та же значащая часть, показатель степени увеличивается на единицу (смещенное значение 129 или 100 0000 1 в двоичном формате).

    Значение Формула Двоичное представление Шестнадцатеричное
    4 1 * 22 0100 0000 1000 0000 0000 0000 0000 0000 0x40800000
  • Значение 6. Тот же показатель степени; значащая часть увеличивается наполовину. Это (1.) 100 0000 ... 0000 0000, который, так как это двоичная дробь, составляет 1 1/2, потому что значения дробных цифр : 1/2, 1/4, 1/8 и т. д.

    Значение Формула Двоичное представление Шестнадцатеричное
    6 1.5 * 22 0100 0000 1100 0000 0000 0000 0000 0000 0x40C00000
  • Значение 1. Та же значащая часть, что и для остальных степеней двух; смещенный показатель степени на единицу меньше, чем у двух при 127, то есть 011 1111 1 в двоичном формате.

    Значение Формула Двоичное представление Шестнадцатеричное
    1 1 * 20 0011 1111 1000 0000 0000 0000 0000 0000 0x3F800000
  • Значение 0,75. Предвзятый экспонент равен 126, 011 1111 0 в двоичном файле, а знаки — (1.) 100 0000 ... 0000 0000, что составляет 1 1/2.

    Значение Формула Двоичное представление Шестнадцатеричное
    0.75 1.5 * 2-1 0011 1111 0100 0000 0000 0000 0000 0000 0x3F400000
  • Значение 2,5. Так же, как и два, однако в значащей части задан разряд, который представляет 1/4.

    Значение Формула Двоичное представление Шестнадцатеричное
    2.5 1.25 * 21 0100 0000 0010 0000 0000 0000 0000 0000 0x40200000
  • 1/10 — это повторяющаяся часть в двоичном формате. Значащая часть здесь немного меньше 1,6, а экспонента с учетом смещения указывает, что 1,6 нужно разделить на 16. (Это 011 1101 1 в двоичном файле, что составляет 123 в десятичном разряде.) Истинный экспонент равен 123 – 127 = -4, что означает, что коэффициент умножения равен 2-4 = 1/16. Хранимая в памяти значащая часть округляется до последнего разряда, чтобы представить выходящие за пределы числа с максимально возможной точностью. (Величины 1/10 и 1/100 нельзя точно представить в двоичном формате по той же причине, по которой 1/3 нельзя представить в десятичном.)

    Значение Формула Двоичное представление Шестнадцатеричное
    0,1 1.6 * 2-4 0011 1101 1100 1100 1100 1100 1100 1101 0x3DCCCCCD
  • Нуль рассматривается как особый случай. Для него используется формула минимального положительного числа, которое может быть представлено, то есть представление из одних нулей.

    Значение Формула Двоичное представление Шестнадцатеричное
    0 1 * 2-128 0000 0000 0000 0000 0000 0000 0000 0000 0x00000000

См. также

Почему может уменьшиться точность чисел с плавающей запятой