负零(-0.0)与正零(+0.0)相比的行为

Jay*_*esh 11 c++ floating-point ieee-754

在我的代码中,

float f = -0.0; // Negative 
Run Code Online (Sandbox Code Playgroud)

并与负零相比

f == -0.0f
Run Code Online (Sandbox Code Playgroud)

结果将是true.

float f = 0.0; // Positive
Run Code Online (Sandbox Code Playgroud)

并与负零相比

f == -0.0f
Run Code Online (Sandbox Code Playgroud)

另外,结果将是true代替false

为什么在这两种情况下都是真的?


这是一个测试它的MCVE(住在coliru上):

#include <iostream>

int main()
{
    float f = -0.0;

    std::cout<<"==== > " << f <<std::endl<<std::endl;

    if(f == -0.0f)
    {
        std::cout<<"true"<<std::endl;
    }
    else
    {
        std::cout<<"false"<<std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

==== > -0  // Here print negative zero

true
Run Code Online (Sandbox Code Playgroud)

YSC*_*YSC 12

C++中的浮点运算通常是IEEE-754.该范数与实数集的数学定义不同.

该范数为零值定义了两种不同的表示:正零和负零.还定义了这两个表示必须比较等于,因此根据定义:

+0.0 == -0.0
Run Code Online (Sandbox Code Playgroud)

至于为什么会这样,在其论文"每个计算机科学家应该知道什么关于浮点运算"中,David Goldberg,1991-03(链接在IEEE网站上的IEEE-754页面)写道:

在IEEE算术中,当x <0时,将log 0 =-∞和log x定义为NaN是很自然的.假设x表示已经下溢到零的小负数.由于有符号零,x将为负数,因此log可以返回NaN.但是,如果没有符号零,则日志函数无法将下溢的负数与0区分开,因此必须返回-∞.

  • `log` 参数有点可疑。IEEE 754-2008 建议 `log(+0.0)` 和 `log(-0.0)` 都应该返回负无穷大。(参见第 9.2.1 节“特殊值”。) (2认同)

Bat*_*eba 10

这是因为签署负零必须比较true具有零:即-0.0 == 0.0,-0f == 0f-0l == 0l.

这是C++编译器支持的任何浮点方案的要求.

(请注意,目前大多数平台都使用IEEE754浮点,并且该规范明确记录了此行为.)


Pet*_*ter 7

如果实现支持带符号的零(例如,由于使用IEEE浮点),则C ++ 11引入了诸如std::signbit()可以检测带符号的零以及std::copysign()可以在浮点值之间复制符号位的函数。除了那种事情,我不知道C ++标准中的任何引用,甚至提到带符号的零,更不用说比较它们的结果了。

C ++标准也没有规定任何浮点表示形式-这是实现定义的。

尽管不是确定的,但这些观察结果表明,对有符号零的支持或对其进行比较的结果将由实现(即编译器)支持的浮点表示形式确定。

IEEE-754是现代实现(即编译器)使用的最常见(尽管不是唯一)浮点表示形式。当前版本(2008年发布)的IEEE-758“浮动点算法IEEE标准”第5.11节第二段说(粗体强调我的)

四种互斥关系是可能的:小于相等大于无序。当至少一个操作数为NaN时,出现最后一种情况。每个NaN都应将无序与所有事物(包括自身)进行比较。 比较应忽略零的符号(所以+0 =?0)。 具有相同符号的无限操作数应比较相等