3

I made a function that converts numbers to binary. For some reason it's not working. It gives the wrong output. The output is in binary format, but it always gives the wrong result for binary numbers that end with a zero(at least that's what I noticed..)

unsigned long long to_binary(unsigned long long x)
{
    int rem;
    unsigned long long converted = 0;

    while (x > 1)
    {
        rem = x % 2;
        x /= 2;
        converted += rem;
        converted *= 10;
    }

    converted += x;

    return converted;
}

Please help me fix it, this is really frustrating..

Thanks!

Lockhead
  • 2,423
  • 7
  • 35
  • 48
  • 4
    It is really frustrating because numbers are already in binary form and there is no need to convert. What you can do is to print its bits, but there are tons of examples in Internets. –  Feb 28 '11 at 16:10
  • 2
    What you're doing is converting to a decimal number that looks like binary, but has the wrong value. What exactly is your homework assignment? – Wooble Feb 28 '11 at 16:12
  • It's not a homework assignment. I'm trying to learn something here. I know numbers are already binary, but they are displayed as decimal. I just want to display them as binary, and to do that I need to convert the decimal representation to binary. Or do I? If there's a way to display them as their binary representation, I really would like to see it. Thanks – Lockhead Feb 28 '11 at 16:16
  • possible duplicate of [How to convert an int to a binary number to a string in C++](http://stackoverflow.com/questions/2890502/how-to-convert-an-int-to-a-binary-number-to-a-string-in-c) – Martin York Feb 28 '11 at 18:45

9 Answers9

4

Use std::bitset to do the translation:

#include <iostream>
#include <bitset>
#include <limits.h>

int main()
{
    int     val;
    std::cin >> val;

    std::bitset<sizeof(int) * CHAR_BIT>    bits(val);
    std::cout << bits << "\n";

}
Martin York
  • 257,169
  • 86
  • 333
  • 562
2
  1. You're reversing the bits.
  2. You cannot use the remains of x as an indicator when to terminate the loop.

Consider e.g. 4.

After first loop iteration:

rem == 0
converted == 0
x == 2

After second loop iteration:

rem == 0
converted == 0
x == 1

And then you set converted to 1.

Try:

int i = sizeof(x) * 8; // i is now number of bits in x
while (i>0) {
  --i;
  converted *= 10;
  converted |= (x >> i) & 1;
  // Shift x right to get bit number i in the rightmost position, 
  // then and with 1 to remove any bits left of bit number i,
  // and finally or it into the rightmost position in converted
}

Running the above code with x as an unsigned char (8 bits) with value 129 (binary 10000001)

Starting with i = 8, size of unsigned char * 8. In the first loop iteration i will be 7. We then take x (129) and shift it right 7 bits, that gives the value 1. This is OR'ed into converted which becomes 1. Next iteration, we start by multiplying converted with 10 (so now it's 10), we then shift x 6 bits right (value becomes 2) and ANDs it with 1 (value becomes 0). We OR 0 with converted, which is then still 10. 3rd-7th iteration do the same thing, converted is multiplied with 10 and one specific bit is extracted from x and OR'ed into converted. After these iterations, converted is 1000000.

In the last iteration, first converted is multiplied with 10 and becomes 10000000, we shift x right 0 bits, yielding the original value 129. We AND x with 1, this gives the value 1. 1 is then OR'ed into converted, which becomes 10000001.

Erik
  • 88,732
  • 13
  • 198
  • 189
  • 1
    He's not using the remains as a stop condition and I think your piece of code need some explanation. I understand it, but I doubt someone with basic C knowledge would. And you're missing the initialization of converted, which is quite important. – krtek Feb 28 '11 at 16:30
  • Could you explain the last line? For what purpose did you use bitwise OR, AND and right shift? And also, what's the purpose of the first line(sizeof(x) * 8)? – Lockhead Feb 28 '11 at 20:18
  • Still having a bit of trouble understanding this... Forgive my ignorance :P Could you perhaps show an example of how this works? – Lockhead Feb 28 '11 at 21:09
  • Awesome! Thanks! I understand it now! I profiled with gprof and this seems to be the best method. – Lockhead Feb 28 '11 at 21:53
