IEEE 754 Float debug - from memory little endian to the actual floating number
I am testing IEEE 754 floating format with VS2008 using the example below:
int main(int argc, char *argv[])
{
float i = 0.15625;
}
I put &i to the VS2008 watch and I see the address is 0x0012FF60 and I can see address's content is 00 00 20 3e from Memory debug window, see below:
0x0012FF60 00 00 20 3e cc cc cc cc
BTW I have the basic knowledge of IEEE754 floating fo开发者_StackOverflow中文版rmat and I know IEEE 754 floating format consist of three fields: sign bit, exponent, and fraction. The fraction is the significand without its most significant bit.
But how did I calcuate exactly from little endian 00 00 20 3e to 0.15625 ?
Many thanks
Memory layout of a 32bit float ( see http://en.wikipedia.org/wiki/Single_precision ) on a big endian machine.
A little endian machine (eg. x86) simply swaps pairs of bytes, the 'cc' are unused bits of memory to make the 32bit float upto a 64bit value being displayed by the debugger
edit: Remember the exponent is signed (twos complement) and since 0.15625 is less than 1 the exponent is negative)
value = sign * 2^exp * mantissa.
0x3e = 0011 1110
0x20 = 0010 0000
Because of the sign bit we have to shuffle these along one so
exponent = 0111 1100 = -3
mantissa = 0100 0000 = 1 + 0.25 ( the one before the first place is assumed)
ie 0.15625 = +1 * 2^(-3) * 1.25
You are printing out something broken. We only need 32 bits, which are:
00 00 20 3E
Your variable in binary:
00000000 00000000 00100000 00111110
Logical value accounting for little endian:
00111110 00100000 00000000 00000000
According to IEEE:
0 01111100 01000000000000000000000
S E - 127 M - 1
So now it's clear:
- the sign is +1 (
S = 0
) - the exponent is 124 - 127 = -3
- the mantissaa is 1.01b, which is 5/4
So the value is 5/4 / 8 = 5/32 = 0.15625.
Your value is hex 0x3E200000 or
0011 1110 0010 0000 0000 0000 0000 0000
or rearranged:
s ----e--- ----------m------------
0 01111100 01000000000000000000000
sign_bit = 0 (i.e. positive)
exponent = 0x7C = 124 ---> subtract 127 to get -3
significand = 1 + 0.0100... = 1.0100... = 1*2^0 + 0*2^-1 + 1*2^-2 = 1.25
significand * 2^exponent = 1.25 * 2^-3 = 1.25 * 0.125 = 0.15625
The basic format of an IEEE floating point is based on a four byte value, and it is simpler to analyse if you display it as such. In that case, the top bit is the exponent, the next 8 the exponent (in excess 127), and the rest the mantissa. The simplest way to explain it is probably to show the C++ code which would access the separate fields:
double d;
// ...
uint32_t const* p = reinterpret_cast<uint32_t const*>( &d );
bool isNegative = (*p & 0x80000000) != 0;
int exp = ((*p & 0x78000000) >> 23) - 127;
int mantissa = (*p & 0x07FFFFFF) | 0x08000000 ;
The mantissa should have an implicit decimal place just above the 24 bits (But I don't know how to represent this as an integer:-)).
If all you have is a sequence of bytes, you have to assemble them, according to the byte order, and then apply the above.
Edited: the constant values have been corrected, following up on Rudy Velthuis' pointing out my error.
精彩评论