当前位置: 首页 > 知识库问答 >
问题:

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

司徒池暝
2023-03-14

在我的代码中,

float f = -0.0; // Negative 

与负零相比

f == -0.0f

结果将为true。

但是

float f = 0.0; // Positive

与负零相比

f == -0.0f

此外,结果将为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;
    }
}

输出:

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

true

共有3个答案

姬实
2023-03-14

这是因为有符号负零必须与零进行比较:即-0.0==0.0、-0f==0f和-0l==0l。

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

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

乔鸿骞
2023-03-14

C 11引入了像std::signbit()这样的函数,它可以检测有符号的零,以及std::copysign(),如果实现支持有符号的零(例如,由于使用IEEE浮点),它可以在浮点值之间复制符号位。这些函数的规范实际上并不要求实现支持不同的正零和负零。撇开这类事情不谈,我不知道C标准中的任何引用甚至提到了有符号的零,更不用说比较它们的结果了。

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

虽然不是确定的,但这些观察结果表明,有符号零的支持或比较结果将由实现支持的浮点表示形式决定。

IEEE-754是现代实现(即主机系统上的编译器)使用的常见(但不是唯一)浮点表示。IEEE-758“浮点算术IEEE标准”第5.11节第二段的当前版本(2008年发布)说(粗体强调)

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

程承恩
2023-03-14

C中的浮点运算通常是IEEE-754。这个范数不同于实数集的数学定义。

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

+0.0 == -0.0

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

在IEEE算法中,定义对数0=-∞ 当x时,将x记录为NaN

 类似资料:
  • 我想编写对浮点和双精度都有效的代码。我正在做这样的事情: 这让我想到,我不想在做双精度时,在常数为0.5f时失去精度,但是我不想在做单精度时,将0.5提升到双精度! 因此,我最终使用了操作符real(),如示例中所示。在单精度模式下,如果我使用real(0.5)反汇编函数“foo”,我得到的结果是,没有提升到double,而不是只使用0.5,提升发生在那里。 您可以检查使用: 我懂了 使用实数(0

  • 问题内容: 我是Java的新手,我一直在尝试实现一种用于查找三次方程式根的算法。当我计算判别式并尝试检查其相对于零的位置时,就会出现问题。 如果运行它并输入数字“ 1 -5 8 -4”,则输出如下: 我知道问题是因为双精度计算不精确。通常,判别式应为0,但最终变为0.00000000000000001236。 我的问题是,避免这种情况的最佳方法是什么?我是否应该检查数字是否介于零附近的ε之间?还是

  • 我得到了下面的错误当我运行一个应用程序JavaWeb使用 我的问题是为什么它只在部署应用程序后才发生?在开发环境中它没有发生。 2021 03月24日08:50:41.150信息19613---[uler事件循环]组织。阿帕奇。火花调度程序。DAGScheduler:ShuffleMapStage 0(FalhaService中的collectAsList。java:60)在7.513秒内失败,原

  • 我在R中有一个数据框,其中有一列表示“低”、“中”和“高”,还有一列表示年份(2019年、2020年或2021),平均值如下。我想找出与第一年(2019年)(即2020-2019年和2021-2020年)相比的水平变化。我正在使用函数:df%

  • 问题内容: 是否可以检查a 是正零(0.0)还是负零(-0.0)? 我已经将转换为,并检查第一个是否为,但是还有其他方法吗? 问题答案: 是的,除以它。是,但是是。通过简单的比较很容易找出是哪一个,因此您得到: (这假定只能是两个零之一)

  • 问题内容: IEEE754支持负零。但是这段代码 输出 我本来期望的 浮动格式基于IEEE754的其他语言可让您创建负零文字 Java的: C# : Javascript: 但是我在Go中找不到等效项。 您如何在go中编写一个负零文字? 问题答案: 有一个已注册的问题。 碰巧提供了一种解决方案: 还不错,因为它显然引用了定义的标准函数。 但这意味着您需要导入一个软件包,而对于(当然较小且很少见的)