Как числа с плавающей запятой хранятся в памяти? - PullRequest
28 голосов
/ 04 октября 2011

Я читал, что они хранятся в форме мантиссы и показателя

Я прочитал этот документ , но я ничего не мог понять.

Ответы [ 7 ]

43 голосов
/ 04 октября 2011

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

В отличие от целых чисел, значение с плавающей запятой предназначено для представления как чрезвычайно малых значений, так и очень больших. Для обычных 32-битных значений с плавающей точкой это соответствует значениям в диапазоне от 1.175494351 * 10 ^ -38 до 3.40282347 * 10 ^ + 38 .

Очевидно, что, используя только 32 бита, невозможно сохранить каждую цифру в таких числах.

Когда дело доходит до представления, вы можете видеть все нормальные числа с плавающей запятой в виде значений в диапазоне от 1,0 до (почти) 2,0, масштабированных со степенью двойки. Так что 1.0 это просто 1.0 * 2 ^ 0 . 2,0 1,0 * 2 ^ 1 . -5.0 это -1.25 * 2 ^ 2 .

Итак, что нужно для того, чтобы закодировать это максимально эффективно? Что нам действительно нужно?

  • Знак выражения.
  • Показатель степени
  • Значение в диапазоне от 1,0 до (почти) 2,0. Это известно как "мантисса", то есть значение.

Это кодируется следующим образом в соответствии со стандартом IEEE-754.

  • Знак - один бит.
  • Показатель степени хранится в виде целого числа без знака, для 32-битных значений с плавающей запятой это поле равно 8 битам. 1 представляет наименьший показатель степени, а «все единицы - 1» наибольший. (0 и «все единицы» используются для кодирования специальных значений, см. Ниже.) Значение в середине (127, в 32-битном случае) представляет ноль, это также известно как смещение .
  • Глядя на мантиссу (значение от 1,0 до (почти) 2,0), можно увидеть, что все возможные значения начинаются с «1» (как в десятичном, так и в двоичном представлении). Это означает, что нет смысла хранить его. Остальные двоичные цифры хранятся в целочисленном поле, в 32-разрядном случае это поле составляет 23 бита.

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

  • Ноль кодируется с показателем степени и мантиссой как ноль. Знаковый бит используется для обозначения «плюс ноль» и «минус ноль». Минус ноль полезен, когда результат операции чрезвычайно мал, но все равно важно знать, из какого направления произошла операция.
  • плюс и минус бесконечность - представлены с использованием показателя «все единицы» и нулевого поля мантиссы.
  • Не число (NaN) - представлено с использованием показателя «все единицы» и ненулевой мантиссы.
  • Денормализованные числа - числа, меньшие наименьшего нормального числа. Представлено с использованием поля нулевого показателя и ненулевой мантиссы. Особенность этих чисел заключается в том, что точность (то есть количество цифр, которое может содержать значение) будет падать по мере уменьшения значения просто потому, что в мантиссе нет места для них.

Наконец, ниже приведено несколько конкретных примеров (все значения в шестнадцатеричном формате):

  • 1,0: 3f800000
  • -1234.0: c49a4000
  • 100000000000000000000000.0: 65a96816
9 голосов
/ 04 октября 2011

С точки зрения непрофессионала, это по сути научная запись в двоичном виде. Формальный стандарт (с подробностями): IEEE 754 .

6 голосов
/ 04 октября 2011
  typedef struct {
      unsigned int mantissa_low:32;     
      unsigned int mantissa_high:20;
      unsigned int exponent:11;        
      unsigned int sign:1;
    } tDoubleStruct;

double a = 1.2;
tDoubleStruct* b = reinterpret_cast<tDoubleStruct*>(&a);

Это пример того, как устанавливается память, если компилятор использует двойную точность IEEE 754, которая является значением по умолчанию для двойного C в системах с прямым порядком байтов (например, Intel x86).

Здесь это в Cоснованный на двоичной форме и лучше прочитать википедию о двойной точности , чтобы понять это.

2 голосов
/ 04 октября 2011

Существует несколько различных форматов с плавающей точкой.Большинство из них имеют несколько общих характеристик: бит знака, некоторые биты, предназначенные для хранения показателя, и некоторые биты, предназначенные для хранения значения и (также называемого мантиссой).

Стандарт IEEE с плавающей точкой пытаетсяопределить один формат (или, вернее, набор форматов нескольких размеров), который может быть реализован в различных системах.Он также определяет доступные операции и их семантику.Он довольно хорошо зарекомендовал себя, и большинство систем, с которыми вы можете столкнуться, вероятно, используют IEEE с плавающей запятой.Но все еще используются другие форматы, а также не совсем полные реализации IEEE.Стандарт C обеспечивает необязательную поддержку IEEE, но не обязывает ее.

1 голос
/ 04 октября 2011

Я нашел статью, на которую вы ссылались, довольно неразборчивой (и я действительно немного знаю, как работают поплавки IEEE). Я предлагаю вам попробовать с Wiki-версией объяснения. Это довольно ясно и имеет различные примеры:

http://en.wikipedia.org/wiki/Single_precision и http://en.wikipedia.org/wiki/Double_precision

1 голос
/ 04 октября 2011

Мантисса представляет наиболее значимые биты числа.

Показатель степени показывает, сколько смен должно быть выполнено в мантиссе, чтобы получить фактическое значение числа.

Кодировка указывает, как представлены знак мантиссы и знак экспоненты (в основном, смещается ли влево или вправо).

В документе, на который вы ссылаетесь, указывается кодировка IEEE, наиболее широко используемая.

0 голосов

Это определяется реализацией, хотя IEEE-754 является наиболее распространенным на сегодняшний день.

Чтобы быть уверенным, что используется IEEE-754:

  • в С, используйте #ifdef __STDC_IEC_559__
  • в C ++, используйте std::numeric_limits<float>::is_iec559 константы

Я написал несколько руководств по IEEE-754 по адресу:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...