我从书籍计算机系统:程序员的视角中学到,IEEE标准要求使用以下64位二进制格式来表示双精度浮点数:
- s:1位符号位
- exp:11位指数位
- frac:52位小数位
+无穷大被表示为以下特殊值:
- s = 0
- 所有的exp位都是1
- 所有的frac位都是0
我认为完整的64位双精度应该按照以下顺序:
(s)(exp)(frac)
因此我编写了以下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
为什么这个数字是有效的数字,而不是无穷大错误?
为什么x1等于x2?
(我正在使用MinGW GCC编译器。)
ADD 1
我修改了以下代码并成功验证了无穷大和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
格式。
ADD 2
出于好奇,我使用以下代码检查了变量的位表示。
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???
它们为什么不同?y4是如何获得的?