与 long 复制的位不同的两个双精度打印不同

Two doubles with bits copied differently from a long are printed differently

如下面的代码所示,我正在尝试使用不同的方法将位从长 longnum 复制到两个双打 d1d2:指针转换+ 分别取消引用和“按位与”。

# include <stdio.h>

int main(void) {
    long longnum = 0xDDDDDDDDDDDDDDDD;
    double d1 = *((double*)(&longnum));
    double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

    printf("%ld\n\n",longnum);
    printf("%lf\n\n",d1);
    printf("%lf\n",d2);
    return 0;
}

问题是两个双打的打印方式不同,如下面的输出所示。

-2459565876494606883

-1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000

15987178197214945280.000000

考虑到 DBL_MAX 的大小,一个双打的最大大小,在我看来,这是一个巨大的数字,实际上是打印的两个双打的合理输出。

double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

& 掩码没有任何作用。一个数字与全 1 的 AND 运算是相同的数字。上面的行与:

没有区别
double d2 = longnum;

该行没有进行任何重新解释。相反,它将 d2 设置为最接近代表 longnum 中的值的 double。价值将是相似的;位模式将完全不同。

做你想做的事情的最好方法是加入工会。工会是执行 type punning.

的最佳方式
union {
     long l;
     double d;
} u;

u.l = longnum;
printf("%f\n\n", u.d);

像使用 d1 那样使用指针在技术上会调用未定义的行为。这是一个常见的习语,在实践中可能会很好地工作,但应该避免使用指针进行类型双关。

你的问题是

d1 = *((double*)(&longnum));

通过执行上述操作,您错误地从内存中获取内容,然后假设它是双精度格式。

如果您通过以下方式完成:

d1 = (double) longnum;

然后内存space longnum的内容,一个8字节整数,被正确转换然后存储 正确地存储在 d1 指向的位置的内存中。 然后 d1 的内容将是正确的。 建议您阅读有关 "Double-precision floating-point format"

的维基百科页面

浮点值(或双精度值)在内存中的存储方式与整数不同。 https://en.wikipedia.org/wiki/Double-precision_floating-point_format