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

问题描述 投票:9回答:4

在我的代码中,

float f = -0.0; // Negative 

并与负零相比

f == -0.0f

结果将是true

float f = 0.0; // Positive

并与负零相比

f == -0.0f

另外,结果将是true而不是false

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


这是a MCVE to test it (live on 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;
    }
}

输出:

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

true
c++ floating-point ieee-754
4个回答
12
投票

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

这个规范defines two different representations for the value zero: positive zero and negative zero。还定义了这两个表示必须比较等于,因此根据定义:

+0.0 == -0.0

至于为什么会这样,在其论文What Every Computer Scientist Should Know About Floating Point Arithmetic,David Goldberg,1991-03(链接在IEEE网站上的IEEE-754页面)中写道:

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


10
投票

那是因为有符号的负零必须将true与零进行比较:即-0.0 == 0.0-0f == 0f-0l == 0l

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

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


5
投票

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

C ++标准也没有规定任何浮点表示 - 即实现定义。

虽然不是确定的,但这些观察结果表明,对签名零的支持或比较它们的结果将由实现(也称为编译器)支持的浮点表示确定。

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

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


-3
投票

因为0.0f和-0.0f相同,零的负数为零

© www.soinside.com 2019 - 2024. All rights reserved.