Double precision comparison in C/C++

Checking double precision value for limits is tricky.

Say,

double x = 1.0;
if ( x == 1.0 ) do_something();

 

This comparison can fail as double precision value when converted to hexadecimal (what computer can do only) representation, looses some least significant bits or positions beyond double precision digits. So, in above example if ( x == 0.9999999 ) might have worked depending on compiler and/or CPU. Therefore, in programming, we create functions to check such limits to approximate values.

 

// Used for double type comparasion
typedef union mydouble_ {
    double dbl_val;
    unsigned long un_u32_val[2];
    unsigned char un_u8_val[8];
} mydouble;

 

// Checks double value against close enough limits i.e. min <= val <= max
// Return: -1 => val < min
// Return: 0 => min <= val <= max
// Return: 1 => val > max
int my_double_limit_check( double val, double min, double max )
{
    mydouble dbl;
    mydouble cmp;
    int ret = 0;
 
    if ( val < min )
    {
        dbl.dbl_val = val;
        cmp.dbl_val = min;
        if ( dbl.un_u32_val[0] != cmp.un_u32_val[0] )
            ret = -1;
        else if ( dbl.un_u8_val[4] != cmp.un_u8_val[4] )
            ret = -1;
    }
 
    if ( val > max )
    {
        dbl.dbl_val = val;
        cmp.dbl_val = max;
        if ( dbl.un_u32_val[0] != cmp.un_u32_val[0] )
            ret = 1;
        else if ( dbl.un_u8_val[4] != cmp.un_u8_val[4] )
            ret = 1;
    }
 
    return ret;
}
 
// Checks double value against close enough less value i.e. val < min
// Return: -1 => val < min
// Return: 0 => val >= min
int my_double_less_check( double val, double min )
{
    mydouble dbl;
    mydouble cmp;
    int ret = 0;
 
    if ( val < min )
    {
        dbl.dbl_val = val;
        cmp.dbl_val = min;
        if ( dbl.un_u32_val[0] != cmp.un_u32_val[0] )
            ret = -1;
        else if ( dbl.un_u8_val[4] != cmp.un_u8_val[4] )
            ret = -1;
    }
 
    return ret;
}
 
// Checks double value against close enough greater value i.e. val > max
// Return: 1 => val > max
// Return: 0 => val <= max
int my_double_greater_check( double val, double max )
{
    myouble dbl;
    myouble cmp;
    int ret = 0;
 
    if ( val > max )
    {
        dbl.dbl_val = val;
        cmp.dbl_val = max;
        if ( dbl.un_u32_val[0] != cmp.un_u32_val[0] )
            ret = 1;
        else if ( dbl.un_u8_val[4] != cmp.un_u8_val[4] )
            ret = 1;
    }
 
    return ret;
}
 
// Checks double value against close enough equal value i.e. val == eql
// Return: 0 => val == eql
// Retrun: 1 => val != eql
int my_double_equal_check( double val, double eql )
{
    mydouble dbl;
    mydouble cmp;
    int ret = 0;
 
    if ( val != eql )
    {
        dbl.dbl_val = val;
        cmp.dbl_val = eql;
        if ( dbl.un_u32_val[0] != cmp.un_u32_val[0] )
            ret = 1;
        else if ( dbl.un_u8_val[4] != cmp.un_u8_val[4] )
            ret = 1;
    }
 
    return ret;
}
 

One thought on “Double precision comparison in C/C++

Leave a Reply

Your email address will not be published. Required fields are marked *