2009-12-28 78 views
1

我正在查看一些第三方代碼,並且不確定某一行正在做什麼。我不能發佈確切的代碼,但它的線沿線的是:C++ float to bool轉換

bool function(float x) 
{ 
float f = doCalculation(x); 
return x > 0 ? f : std::numeric_limits<float>::infinity(); 
} 

這顯然從編譯器會引發一個警告有關轉換浮子>布爾,但實際行爲是什麼呢? Visual C++如何將float轉換爲bools?至少我應該能夠取代那個令人討厭的無限...

+3

這看起來像壞代碼給我。爲什麼計算'x <= 0.0'?爲什麼要寫出表達式爲無窮大而不是1.0的麻煩,因爲它們都轉換爲「真」?爲什麼要計算x中的某些內容,並且如果'x> 0.0'和'f == 0.0'而不是'abs(f)<ε「,則返回false,因爲浮點相等(將'float'轉換爲'bool' )是不確定的?我認爲你在那裏有一些不好的代碼。 –

+0

無法發佈「確切」的代碼?函數(x)的「確切」名稱是什麼? – fupsduck

+1

它有什麼不同?由於許可證限制,我無法發佈代碼,這相當類似。 –

回答

22

我認爲這是一個錯誤。該函數應該返回一個浮點數。這對我來說似乎合乎邏輯。

將浮點數轉換爲bool與float!= 0相同。但是,由於精度的原因,嚴格比較兩個浮點並不總是如您所期望的那樣。

+0

不是很有幫助。這是在第三方庫中,我沒有時間追蹤調用函數並將其全部清除......我只想知道浮點轉換規則是什麼,特別是對於無窮大。 –

+0

infinity *將*轉換爲「true」,因爲它不爲零,但是這種錯誤強烈地感染了。 –

+11

它怎麼沒有幫助?他回答了你的問題:「浮動到bool的轉換與float!= 0相同」。無窮大等於零嗎?如果不是,浮動將轉換爲true。 – jalf

0

我一般做

return x != 0; 
2

如果== 0.0F浮子將被轉換爲false,但精度要小心!否則它將被轉換爲true - 它也將是true如果它不是exacly 0.0f! Inifinity也將被轉換爲true。正如David Thornley所說,你的例子是非常糟糕的代碼。

0

我認爲最好是使用isnan()

如果f不是數字,則isnan()返回true。但它會在例如0.0 ...

#include <cmath> 
bool function(float x) 
{ 
    float f = doCalculation(x); 
    return isnan(f) ? false : true; 
} 

如上所述,將不會捕捉到f爲0.0或與其非常接近的情況。

如果你需要這個,你可以檢查有:

bool near0 = std::abs(f) > std::numeric_limits<float>::epsilon(); 

編輯:這裏的改進例子包括試車手:

#include <cmath> 

#include <limits> 
#include <iostream> 
#include <vector> 

// using namespace std; 
bool fn(float f) { 
    if (isnan(f)) return false; // it is not-a-number 
    return std::abs(f) > std::numeric_limits<float>::epsilon(); 
} 

// testdriver 
int main(void) { 
    std::vector<float> t; 
    t.push_back(0.0); 
    t.push_back(0.1); 
    t.push_back(-0.1); 
    t.push_back(0.0 + std::numeric_limits<float>::epsilon()); 
    t.push_back(0.0 - std::numeric_limits<float>::epsilon()); 
    t.push_back(0.0 - 2*std::numeric_limits<float>::epsilon()); 
    t.push_back(0.0 + 2*std::numeric_limits<float>::epsilon()); 
    t.push_back(1.0 * std::numeric_limits<float>::epsilon());  
    t.push_back(-0.1 * std::numeric_limits<float>::epsilon()); 
    t.push_back(0.1 * std::numeric_limits<float>::epsilon()); 
    for (unsigned int i=0; i<t.size(); i++) { 
     std::cout << "fn(" << t[i] << ") returned " << fn(t[i]) << std::endl; 
    } 
} 

testresults:

 
fn(0) returned 0 
fn(0.1) returned 1 
fn(-0.1) returned 1 
fn(1.19209e-07) returned 0 
fn(-1.19209e-07) returned 0 
fn(-2.38419e-07) returned 1 
fn(2.38419e-07) returned 1 
fn(1.19209e-07) returned 0 
fn(-1.19209e-08) returned 0 
fn(1.19209e-08) returned 0 

0

假設DoCalculation( x)對x的非正值返回無窮大(),然後對於x函數(x)的正值對非零值o DoCalculation()的值,否則爲false。所以函數(x)是確定DoCalculation(x)是否爲零。我將函數(x)重命名爲IsDoCalculationNonzero(x)。

0

這看起來很簡單。請記住,唯一承認bool的狀態是零或非零。所以這個代碼:

return x > 0 ? f : std::numeric_limits<float>::infinity(); 

將評估如下:

如果x> 0:返回F。如果f == 0.0F,那麼它將返回false。 否則它將返回true。正如其他人所說,精度問題可能會給出一個錯誤的真實,但如果它正在工作,那麼我會說...

如果x < = 0:返回無窮大(),這是一個奇怪的情況。然而,infinity()!= 0 - 因此這將返回true。(參考:http://msdn.microsoft.com/en-us/library/85084kd6.aspx