Sunday, November 29, 2015

C/C++ - Getting fraction and exponent from double number using unions

Double is stored as 64-bit number, with following internal structure in computer registers:


This storage can be binary presented in C++ using unions, since their members share the same address space. That way we can have presentation of both exponent and fraction in one object:


typedef union 
{
 double db;
 unsigned short sh[4];
} Double;

Double D;
D.db = d; // some double
In this presentation, members of union have following meaning:

D.sh[0] - fraction (bits 15-0)
D.sh[1] - fraction (bits 31-16)
D.sh[2] - fraction (bits 47-32)
D.sh[3] - bit 15 is for sign 0 +, 1 -), bits 14-4 are for exponent, and bits 3-0 are part of fraction (bits 51-48)

From D.sh it is possible to extract sign, fraction (mantissa) and exponent:


short exp = ((D.sh[3] & 0x7FF0) >> 4) - 1023;
short sign = (D.sh[3] & 0x8000) >> 15;

double mant = 1.;

for (short i=0; i<16; i++)
{
 short bit = (D.sh[0] >> i) & 1; 
 mant += bit * pow (2., i-52);
}

for (short i=16; i<32; i++)
{
 short bit = (D.sh[1] >> (i-16)) & 1; 
 mant += bit * pow (2., i-52);
}

for (short i=32; i<48; i++)
{
 short bit = (D.sh[2] >> (i-32)) & 1; 
 mant += bit * pow (2., i-52);
}

for (short i=48; i<52; i++)
{
 short bit = (D.sh[3] >> (i-48)) & 1; 
 mant += bit * pow (2., i-52);
}

double dNew = pow(-1., sign) * mant * pow (2., exp); // should be the same as initial double d

No comments: