负零 (-0.0) 与正零 (+0.0) 相比的行为
Behaviour of negative zero (-0.0) in comparison with positive zero (+0.0)
在我的代码中,
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 相同,零为零
- 当回溯以零开始时,如何调试崩溃
- 在没有太多条件句的情况下,我如何避免被零除
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- 矩阵向量乘法(cublasDgemv)返回零
- 是否可以对零模板参数进行模板专门化
- 处理除以零会导致<csignal>意外行为
- 在C++中向零方向近似的最佳方法
- 在 C++ 中访问数组负索引处的内存不会返回垃圾
- 打包可变参数模板具有零元素时的递归
- 负零整数
- 实现基于数字值(正、负、零)的条件表达式的最佳方法
- 负零 (-0.0) 与正零 (+0.0) 相比的行为
- 左移负整数为零是否有意义?
- 是否可以在编译时测试类型是否支持负零C++
- 避免输出为负零的最佳方法是什么
- 程序必须决定正、负或零
- 我的 glOrtho 有什么问题?负零而不是零
- 用std::cout正确填充带零的负整数
- std::cout如何在一补系统中打印负零?
- 用于负零浮点值