简体   繁体   中英

c++ float to bool conversion

I'm looking at some 3rd party code and am unsure exactly what one line is doing. I can't post the exact code but it's along the lines of:

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

This obviously throws a warning from the compiler about converting float->bool, but what will the actual behaviour be? How does Visual C++ convert floats to bools? At the very least I should be able to replace that nasty infinity...

I think it is a mistake. That function should return a float. This seem logical to me.

The conversion float to bool is the same as float != 0. However, strict comparing two floating points is not always as you'd expect, due to precision.

A float will be converted to false if its == 0.0f, but beware of the precision! Otherwise it will be converted to true -- it will be also true if its not exacly 0.0f! Inifinity will also be converted to true . As David Thornley mentioned, your example is very bad code.

I think it would be better to use isnan() .

isnan() returns true if f is not-a-number. But it will return true for eg 0.0 ...

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

as mentioned that will not catch the case where f is 0.0 - or very close to it.

If you need this you could check with:

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

EDIT: here an improved example including a test driver:

#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

我通常会

return x != 0;

Assuming DoCalculation(x) returns infinity() for non positive values of x then for positive values of x function(x) is true for non-zero values of DoCalculation() and false otherwise. So function(x) is to determine if DoCalculation(x) is zero or not. I would rename function(x) to IsDoCalculationNonzero(x).

This seems pretty straightforward. Remember that the only states recognized for bool is zero or non-zero. So this code:

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

Would evaluate as follows:

if x > 0 : return f. If f == 0.0F then it will return false. Otherwise it will return true. As others have mentioned, precision issues may give a false true, but if it's working then I 'd say not...

If x <= 0 : return infinity() which is ... an odd case. However, infinity() != 0 -- therefor this will return true. (Reference: http://msdn.microsoft.com/en-us/library/85084kd6.aspx )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM