Как бесконечность представлена в C двойном?
Я узнал из книгиКомпьютерные системы: взгляд программиста что стандарт IEEE требует представления числа с плавающей запятой двойной точности в следующем 64-битном двоичном формате:
s: 1 бит для знакаexp: 11 бит для показателя степениГРП: 52 бита для дроби+ Бесконечность представляется как специальное значение со следующим шаблоном:
с = 0все биты опыта 1все биты дроби равны 0И я думаю, что полная 64-битная для double должна быть в следующем порядке:
(Ы) (ехр) (ГРП)
Поэтому я пишу следующий код C, чтобы проверить это:
//Check the infinity
double x1 = (double)0x7ff0000000000000; // This should be the +infinity
double x2 = (double)0x7ff0000000000001; // Note the extra ending 1, x2 should be NaN
printf("\nx1 = %f, x2 = %f sizeof(double) = %d", x1,x2, sizeof(x2));
if (x1 == x2)
printf("\nx1 == x2");
else
printf("\nx1 != x2");
Но результат:
x1 = 9218868437227405300.000000, x2 = 9218868437227405300.000000 sizeof(double) = 8
x1 == x2
Почему число является действительным числом, а не ошибкой бесконечности?
Почему х1 == х2?
(Я использую компилятор MinGW GCC.)
ДОБАВИТЬ 1Я изменил код, как показано ниже, и успешно проверил Infinity и NaN.
//Check the infinity and NaN
unsigned long long x1 = 0x7ff0000000000000ULL; // +infinity as double
unsigned long long x2 = 0xfff0000000000000ULL; // -infinity as double
unsigned long long x3 = 0x7ff0000000000001ULL; // NaN as double
double y1 =* ((double *)(&x1));
double y2 =* ((double *)(&x2));
double y3 =* ((double *)(&x3));
printf("\nsizeof(long long) = %d", sizeof(x1));
printf("\nx1 = %f, x2 = %f, x3 = %f", x1, x2, x3); // %f is good enough for output
printf("\ny1 = %f, y2 = %f, y3 = %f", y1, y2, y3);
Результат:
sizeof(long long) = 8
x1 = 1.#INF00, x2 = -1.#INF00, x3 = 1.#SNAN0
y1 = 1.#INF00, y2 = -1.#INF00, y3 = 1.#QNAN0
Детальный вывод выглядит немного странно, но я думаю, что суть ясна.
PS .: Кажется, преобразование указателя не нужно. Просто используйте%f
рассказатьprintf
функция для интерпретацииunsigned long long
переменная вdouble
формат.
Из любопытства я проверил представление битов переменных с помощью следующего кода.
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len)
{
int i;
for (i = len-1; i>=0; i--)
{
printf("%.2x", start[i]);
}
printf("\n");
}
И я попробовал код ниже:
//check the infinity and NaN
unsigned long long x1 = 0x7ff0000000000000ULL; // +infinity as double
unsigned long long x2 = 0xfff0000000000000ULL; // -infinity as double
unsigned long long x3 = 0x7ff0000000000001ULL; // NaN as double
double y1 =* ((double *)(&x1));
double y2 =* ((double *)(&x2));
double y3 = *((double *)(&x3));
unsigned long long x4 = x1 + x2; // I want to check (+infinity)+(-infinity)
double y4 = y1 + y2; // I want to check (+infinity)+(-infinity)
printf("\nx1: ");
show_bytes((byte_pointer)&x1, sizeof(x1));
printf("\nx2: ");
show_bytes((byte_pointer)&x2, sizeof(x2));
printf("\nx3: ");
show_bytes((byte_pointer)&x3, sizeof(x3));
printf("\nx4: ");
show_bytes((byte_pointer)&x4, sizeof(x4));
printf("\ny1: ");
show_bytes((byte_pointer)&y1, sizeof(y1));
printf("\ny2: ");
show_bytes((byte_pointer)&y2, sizeof(y2));
printf("\ny3: ");
show_bytes((byte_pointer)&y3, sizeof(y3));
printf("\ny4: ");
show_bytes((byte_pointer)&y4, sizeof(y4));
Выход:
x1: 7ff0000000000000
x2: fff0000000000000
x3: 7ff0000000000001
x4: 7fe0000000000000
y1: 7ff0000000000000
y2: fff0000000000000
y3: 7ff8000000000001
y4: fff8000000000000 // <== Different with x4
Странная часть: хотя x1 и x2 имеют битовую комбинацию, идентичную y1 и y2, сумма x4 отличается от y4.
А также
printf("\ny4=%f", y4);
дает это:
y4=-1.#IND00 // What does it mean???
Почему они разные? И как получается у4?