[英]c++ float to bool conversion
我正在查看一些第三方代碼,不確定一行到底在做什么。 我無法發布確切的代碼,但它遵循以下原則:
bool function(float x)
{
float f = doCalculation(x);
return x > 0 ? f : std::numeric_limits<float>::infinity();
}
顯然這會向編譯器發出有關轉換float-> bool的警告,但是實際行為是什么? Visual C ++如何將浮點數轉換為布爾值? 至少我應該能夠取代那討厭的無限...
我認為這是一個錯誤。 該函數應返回一個浮點數。 在我看來,這是合乎邏輯的。
從float到bool的轉換與float!= 0相同。但是,由於精度的原因,嚴格比較兩個浮點並不總是如您所願。
如果浮點數== 0.0f,則浮點數將轉換為false
,但要注意精度! 否則,將被轉換為true
-這也將是true
,如果它不是exacly 0.0F! Inifinity也將轉換為true
。 正如David Thornley所提到的,您的示例是非常糟糕的代碼。
我認為使用isnan()會更好。
如果f不是數字,則isnan()返回true。 但是它將返回true,例如0.0 ...
#include <cmath>
bool function(float x)
{
float f = doCalculation(x);
return isnan(f) ? false : true;
}
如前所述,這將無法解決f為0.0或非常接近f的情況。
如果您需要,可以通過以下方式進行檢查:
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;
}
}
檢測結果:
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
我通常會
return x != 0;
假設對於x的非正值,DoCalculation(x)返回infinity(),那么對於x的正值,對於DoCalculation()的非零值,則function(x)為true,否則為false。 因此,函數(x)將確定DoCalculation(x)是否為零。 我會將function(x)重命名為IsDoCalculationNonzero(x)。
這似乎很簡單。 請記住,布爾的唯一狀態是零或非零。 所以這段代碼:
return x > 0 ? f : std::numeric_limits<float>::infinity();
評估如下:
如果x> 0:返回f。 如果f == 0.0F,則它將返回false。 否則它將返回true。 正如其他人提到的那樣,精度問題可能會給出錯誤的true,但是如果它起作用了,那么我會說不...
如果x <= 0:返回infinity(),這是一種奇怪的情況。 但是,infinity()!= 0-因此將返回true。 (參考: http : //msdn.microsoft.com/en-us/library/85084kd6.aspx )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.