Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can std::numeric_limits::quiet_NaN double/float store some extra info

Tags:

c++

c++11

nan

When storing double data in my data acquisition project, I identify all "missing" data using std::numeric_limits::quiet_NaN(). However, I'd like to store some extra information to know why the data is "missing" (data transmission lost, bad checksum, no measurement done, internal error....) so I need many different "nan" values in the end. And they must all be identified as NaN by any legacy code (x!=x).

I see in IEEE 754-1985 that NaN fraction could be "anything except all 0 bits (since all 0 bits represents infinity).". Can the fraction be used to safely store some extra info? If yes, how should I do this? Would this be totally safe on all platform and with any compiler?

Here is what I was thinking about:

double GetMyNaN1()
{
    double value = std::numeric_limits<double>::quiet_NaN();
    // customize it!
    return value;
}

double GetMyNaN2()
{
    double value = std::numeric_limits<double>::quiet_NaN();
    // customize it!
    return value;
}

bool IsMyNan1( double value )
{
    // return true if value was created by GetMyNaN1() 
}

bool IsMyNan2( double value )
{
    // return true if value was created by GetMyNaN2() 
}

int main()
{
    double regular_nan = std::numeric_limits<double>::quiet_NaN();
    double my_nan_1 = GetMyNaN1();
    double my_nan_2 = GetMyNaN2();

    assert( std::isnan( regular_nan ) && !IsMyNan1( regular_nan ) && !IsMyNan2( regular_nan ) );
    assert( std::isnan( my_nan_1 ) && IsMyNan1( my_nan_1 ) && !IsMyNan2( my_nan_1 ) );
    assert( std::isnan( my_nan_2 ) && !IsMyNan1( my_nan_2 ) && IsMyNan2( my_nan_2 ) );
    return 0;
}

The code must work on all platform.

like image 246
jpo38 Avatar asked Sep 24 '26 02:09

jpo38


1 Answers

This is known as NaN-boxing. It’s very widely used, but there’s no language-defined way of doing it since (as usual) the bit layout isn’t specified. On real implementations, with care you can get the right behavior via the obvious bit operations even though formally it’s undefined (if you use type punning via reinterpret_cast or a union) or at best unspecified (if you use memcpy or bit_cast).

like image 175
Davis Herring Avatar answered Sep 26 '26 16:09

Davis Herring