Thread: binary representation of a float

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    596

    binary representation of a float

    I was curious to see exactly how a float (and a double) is stored in memory so I wrote this little program to let me see the actual bits for the numbers 0-9 stored as floats:
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main( int argc, char* argv[] ) {
      float num; // = atof( argv[1] );
      int *ip = (int*)&num;
      int size, digit;
      string ch;
      string binstr;
      size = sizeof(num);
      cout << "sizeof int = " << sizeof(size) << endl;
      cout << "sizeof float = " << sizeof(num) << endl;
    
      for( int k = 0; k < 10; ++k ) {
        num = k;
        for( int j = 0; j < size; ++j ) {
          for( int i = 0; i < 8; ++i ) {
            digit = 1 & (*ip);
            ch = string( 1, (char)(48 + digit) );
            binstr.insert( 0, ch );
            *ip >>= 1;
          }
          binstr.insert( 0, " ");
        }
        cout << binstr << endl;
        binstr = "";
      }
    
      return 0;
    }
    I thought I understood that a 32-bit float is stored as an 8-bit exponent and 24-bit significand, so (assuming the first byte would be the exponent, 0, and the next 3 bytes would be the significand) I was expecting as output:
    Code:
    sizeof int = 4
    sizeof float = 4
     00000000 00000000 00000000 00000000
     00000000 00000001 00000000 00000000
     00000000 00000010 00000000 00000000
     00000000 00000011 00000000 00000000
     00000000 00000100 00000000 00000000
     00000000 00000101 00000000 00000000
     00000000 00000110 00000000 00000000
     00000000 00000111 00000000 00000000
     00000000 00001000 00000000 00000000
     00000000 00001001 00000000 00000000
    but instead, this is the surprising output:
    Code:
    sizeof int = 4
    sizeof float = 4
     00000000 00000000 00000000 00000000
     00111111 10000000 00000000 00000000
     01000000 00000000 00000000 00000000
     01000000 01000000 00000000 00000000
     01000000 10000000 00000000 00000000
     01000000 10100000 00000000 00000000
     01000000 11000000 00000000 00000000
     01000000 11100000 00000000 00000000
     01000001 00000000 00000000 00000000
     01000001 00010000 00000000 00000000
    Can you explain this?

    (My code may not be the most elegant way to do this, but I don't see anything actually wrong in it, do you?)

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I thought I understood that a 32-bit float is stored as an 8-bit exponent and 24-bit significand
    1 sign bit
    8 bit biased exponent
    23 bit mantissa with an implied 1
    http://en.wikipedia.org/wiki/Single_precision
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, so aside from the correction of the misunderstood format of floating point in itself, there are some other things to consider:
    1. There is an implicit 1 at the beginning of all non-zero values, so when you have 1.0 (for example), it is actually stored with all zeros in the mantissa, because the single 1 that is at the beginning is implied by the floating point format itself.
    2. The stored number is ALWAYS normalized, that is the actual bits of the mantissa is always as far left as it can be - or put another way, the exponent is always the smallest it can be.
    3. The exponent is stored as a biased number - it is 128+actual value. So 1.0 is stored as exponent of 127 and a mantissa of all zeros, for example.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Thanks. I had looked at a couple of articles in Wikipedia but didn't find that one.

    That's quite a system. I'd love to hear Bob Newhart explain it.

  5. #5
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote Originally Posted by matsp
    3. The exponent is stored as a biased number - it is 128+actual value. So 1.0 is stored as exponent of 127 and a mantissa of all zeros, for example.
    127, I think? Although, the second part is correct - 1.0 is stored as an exponent of 127 and a mantissa of all zeros: 127 - [bias of] 127 = 0, so: 1.0 * 2^0 = 1.0
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  6. #6
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Yes, the bias is 127 as explained in the Wikipedia article. All of the encodings in my output example bear that out.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-13-2009, 03:25 PM
  2. Replies: 3
    Last Post: 11-25-2006, 04:14 PM
  3. help me
    By warthog89 in forum C Programming
    Replies: 11
    Last Post: 09-30-2006, 08:17 AM
  4. Could somebody please help me with this C program
    By brett73 in forum C Programming
    Replies: 6
    Last Post: 11-25-2004, 02:19 AM
  5. ~ Array Help ~
    By Halo in forum C++ Programming
    Replies: 1
    Last Post: 11-08-2002, 04:19 PM