0
#include <iostream>

using namespace std;

int main()
{
    long int b2 = 0;
    long int i = 1;
    int x;

    cout << "Enter a number:" ;
    cin >> x ;
    int y = x;
    while (x!=0) {
         if ( x%2 )
         {
             b2 = b2 + i;
         }
         i = i*10;
        x=x/2;
     }
     cout << "Number " << y << " in base(2) is: " << b2;
}    

This code transforms any number from base 10 to binary. There is only one problem, if I change any of the variable b2 or i to int instead of long int and I insert a number great than 1000 I get some weird results, sometimes negatives. I'm using Ubuntu 18.04 and code::blocks to compile. I researched but couldn't really find an answer. The int has 4 bytes which means 2^32 possibilities. It should work...

Ripi2
  • 7,031
  • 1
  • 17
  • 33
eMe
  • 47
  • 5
  • As explained [here](https://en.cppreference.com/w/cpp/language/types) standard defines `int` to be at least 16-bit long, while it defines `long int` to be at least 32-bits long. – Algirdas Preidžius Sep 24 '18 at 17:06
  • 4
    Understand that when you "encode" the binary representation of a number in an `int`, you are actually writing a base 10 number using only `1` and `0`. You are wasting the vast majority of your 2^32 possibilities. – François Andrieux Sep 24 '18 at 17:06
  • 3
    I recommend you store the binary "number" as a string instead. – Some programmer dude Sep 24 '18 at 17:06
  • 4
    `i = i*10;` That can get really large really fast. – 001 Sep 24 '18 at 17:08
  • 2
    `INT_MAX = 2,147,483,647` so after 9 bits you'll overflow since `10^10 = 10,000,000,000`. – 001 Sep 24 '18 at 17:12
  • If you only print the binary bits, there is no need to store them. Output the bit values inside the `while` loop. – Thomas Matthews Sep 24 '18 at 17:35
  • @ThomasMatthews might want to check the digit emission order on that suggestion. If they are just dumped from the loop they'l be in reverse order. The OP would need to stack them, or just use a recursive algorithm (which sometimes lends itself well to certain fixed-depth applications, and this is one of those times), – WhozCraig Sep 24 '18 at 17:38

2 Answers2

4

You're confusing numbers with numerals.

A (32-bit) int (by far the most common these days) can hold 2^32 (about 4 billion) possible values. But each of those values is a number. 0b10000, 0x10, 020, and 16 are different numerals, but as an int, they're all the same number. There's no conversion to be done at that level.

What you're doing is trying to use numbers as numerals. And that is going to cause you headaches. By multiplying by 10 to shift, you effectively use decimal digits as bits. A decimal digit is worth a little over 3 bits (log210 ~= 3.322), meaning your 32-bit number can only represent 10 bits without problems. Any value over 1023 will end up becoming an 11-digit number and overflowing your int.

Using long int instead can get you another 32 bits, if your environment has 64-bit longs. That'll get your limit up to 19 "bits" (20 if you use unsigned long). But the better solution is to use a string instead, if the goal is simply to see a binary representation.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • Ok I get it! Is there any way to optimize the code so that i = i*10 won't get that big ? – eMe Sep 24 '18 at 17:50
  • @eMe no, `i` is an integer type; jack it up by x10 with each iteration and sooner or later you're going to overflow. So don't do that in the first place, as it says how in the last sentence of this answer: stop using a integral value for storing your bits in the first place (i.e. use a string of digit *characters*, a bitset, etc.) – WhozCraig Sep 24 '18 at 17:54
  • @eMe: No. Any way you try to do that, you end up using a decimal digit's worth of space per "bit". What you need is to get away from the whole idea of using an `int` or `long` to hold your numeral. That's not what it does (at least not well). You can do something very similar with a string instead. – cHao Sep 24 '18 at 17:56
  • In my mind if I'm going to use "i" as a string I don't see how it would work. Because you can't multiply and divide strings with numbers can't you ?! I have to read that thing you showed me. I'm sure the answer is already there. Forgive me for being a newb and thanks for ur help! Ok so probably there is a difference between a bitset and a string. – eMe Sep 24 '18 at 18:02
  • @eMe: Yes, there is. A bitset is made for doing bitwise stuff with. You can examine individual bits and twiddle them to your heart's content. If you want to do that, then it's a better choice. A string is more for if you just want to see your number represented a certain way. – cHao Sep 24 '18 at 18:06
  • @eMe: As far as multiplying and dividing strings with numbers, if you're simply switching bases, there's no need to do that. Your number, you'd keep in an int. You shift or mask (or divide or mod) the int as needed to determine whether you have a 0 or 1 in a given position, and add the appropriate digit to your string. – cHao Sep 24 '18 at 18:25
  • @cHao I read your comment and I'm like "Ooooooooooooooooooooooooooooo" that's right. Thank you! I get it now! – eMe Sep 25 '18 at 14:22
  • I made it. YES! `while (x!=0) { if ( x%2 ) { b2.insert(0,"1"); x=x/2; } else { b2.insert(0,"0"); x=x/2; } ` – eMe Sep 25 '18 at 15:14
3

There is a problem with your code. You actually, don't convert a base 10 number to base 2. You store your number as int or long, that is why it is becoming bigger than the int or long size very quickly. The numbers are kept already in binary in our computer.

If you really want to print the number see std::bitset.

If you want to play the numbers, like setting or clearing bits you have to use some mask. Or, better use std::bitset from the c++ standard library;

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
kelalaka
  • 5,064
  • 5
  • 27
  • 44
  • Ok I get it! I'll go through that "std::bitset" post, it looks very interesting. Also... is there any way to optimize the code so that i = i*10 won't get that big ? – eMe Sep 24 '18 at 17:50
  • 1
    Please read carefully, The number is already stored binary. You only need printing, rest are operations... – kelalaka Sep 24 '18 at 17:53