6

Possible Duplicate:
Float to binary in C++

I want to print out the binary representation of a float number in C++. Not very practical, just out of curiosity.

The following program doesn't compile though. The reinterpret_cast fails. What kind of cast can I use so that I can do the " &(1 << i) " part?

#include <iostream>
using namespace std;


void toBinary(float num) {
  int numi = reinterpret_cast<int>(num);
  cout << num << " " << numi << endl;
  for (int i = 0; i < 8 * sizeof(num); i++){
    if (numi & (1<<i)) {
      cout << 1;
    } else {
      cout << 0;
    }
  }
  cout << endl << endl;
}

int main() {
  float a;
  cout << sizeof(int) << " " << sizeof(float) << endl;
  a = 13.5;
  toBinary(a);
  toBinary(13.9);
  toBinary(2 * a);
  toBinary(-a);
}
Community
  • 1
  • 1
Petko M
  • 653
  • 2
  • 5
  • 18

2 Answers2

19

There's a much easier way. Take a pointer to the float, and reinterpret_cast it to a pointer to char. Now loop through sizeof(float) and convert each char to 8 binary digits. This method works for doubles too.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
3

Use a union. I did this code to do exactly what you want:

// file floattobinary.cc
#include <string>
#include <inttypes.h> // for uint32_t
using namespace std;

void floatToBinary(float f, string& str)
{
    union { float f; uint32_t i; } u;
    u.f = f;
    str.clear();

    for (int i = 0; i < 32; i++)
    {
        if (u.i % 2)  str.push_back('1');
        else str.push_back('0');
        u.i >>= 1;
    }

    // Reverse the string since now it's backwards
    string temp(str.rbegin(), str.rend());
    str = temp;
}

Below is a test program to run this function:

// file test.cc
#include <iostream>
#include <string>
#include <cstdlib> // for atof(3)

using namespace std;

void floatToBinary(float, string&);

int main(int argc, const char* argv[])
{
    string str;
    float f;
    if (argc > 1)
    {
        f = static_cast<float>(atof(argv[1]));
        floatToBinary(f, str);
    }
    cout << str << endl;
    return 0;
}

Compile and run (I'm using GNU g++ on Linux):

me@mypc:~/college/c++/utils$ g++ -c floattobinary.cc
me@mypc:~/college/c++/utils$ g++ -c test.cc
me@mypc:~/college/c++/utils$ g++ -o test *.o
me@mypc:~/college/c++/utils$ ls
floattobinary.cc  floattobinary.o  test*  test.cc  test.o
me@mypc:~/college/c++/utils$ ./test 37.73
01000010000101101110101110000101
me@mypc:~/college/c++/utils$ ./test 2.0
01000000000000000000000000000000
me@mypc:~/college/c++/utils$ ./test 0.0
00000000000000000000000000000000
me@mypc:~/college/c++/utils$ ./test 237.74
01000011011011011011110101110001
me@mypc:~/college/c++/utils$ ./test 2.74e12
01010100000111110111110100101111
me@mypc:~/college/c++/utils$ ./test 2.74e13
01010101110001110101110001111010
me@mypc:~/college/c++/utils$ ./test -88.37
11000010101100001011110101110001
pr1268
  • 1,176
  • 3
  • 9
  • 16
  • 1
    That's an interesting solution. The only problem is if sizeof(float) != sizeof(uint32_t). The char* solution doesn't have this problem. – Petko M Nov 19 '10 at 02:14
  • 2
    I think that's a undefined behavior. Only one member of a union is active at any time. There are many threads on SO on this – Chubsdad Nov 19 '10 at 02:18
  • 1
    @Ignite: The size of a C/C++ single-precision floating point (type float) is 32 bits (4 bytes) as per IEEE-754. A C/C++ double is 64 bits (8 bytes). But yes, you would be correct that my code would not work if sizeof(float) != sizeof(uint32_t). Note that I use uint32_t (an unsigned 32-bit number) since the sizes of int, short, long, etc. all can change depending on the architecture/compiler/etc. @Chubsdad: Not undefined behavior - unions in C/C++ are simply a way of placing multiple types of objects at the same memory address. Try my code--it works. – pr1268 Nov 19 '10 at 02:40
  • 1
    @pr1268 remember that one of the possible outcomes of undefined behavior is *appearing* to work correctly. In recent years the compiler writers have been taking liberties with undefined behavior to get the last bit of optimization in their code. What worked yesterday may not work tomorrow. – Mark Ransom Feb 22 '16 at 19:05