我有一个带有两个重载比较运算符 (operator==) 的 RGB 颜色类。 一种用于 self 类型,一种用于 int (HEX)。
// this one assigns the value correctly
RGB RGB::operator=(const int hex)
{
this->r = (hex>>16 & 0xFF) / 255.0f;
this->g = (hex>>8 & 0xFF) / 255.0f;
this->b = (hex & 0xFF) / 255.0f;
return *this;
}
//--------------------------------------------------------------------------------------
// also works
bool RGB::operator==(const RGB &color)
{
return (r == color.r && g == color.g && b == color.b);
}
// this is evil
bool RGB::operator==(const int hex)
{
float rr = (hex>>16 & 0xFF) / 255.0f;
float gg = (hex>>8 & 0xFF) / 255.0f;
float bb = (hex & 0xFF) / 255.0f;
// if i uncomment these lines then everything is fine
//std::cout<<r<<" "<<rr<<std::endl;
//std::cout<<g<<" "<<gg<<std::endl;
//std::cout<<b<<" "<<bb<<std::endl;
return (r == rr &&
g == gg &&
b == bb);
}
RGB::RGB(int hex)
{
setHex(hex);
}
inline void RGB::setHex(unsigned hex)
{
r = (float)(hex >> 16 & 0xFF) / 255.0f;
g = (float)(hex >> 8 & 0xFF) / 255.0f;
b = (float)(hex & 0xFF) / 255.0f;
}
...然后我在 main.cpp 中比较:
RGB a = 0x555555;
bool equals = (a == 0x555555); // returns false
我不知道会发生什么。比较返回 false,但如果我取消注释定义中的 std::cout 行,则该函数按预期工作并返回 true。
这也没有问题:
RGB a = 0x555555;
RGB b = 0x555555;
bool equals = (a == b); // returns true
有人有想法吗?
最佳答案
你不应该在没有优化的情况下获得浮点比较效果。这是因为您在这两种情况下具有相同的功能。
没有优化,以下是正确的:
float func(float);
float a = ...;
func(a) == func(a); //< always true
这就是您所拥有的,您的功能是移位并除以 255。
但是 - 对于优化,情况就不同了。 GCC 具有可以重新排列表达式的优化(参见例如 -freciprocal-math、-fassociative-math)。
在你的情况下,你有:
float rr = (X) / 255.0f;
...
r == rr
例如,它可以在优化后做一些相当于这样的事情:
255.0f * r == (X)
这现在确实受到浮点比较效应的影响。但是,通过在中间引入标准输出,您迫使它对表达式求值更接近它们的书写方式,这再次让您回到对同一函数自身求真值的理智状态。
您可以更改类的定义以将值存储为整数并仅在需要 float 时转换为 float ,或者同时存储十六进制表示和 float 并使用十六进制进行比较。或者您可以使用大于/小于而不是双等于来比较测试两个浮点值是否在彼此的 1/255 以内。例如。像这样:
return (abs(r - rr) < 1/255.0f && ...);
关于c++ - 重载比较运算符失败 [C++11],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17369984/