【问题标题】:What is the difference between 0 and -0 floating point value?0和-0浮点值有什么区别?
【发布时间】:2014-08-13 20:50:26
【问题描述】:

Visual Studio 2013 中的这段代码 sn-p:

double a = 0.0;
double b = -0.0;

cout << (a == b) << " " << a << " " << b;

打印1 0 -0ab有什么区别?

【问题讨论】:

  • 区别要么是0要么是-0
  • 亲爱的投票者,我试着用谷歌搜索它,不幸的是我的查询 float -0 0 被按字面意思对待。 float "-0" 0 效果更好。以防万一其他人想投反对票。
  • @MattMcNabb 谢谢,我的意思是ab
  • "floating point negative zero" 使搜索队列更加出色。最热门的是signed zero 上的维基百科文章,可能是一本好书。事情不仅限于 C++,更不用说 Visual Studio。它是浮点值的 IEEE 标准。

标签: c++ visual-studio floating-point


【解决方案1】:

C++ 不保证区分 +0 和 -0。这是每个特定数字表示的一个特征。浮点运算的 IEEE 754 标准确实做出了这种区分,即使数字变为零,它也可用于保留符号信息。 std::numeric_limits 不会直接告诉您是否有可能的签名零。但是如果std::numeric_limits&lt;double&gt;::is_iec559 为真,那么您实际上可以假设您有 IEEE 754 表示,因此可能是负零。


a comment 中的“gmch”指出,C++11 标准库检查零符号的方法是使用std::copysign,或更直接使用std::signbit,例如如下:

#include <iostream>
#include <math.h>       // copysign, signbit

using namespace std;

auto main() -> int
{
    double const z1 = +0.0;
    double const z2 = -0.0;

    cout << boolalpha;
    cout << "z1 is " << (signbit( z1 )? "negative" : "positive") << "." << endl;
    cout << "z2 is " << (signbit( z2 )? "negative" : "positive") << "." << endl;
}

没有copysignsignbit,例如对于 C++03 编译器,检测负零 z 的一种方法是检查 1.0/z 是否为负无穷大,例如通过检查它是否只是负面的。

#include <iostream>
using namespace std;

auto main() -> int
{
    double const z1 = +0.0;
    double const z2 = -0.0;

    cout << boolalpha;
    cout << "z1 is " << (1/z1 < 0? "negative" : "positive") << "." << endl;
    cout << "z2 is " << (1/z2 < 0? "negative" : "positive") << "." << endl;
}

虽然这可能在大多数任何实现中都可以在实践中发挥作用,但它正式*未定义行为。

需要确保表达式评估不会陷入困境。


*) C++11 §5.6/4 “如果/% 的第二个操作数为零,则行为未定义”

【讨论】:

  • copysign(1.0, x) 是一种不那么残酷的方法来发现 x 是 -0 还是 0。
  • @gmch:谢谢,我忘了copysign。没用过。
【解决方案2】:

http://en.m.wikipedia.org/wiki/Signed_zero

简而言之,这是由于符号被存储为 IEEE 754 浮点表示中的独立位。这导致能够具有零指数和小数部分,但仍设置符号位 - 因此为负零。对于以二进制补码形式存储的有符号整数,这种情况不会发生。

【讨论】:

  • 有符号整数可以存储在负零的补码或符号大小中。
  • @MattMcNabb 在技术上是正确的。您可能会看到在大约 30 年前的旧大型机和小型机上使用的补充。这里有一些关于它的好历史:en.m.wikipedia.org/wiki/Signed_number_representations
猜你喜欢
  • 2016-03-23
  • 2021-06-16
  • 1970-01-01
  • 2012-09-23
  • 2021-02-13
  • 2012-08-02
  • 1970-01-01
  • 2016-02-19
相关资源
最近更新 更多