tags:

views:

371

answers:

6

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...

+18  A: 

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.

Cătălin Pitiș
Not really helpful. This is in a working 3rd party library, I don't have time to trace into calling functions and figure it all out... I just want to know what the float conversion rules are, especially for infinity.
John
infinity *would* convert to `true`, as it's non-zero, but this smells strongly of a typo.
Shmoopty
How is it not helpful? He answered your question: "The conversion float to bool is the same as float != 0". Is infinity equal to zero? If not, the float will convert to true.
jalf
I'd say you don't have time NOT to hunt down a few callers and see what's going on there. This is CLEARLY a mistake (although clearly it's one that isn't causing any trouble right now). If you need to understand, you need to figure out what the callers think is going on, to understand what was meant.
Michael Kohne
A: 

i generally do

return x != 0;
ufukgun
+1  A: 

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.

Wolfgang Plaschg
A: 

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

isnan() returns true if f is not-a-number. But it will return true for e.g. 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

A: 

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).

fupsduck
A: 

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)

Marc Paradise