Manipulating individual bits in a double precision number

This is a discussion on Manipulating individual bits in a double precision number within the C++ Programming forums, part of the General Programming Boards category; I'm trying to display double precision numbers in binary form so that I can manipulate them on the bit level. ...

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    197

    Unhappy Manipulating individual bits in a double precision number

    I'm trying to display double precision numbers in binary form so that I can manipulate them on the bit level. I'm pretty sure I've figured out how to display them in binary form, only I'm getting weird results that I can't make sense of.

    I have the following code:
    Code:
    #include <bitset>
    #include <iostream>
    #include <string>
    #include <limits>
    using namespace std;
    
    
    int main(){
    
        cout << "1:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(1)
             << endl;
    
        cout << "-1:      \n"
             << bitset<numeric_limits<unsigned long>::digits>((-1))
             << endl;
             
        cout << "5:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(5)
             << endl;        
             
        cout << "-5:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(-5)
             << endl;
                               
        cout << "4503599627370496:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(4503599627370496)
             << endl;
    
        cout << "-4503599627370496:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(-4503599627370496)
             << endl;   
             
        cout << "4503599627370496e1:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(4503599627370496e1)
             << endl;
             
        cout << "4503599627370496e-1:      \n"
             << bitset<numeric_limits<unsigned long>::digits>(4503599627370496e-1)
             << endl;         
                      
    return 0;                  
    }
    which results in:
    Code:
    1:      
    0000000000000000000000000000000000000000000000000000000000000001
    -1:      
    1111111111111111111111111111111111111111111111111111111111111111
    5:      
    0000000000000000000000000000000000000000000000000000000000000101
    -5:      
    1111111111111111111111111111111111111111111111111111111111111011
    4503599627370496:      
    0000000000010000000000000000000000000000000000000000000000000000
    -4503599627370496:      
    1111111111110000000000000000000000000000000000000000000000000000
    4503599627370496e1:      
    0000000010100000000000000000000000000000000000000000000000000000
    4503599627370496e-1:      
    0000000000000001100110011001100110011001100110011001100110011001
    My understanding is that a double precision number is suppose to have the following layout:

    1 sign bit, 11 exponent bits, 52 fraction bits

    If this is true, then there must be something wrong with my code because "1" and "-1" should only have one bit that is different. What is wrong with my code?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    You're printing ints and not floats, since that's what "unsigned long" is is ints. You may want to make a real float and then copy/cast/whatever to the bitset.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,295
    1 is an int
    1U is an unsigned int
    1.f, 1.0f, 1e0f are examples of floats
    1., 1.d, 1.0, 1.0d, and 1e0 are examples of doubles
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    18
    you are printing "unsigned long"
    for double use "double"
    well if you consider "1" in 8 bit system it looks like 0 0000001
    first 0 indicates it is positive number 7 bits are for magnitude
    for "-1" bit pattern is 1 1111110
    first "1" indicates it is negative number and magnitude is 1's compliment of "+1" i.e. all lower 7 bits are inverted.
    that is how negative number is represented in binary.

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,794
    Well, for single precision floats you've got:
    Code:
    #include <bitset>
    #include <iostream>
    #include <limits>
    using namespace std;
    
    int main(){
        float f1 = 1.0f;
        float f2 = -1.0f;
    
        cout << "1:      \n"
            << bitset<32>(*(reinterpret_cast<unsigned long*>(&f1)))
            << endl;
    
        cout << "-1:      \n"
            << bitset<32>(*(reinterpret_cast<unsigned long*>(&f2)))
            << endl;
    
        return 0;                  
    }
    My output:
    Code:
    1:
    00111111100000000000000000000000
    -1:
    10111111100000000000000000000000

    On my system unsigned long is 4 bytes (32 bits) which is what you initialize a bitset with and fits nicely with the size of a single precision float. You can't do the above quite so easily with a double since it's 64 bits (you can only initialize the bitset with up to 32 of those 64 bits) so you need a bit more trickery to break up the 64 bit double value into something that can be used to initialize the bitset with:
    Code:
    double d1 = 1.0;
    double d2 = -1.0;
    
    cout << "1:\n"
        << bitset<32>(*(reinterpret_cast<unsigned long*>(&d1)+1))
        << bitset<32>(*reinterpret_cast<unsigned long*>(&d1)) << endl;
    
    cout << "-1:\n"
        << bitset<32>(*(reinterpret_cast<unsigned long*>(&d2)+1))
        << bitset<32>(*reinterpret_cast<unsigned long*>(&d2)) << endl;
    My output:
    Code:
    1:
    0011111111110000000000000000000000000000000000000000000000000000
    -1:
    1011111111110000000000000000000000000000000000000000000000000000
    In both the above instances (single and double precision floats/doubles), the values for 1 and -1 are off by a single bit like you would expect.
    Last edited by hk_mp5kpdw; 05-27-2010 at 07:24 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Travel Expenses-Weird Result
    By taj777 in forum C++ Programming
    Replies: 4
    Last Post: 04-06-2010, 02:23 PM
  2. SDLKey to ASCII without unicode support?
    By zacs7 in forum Game Programming
    Replies: 6
    Last Post: 10-07-2007, 03:03 AM
  3. functions and passing data
    By redmondtab in forum C Programming
    Replies: 41
    Last Post: 09-21-2006, 12:04 PM
  4. Logical errors with seach function
    By Taka in forum C Programming
    Replies: 4
    Last Post: 09-18-2006, 05:20 AM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21