C: как двойное число (например, 123.45) хранится в переменной с плавающей запятой, двойной переменной или длинной двойной переменной? - PullRequest
3 голосов
/ 30 июня 2011
#include <stdio.h>

int main () {
float a = 123.0; 

unsigned char ch, *cp;
ch = 0xff;

cp = (unsigned char *) &a;
printf ("%02x", ch&(*(cp+3)));
printf ("%02x", ch&(*(cp+2)));
printf ("%02x", ch&(*(cp+1)));
printf ("%02x\n", ch&(*(cp+0)));

/*I have written this program to see binary representation, but I can not understand the output, the binary representation?
}

Ответы [ 3 ]

9 голосов
/ 30 июня 2011

См. Википедию: http://en.wikipedia.org/wiki/Single_precision_floating-point_format,, которая описывает плавающую точку одинарной точности (типичный C float, но зависит от компилятора) как 1-битный знак, 8-битный смещенный показатель и 24-битный мантисса(Сохранено 23 бита).

Для вашего примера:

123.0 = 42f60000 hex = 0 10000101 11101100000000000000000 bin
1-битный знак = 0 (указывает положительное число)
8-битный смещенный показатель = 10000101 bin = 133 dec - 127 dec = 6 dec
23-битная мантисса = 11101100000000000000000 bin = 1.111011 bin (примечание подразумевает ведущий 1)

Преобразование 1.111011 bin x 2 6 dec = 1111011.0 bin = 123.0 dec

1 голос
/ 30 июня 2011

догадываясь о вашем вопросе how is double number (e.g. 123.45) stored in a float variable or double variable or long double variable?: если вы храните двойное значение (например, литерал "123.0") в переменной с плавающей запятой, компилятор static_cast<float> изменит значение, чтобы оно стало допустимымзначение с плавающей точкой.

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

int main () {
    float foo = 123.0;
}

в основном совпадает с

int main () {
    float foo = static_cast<float>(123.0);
}

Если вы хотите явно указать плавающее число-literal, используйте постфикс f или F:

int main () {
    float foo = 123.0f; // alternatively: 123.f, 123.F
}

edit: от стандарта

Только что посмотрел грамматику для плавающих литералов, для любопытных:

floating-literal:
    fractional-constant exponent-part_opt floating-suffix_opt
    digit-sequence exponent-part floating-suffix_opt

fractional-constant:
    digit-sequence_opt . digit-sequence
    digit-sequence .

exponent-part:
    e sign_opt digit-sequence
    E sign_opt digit-sequence

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

float a = 1.f,
      b = 1.0f,
      c = .0f,
      d = 1e1f,
      e = 1.e1f,
      f = 1e-1f,
      g = 1e+1f,
      h = 1E+1F;

Если необходимо преобразование, например,

float a = 1., // double
      b = 1.L,// long double
      c = 1;  // integer

применимо следующее:

4.8 Преобразования с плавающей точкой [conv.double]

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

4.9 Плавающее-интегральное преобразование_ [conv.fpint]:

r-значение целого типа илитип перечисления может быть преобразован в значение типа с плавающей запятой.Результат точен, если это возможно.Значение типа integer или типа перечисления может быть преобразовано в значение типа с плавающей запятой.Результат точен, если это возможно.В противном случае это определяемый реализацией выбор следующего более низкого или более высокого представимого значения.

Итак, если вы введете литерал типа double или long double (или некоторое целое число) в float, компилятор неявно преобразует это значение, если оно может быть преобразовано точно.В противном случае, это зависит от платформы, как сохраняется результат;если значение превышает представимый диапазон, вы попадаете в мир неопределенного поведения *.


* Страшное царство неопределенного поведения, где злоавтору компилятора может быть смешно издавать адский звук через ваши громкоговорители и заставлять вас кровоточить через уши, и при этом по-прежнему налагаться санкции по стандарту (хотя не обязательно по местным законам).

0 голосов
/ 30 июня 2011

Чтобы понять, как работает двоичная разметка переменных с плавающей запятой, я рекомендую вам прочитать статью википедии соответствующей стандартизации.1005 *, double, long double, соответственно реализации half), состоят из богомола и показателя степени для представления числа.

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