1

You're doing it wrong ;)

http://www.bellaonline.com/articles/art31011.asp

The remain of the first division is the rightmost bit in the binary form, with your function it becomes the leftmost bit.

You can do something like this :

unsigned long long to_binary(unsigned long long x)
{
    int rem;
    unsigned long long converted = 0;
    unsigned long long multiplicator = 1;

    while (x > 0)
    {
        rem = x % 2;
        x /= 2;
        converted += rem * multiplicator;
        multiplicator *= 10;
    }

    return converted;
}

edit: the code proposed by CygnusX1 is a little bit more efficient, but less comprehensive I think, I'll advise taking his version.

improvement : I changed the stop condition of the while loop, so we can remove the line adding x at the end.

krtek
  • 26,334
  • 5
  • 56
  • 84
0
void To(long long num,char *buff,int base)
{
    if(buff==NULL)      return;
    long long m=0,no=num,i=1;

    while((no/=base)>0) i++;
    buff[i]='\0';

    no=num;
    while(no>0)
    {
        m=no%base;
        no=no/base;
        buff[--i]=(m>9)?((base==16)?('A' + m - 10):m):m+48;
    }
}
madan
  • 1
  • 1
0

Here is a simple solution.

#include <iostream>
using namespace std;
int main()
{
    int num=241; //Assuming 16 bit integer
    for(int i=15; i>=0; i--) cout<<((num >> i) & 1);
    cout<<endl;
    for(int i=0; i<16; i++) cout<<((num >> i) & 1);
    cout<<endl;
    return 0;
}
Ambrish
  • 31
  • 1
0

You are actually reversing the binary number! to_binary(2) will return 01, instead of 10. When initial 0es are truncated, it will look the same as 1.

how about doing it this way:

unsigned long long digit = 1;
while (x>0) {
  if (x%2)
    converted+=digit;
  x/=2;
  digit*=10;
}
CygnusX1
  • 20,968
  • 5
  • 65
  • 109
0

What about std::bitset?

http://www.cplusplus.com/reference/stl/bitset/to_string/

Kevin
  • 24,871
  • 19
  • 102
  • 158
0

If you want to display you number as binary, you need to format it as a string. The easiest way to do this that I know of is to use the STL bitset.

#include <bitset>
#include <iostream>
#include <sstream>

typedef std::bitset<64> bitset64;


std::string to_binary(const unsigned long long int& n)
{
        const static int mask = 0xffffffff;
        int upper = (n >> 32) & mask;
        int lower = n & mask;
        bitset64 upper_bs(upper);
        bitset64 lower_bs(lower);
        bitset64 result = (upper_bs << 32) | lower_bs;
        std::stringstream ss;
        ss << result;
        return ss.str();
};

int main()
{
        for(int i = 0; i < 10; ++i)
        {
                std::cout << i << ": " << to_binary(i) << "\n";
        };
        return 1;
};

The output from this program is:

0: 0000000000000000000000000000000000000000000000000000000000000000
1: 0000000000000000000000000000000000000000000000000000000000000001
2: 0000000000000000000000000000000000000000000000000000000000000010
3: 0000000000000000000000000000000000000000000000000000000000000011
4: 0000000000000000000000000000000000000000000000000000000000000100
5: 0000000000000000000000000000000000000000000000000000000000000101
6: 0000000000000000000000000000000000000000000000000000000000000110
7: 0000000000000000000000000000000000000000000000000000000000000111
8: 0000000000000000000000000000000000000000000000000000000000001000
9: 0000000000000000000000000000000000000000000000000000000000001001
Stephan
  • 1,007
  • 7
  • 9
0

If your purpose is only display them as their binary representation, then you may try itoa or std::bitset

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <bitset>

using namespace std;

int main()
{
    unsigned long long x = 1234567890;

    // c way
    char buffer[sizeof(x) * 8];
    itoa (x, buffer, 2);
    printf ("binary: %s\n",buffer);

    // c++ way
    cout << bitset<numeric_limits<unsigned long long>::digits>(x) << endl;

    return EXIT_SUCCESS;
}
Oleg Svechkarenko
  • 2,508
  • 25
  • 30