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

Behaviour of negative zero (-0.0) in comparison with positive zero (+0.0)

本文关键字:负零      更新时间:2023-10-16

在我的代码中,

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

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

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

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

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

四种互斥关系是可能的:小于等于大于无序。当至少一个操作数是 NaN 时,会出现最后一种情况。每个 NaN都应该与一切事物进行比较,包括它自己。比较应忽略零符号(因此 +0 = −0(。同一符号的无限操作数应相等

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

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

+0.0 == -0.0

至于为什么会这样,David Goldberg,1991-03(链接在IEEE网站的IEEE-754页面(中写道:

在IEEE算术中,当x<0时,很自然地将log 0 = -∞和log x定义为NaN。假设 x 表示一个已溢出到零的小负数。多亏了有符号的零,x 将为负数,因此 log 可以返回 NaN。但是,如果没有有符号零,log 函数无法区分下溢负数和 0,因此必须返回 -∞。

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

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

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

因为 0.0f 和 -0.0f 相同,因为 0.0f和 -0.0f 相同,零为零