我有一个将RGB色彩空间中的矢量转换为HSV的功能 - 例程通过了所有测试并且在绝大多数时间都可以工作。但是,崩溃报告表明它偶尔会失败(0.0001%的呼叫或更少。)但是,由于此功能被调用太多,这占软件总崩溃的很大一部分。
代码的相关部分如下:
glm::vec4 RGBtoHSV(glm::vec4 rgb)
{
vec4 hsv = vec4(0,0,0,rgb.w);
float r = rgb.x;
float g = rgb.y;
float b = rgb.z;
float M = std::max(std::max(r,g),b);
float m = std::min(std::min(r,g),b);
float c = M - m;
//calc hue
float hp = 0;
if (c == 0)
hp = 0;
else if (M == r)
hp = glm::mod(((g-b)/c), 6.0f);
else if (M == g)
hp = ((b-r)/c) + 2;
else if (M == b)
hp = ((r-g)/c) + 4;
else
EXPECT(false);
float h = hp * 60;
...
glm :: vec4是对GLM库的引用,但类型基本上就是这样:
struct vec4 {
union {
struct { float x, y, z, w; }
struct { float r, g, b, a; }
}
}
失败的行是EXPECT(false); - 这只是断言我们总是达到其中一个上层案例,问题是如何控制到达那里?
答案 0 :(得分:2)
假设这些是IEEE-754浮点数,那么与NaN
相比可能会遇到问题。如果您使用不同的浮点表示,那么我的答案的其余部分可能不相关。
听起来有点奇怪但与NaN
的任何比较都会返回False。所以即使你试图做NaN == Nan
,你也会变得虚假。 MSDN link
如果在代码中引发断言的部分中测试NaN
,则可能是问题所在。您可以使用isnan()
中的<cmath>
#include <iostream>
#include <cmath>
int main(){
float r = 0.0/0;
std::cout << "r = " << r << std::endl;
float g = 7.0;
float b = 0.0;
float M = std::max(std::max(r,g),b);
float m = std::min(std::min(r,g),b);
float c = M - m;
//calc hue
float hp = 0;
if (c == 0)
std::cout << "c == 0" << std::endl;
else if (M == r)
std::cout << "M == r" << std::endl;
else if (M == g)
std::cout << "M == g" << std::endl;
else if (M == b)
std::cout << "M == b" << std::endl;
else
std::cout << "oops" << std::endl;
if(std::isnan(M))
std::cout << "NaN encountered" << std::endl;
}
来查看http://en.cppreference.com/w/cpp/numeric/math/isnan。
我快速汇总了一些代码以进行演示,如果您的系统发生同样的情况,请告诉我们:
r = -nan
oops
NaN encountered
在我用gcc编译的机器上,这给出了以下输出:
0.0/0
所以似乎有可能代码中的其他地方有{{1}}。