2009-12-28 6 views
1

Я смотрю на какой-то сторонний код и не уверен, что именно делает одна строка. Я не могу отправить точный код, но это по линии: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 в bools? По крайней мере, я должен был бы заменить эту неприятную бесконечность ...

+3

Это выглядит как плохой код для меня. Почему вычисление, если 'x <= 0.0'? Зачем перебирать выражение для бесконечности, а не 1.0, поскольку оба они преобразуются в 'true'? Зачем вычислять что-то из x и возвращать false, если 'x> 0.0' и' f == 0.0', а не 'abs (f)

+0

Не удается опубликовать «точный» код? Что такое «точное» имя функции (x)? – fupsduck

+1

Какая разница? Я не могу опубликовать код из-за ограничений лицензии, это достаточно похоже, чтобы быть эквивалентным. –

ответ

22

Я думаю, что это ошибка. Эта функция должна возвращать float. Это кажется мне логичным.

Преобразование float to bool такое же, как float! = 0. Однако строгое сравнение двух плавающих точек не всегда так, как вы ожидали, из-за точности.

+0

Не очень полезно. Это в рабочей сторонней библиотеке, у меня нет времени на то, чтобы отслеживать функции вызова и все это выяснить ... Я просто хочу знать, что такое правила преобразования с плавающей точкой, особенно для бесконечности. –

+0

бесконечность * будет * конвертировать в 'истина', поскольку она отличная от нуля, но это сильно пахнет опечаткой. –

+11

Как это не полезно? Он ответил на ваш вопрос: «Преобразование float в bool такое же, как float! = 0». Бесконечность равна нулю? Если нет, float преобразуется в true. – jalf

2

Поплавок будет преобразован в false, если его == 0.0f, но остерегайтесь точности! В противном случае он будет преобразован в true - он также будет true, если его не exacly 0.0f! Inifinity также будет преобразован в true. Как отметил Дэвид Торнли, ваш пример - очень плохой код.

0

Я думаю, что было бы лучше использовать isnan().

isnan() возвращает true, если f не является числом. Но это вернет истину, например. 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(); 

EDIT: здесь усовершенствованный пример, включая водителя-испытателя:

#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) истинна для non-zer o значения DoCalculation() и false в противном случае. Таким образом, функция (x) определяет, является ли DoCalculation (x) нулевой или нет. Я бы переименовал функцию (x) в IsDoCalculationNonzero (x).

0

Это кажется довольно простым. Помните, что единственные состояния, признанные для bool, равны нулю или не равны нулю. Так что этот код:

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

бы оценить следующим образом:

если х> 0: возвращение ф. Если f == 0.0F, то он вернет false. Иначе это вернет true. Как отмечали другие, точность вопросов может дать ложную истину, но если она работает, то я бы сказал, нет ...

Если x < = 0: вернуть бесконечность(), которая является ... нечетным случаем. Однако infinity()! = 0 - поэтому это вернет true.(Ссылка: http://msdn.microsoft.com/en-us/library/85084kd6.aspx)