Double is stored as 64-bit number, with following internal structure in computer registers:
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:
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:
Post a Comment