[英]Floating point error in HSV conversion
我有一個功能,用於將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); - 這只是斷言我們總是達到其中一個上層案例,問題是如何控制到達那里?
假設這些是IEEE-754浮點數,那么與NaN
相比可能會遇到問題。 如果您使用不同的浮點表示,那么我的答案的其余部分可能不相關。
聽起來有點奇怪,但與NaN
任何比較都會返回False。 所以,即使你試圖做NaN == Nan
你也會得到假。 MSDN鏈接 。
如果您在代碼中引發斷言的部分測試NaN
,那么這可能就是問題所在。 您可以使用<cmath>
的isnan()
來執行此操作,請參閱http://en.cppreference.com/w/cpp/numeric/math/isnan 。
我快速匯總了一些代碼來演示,如果您的系統發生同樣的情況,請告訴我:
#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;
}
在我用gcc編譯的機器上,這給出了以下輸出:
r = -nan
oops
NaN encountered
所以似乎有可能在代碼中的其他地方有0.0/0
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.