150314_ceo_inno

Double precision rounding

Uses my_double_greater_check from http://rutmandal.info/eng/2014/06/double-precision-comparison-in-cc/

double my_double_round( double val, int multiplier )
{
         double val_adj = val * multiplier;
         if ( my_double_greater_check( val_adj – floor( val_adj ), 0.0 ) > 0 )
                      val = round( val_adj ) / multiplier;
         return val;
}

round and floor are C math library <math.h> functions.

E.g.

double rnd_val = my_double_round( 0.000998, 1000);

rnd_val will be 0.001

 

150314_ceo_inno

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;
}
 

150314_ceo_inno

Attributes of Objects

Attributes of Objects – Chirag Patel January 01, 2009

type
– Determines size of object and its memory address alignment
– the values the object can have
– the operations that can be performed on the object
– a function type specifies function parameter lists and return type

scope
– portion of translation unit (source code produced by preprocessor from source and header files) in which the name is visible
– file scope, block scope, function prototype scope, function scope
– C++ has namespace scope and class scope in addition

storage duration
– lifetime of the storage of object
– static, automatic or dynamic
– enumeration constants, functions, labels, types – do not have storage duration

linkage
– no linkage => entity can’t be referenced via name from anywhere else
– internal linkage => entity that can be referenced via name declared in the same scope or in other scopes of the same translation unit
– external linkage => in addition to capabilities similar to internal linkage, this can be referenced in other translation units

keywords: auto, extern, register, static – defines storage duration and/or linkage

150314_ceo_inno

C++ coding tips

Some C++ coding tips:

– Do not turn off warning level(s) from compilation. This will save you trouble later. Use as much stricter settings as possible.

– Do not ignore warning(s) in your build process.

– Stick to ANSI C++ coding as much as possible.
All header file code must be contained within:

#ifndef __file_h
#define __file_h 1

… (code)

#endif
Use “#pragma once” as first line of header file if using Visual C++ compiler 2003 and later.

 – Do not use “goto” if possible.

– Always perform clean build before code submission and/or merge.

– Use “const” modifier as much as possible.

– Define “enum” with assigned values. Do not let it go for assumption. This improves readability. Say,

enum MyEnum {

SUNDAY = 0,

MONDAY = 1,

}; // enum for days

– Use brackets in pre-processor director. Say,

#define BIT(n)  (1 << n) // not preferred

#define BIT(n) (1 << (n)) // preferred

– Prefer library functions that take size or count argument over to functions without such argument for string manipulation. Say,

strncpy is preferred over strcpy.

– One include file should not contain more than one class definitions.

– Using “const” or “enum” is preferred over using “define” for contants. Say,

#define LOOP_COUNT  100 // non preferred

const int LOOP_COUNT = 100; // preferred

enum { LOOP_COUNT = 100, }; // or preferred

– A member function that does not modify class state must be declared as “const”.

– A class must have a default constructor with all data members initialized in it.

– A class must have copy constructor and assignment operator defined to avoid surprises.

– Assignment operator function must take care of destructive operation e.g. assigning to self (a = a).

– Avoid functions having more than five arguments.

– Do not mix malloc/free and new/delete.

– If array is allocated using “new”, use “delete []” for deallocating it.

– Avoid type conversions if possible.

– Re-initialize pointer when deallocated. Say,

delete p;

p = NULL;

– It is good to have a carriage return in the end of a code file.

– Use inclusive lower limit and exclusive upper limit in “for” loop. Say,

for ( int idx = 0; idx < MAX; ++idx ) // exclusive upper limit

for ( int idx = MAX; idx >= 1; –idx ) // inclusive lower limit

– Do not use “static” variable in “inline” function in header file.

I hope that this article is helpful and will avoid some silly bugs creeping over your code 🙂