在C++中检测存储为双精度浮点数的负零

19

我正在进行一些数学计算(试图将Matlab代码转换为C++,使用VS2010),我需要能够判断在某一点上是否得到了负零。

根据IEEE标准,-0 / +0仅在符号位上不同(其余为0)。

我已经使用了以下代码片段(post),将我的双精度数解释为无符号字符。

double f = -5;
    unsigned char *c = reinterpret_cast<unsigned char *>(&f);
    for(int i=(sizeof(double)-1); i>=0; i--){
        printf("%02X", c[i]);
   }

尝试使用5/-5,我得到了预期的结果:

C014000000000000 (-5)
4014000000000000 (5)

但是,当我尝试使用0/-0时,在两种情况下我只得到了零。VS2010指出它们符合IEEE标准(msdn),所以我不确定哪部分我没有理解。

如果0/-0确实以完全相同的方式存储在内存中,那么如果我需要区分它们,我就无法区分它们,所以我应该停止浪费时间,对吗?


19
请尝试使用-0.0代替-0。 - wimh
3个回答

25

如果您编写

double d = -0; 
以下将会发生:
首先,将评估-0,因为0是int类型,所以结果为0。然后0将被转换为double类型并被赋值,从而变为+0.0,而不是-0.0。
double d = -0.0; // is your solution.

3
或者你也可以这样写:double d = -0D; 这告诉编译器将其直接读取为一个双精度浮点数 :) - Eamonn McEvoy
5
@Eamonn:我不相信它是标准的。而且-0.0无论如何都会“直接读取为double”。 - Armen Tsirunyan
我知道我是个新手!谢谢 :) - vicky5G
2
提示:即使是“-0.”(注意末尾的点)也被视为“double”。 - Matteo Italia
2
...以及-.0。下一步将是-.,但不幸的是它不是表示浮点零的有效方式。 - AnT stands with Russia

18

除了Armen的好答案之外,您应该使用signbit来检测此问题。这样做可以保护您免受字节序问题的影响:

#include <iostream>
#include <cmath>

int main()
{
    std::cout << std::signbit(0.0) << '\n';
    std::cout << std::signbit(-0.0) << '\n';
}

0
1

1

同种功能的缩写形式:

static inline unsigned bool signbit(double& d)
{
    return ( ((unsigned char*)&d)[sizeof(double)-1] & 0x80) != 0;
}


int EstimateDoubleBufferSize( double& d )
{
    int len = 0;

    if( signbit(d) ) //if ( d < 0 )
    {
        d = -d;
        len++;
    }
    d += 0.0000005;

    int m = (int) log10(d);

    if( m < 0 )
        m = 1;  // 0.xxxx - include 0
    else
        m++;    // Include first character

    len += m + 1 /*dot*/ + 6 /* precision after . */;
    return len;
}

此外,我还需要找出微软C++编译器sprintf的大小 - 也包括该函数。

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