Visual Studio 2013中的此代码段:
double a = 0.0;
double b = -0.0;
cout << (a == b) << " " << a << " " << b;
打印1 0 -0
。 a
和b
之间有什么区别?
答案 0 :(得分:4)
C ++不保证区分+0和-0。这是每个特定数字表示的特征。用于浮点运算的IEEE 754标准确实做出了这种区分,即使数字变为零,也可用于保持符号信息。 std::numeric_limits
并不会直接告诉您是否有可能签名的零。但如果std::numeric_limits<double>::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;
}
没有copysign
或signbit
,例如对于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“如果/
或%
的第二个操作数为零,则行为未定义”
答案 1 :(得分:2)
请参阅http://en.m.wikipedia.org/wiki/Signed_zero
简而言之,这是由于符号被存储为IEEE 754浮点表示中的独立位。这导致能够具有零指数和小数部分,但仍然设置符号位 - 因此为负零。对于存储在二进制补码中的有符号整数,这是不会发生的情况。