开发者

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.

IEEE 754 Float debug - from memory little endian to the actual floating number

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