双精度浮点数的精确二进制表示

5

可能是重复问题:
C++中的浮点数转二进制

我有一个非常小的双精度变量,在打印时得到-0。(使用C++)。 现在为了获得更好的精度,我尝试使用

cout.precision(18); \\i think 18 is the max precision i can get.
cout.setf(ios::fixed,ios::floatfield);
cout<<var;\\var is a double.

但它只是写入了-0.00000000000...

我想看到变量的精确二进制表示。

换句话说,我想知道在堆栈内存/寄存器中为此变量编写了哪个二进制数字。


你可以使用调试器。 - Bashwork
3个回答

8
union myUnion {
    double dValue;
    uint64_t iValue;
};

myUnion myValue;
myValue.dValue=123.456;
cout << myValue.iValue;

更新:

上述版本适用于大多数情况,但它假设64位双精度浮点数。这个版本不做任何假设并生成二进制表示:

    double someDouble=123.456;
    unsigned char rawBytes[sizeof(double)];

    memcpy(rawBytes,&someDouble,sizeof(double));

    //The C++ standard does not guarantee 8-bit bytes
    unsigned char startMask=1;
    while (0!=static_cast<unsigned char>(startMask<<1)) {
        startMask<<=1;
    }

    bool hasLeadBit=false;   //set this to true if you want to see leading zeros

    size_t byteIndex;
    for (byteIndex=0;byteIndex<sizeof(double);++byteIndex) {
        unsigned char bitMask=startMask;
        while (0!=bitMask) {
            if (0!=(bitMask&rawBytes[byteIndex])) {
                std::cout<<"1";
                hasLeadBit=true;
            } else if (hasLeadBit) {
                std::cout<<"0";
            }
            bitMask>>=1;
        }
    }
    if (!hasLeadBit) {
        std::cout<<"0";
    }

6
这种方法是按照标准保证可行的:
double d = -0.0;
uint64_t u;
memcpy(&u, &d, sizeof(d));
std::cout << std::hex << u;

1
保证 sizeof(double) == sizeof(uint64_t),当然这是一个相当安全的猜测。同时也要保证实现中存在 uint64_t,这是相当安全的,但在旧版本的 MSVC 中需要自己提供定义它的头文件。 - Steve Jessop
1
谢谢你的回答,但这给我一个十六进制表示,我需要一个二进制的。 - user690936
@user690936:每个十六进制数字代表4位二进制数,最好学会读取十六进制。但是你可以编写一个循环,以每次打印1位二进制数为0/1,或者你可以使用calc.exe(在Windows上)进行转换。 - Steve Jessop
@user690936 - 我认为他们回答的问题是,一个double在二进制文件中是什么样子。你可能想问的是,如何将double转换为二进制。 - sf_jeff

1

尝试:

printf("0x%08x\n", myFloat);

这应该适用于32位变量,以十六进制显示它。我从未尝试过使用此技术查看64位变量,但我认为它是:

printf("%016llx\n", myDouble);

编辑:测试了64位版本,它在Win32上绝对可行(我似乎记得GCC需要大写LL..也许)

编辑2:如果你真的想要二进制,最好使用其他答案之一来获取double的uint64_t版本,然后循环:

for ( int i = 63; i >= 0; i-- )
{
    printf( "%d", (myUint64 >> i ) & 1 );
}

谢谢您的回复。它并没有给出一个二进制数。 对于数字2.0,它写成:0x00000000。 它应该输出10,不是吗? - user690936
我刚刚在我的电脑上尝试了一下,它按预期工作了。这段代码以十六进制打印,而不是二进制。此外,您的评论表明您不了解整数表示的2和浮点版本之间的区别。具有值为2的int具有二进制表示为10,但float则完全不同。 - Hybrid
我知道2的整数表示和浮点数版本有所区别。但我仍然需要一个二进制表示,即{0,1}的表示形式。 - user690936

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接