why not work for 5 to 7 input ? Decimal to Binary conversion in c++

127 Views Asked by At

when giving input from 5 to 7 it's not working but when giving input above 7 it's working properly.

#include<iostream>
#include<math.h>
using namespace std;
int main()
{   int n;
    cout <<"Decimal : ";
    cin>>n;
    int ans = 0;
    int i=0;
    while(n != 0)
    {
      int bit = n % 2;
      ans = (bit * pow(10,i)) + ans;
      n = n / 2;
      i++;
    }
    cout << "Binary : "<<  ans; 
}

output: Decimal to Binary conversion in c++

3

There are 3 best solutions below

4
selbie On

You can't store a binary number as a base 10 inside a 32-bit integer larger than 1111111111. (1.1 billion). And even if you increased ans be a 64-bit long long, you couldn't get higher than 19 bits before exceeding that limit.

Let's say you have a 7 digit number such as: 9999999. In binary, that would be: 100110001001011001111111. But if you interpret that as decimal, you can't assign that value into a 32-bit integer. It won't even fit into a 64-bit integer either.

Use a string instead of trying to do exponent math. The string has the advantage of never overflowing.

std::string ans;

while (n != 0)
{
  int bit = n % 2;
  if (bit == 1)
  {
      ans = std::string("1") + ans;
  }
  else
  {
      ans = std::string("0") + ans;
  }
  n = n / 2;
}
if  (ans.size() == 0) // handle the zero case
{
    ans = "0";
}
cout << "Binary : "<<  ans;     
0
tbxfreeware On

Let std::format do the work

why not work for 5 to 7 input ?

When I tested your program with Visual Studio 2022, set to use the latest "C++ Language Standard" (i.e., Preview - Features from the Latest C++ Working Draft (/std:c++latest)), it ran correctly. The integers 5, 6, and 7 were all converted correctly.

I can only conclude that pow on your system, and, in particular, the expression (bit * pow(10, i)), has somehow introduced rounding errors due to floating point arithmetic, as was mentioned in the comments.

You can test this theory by adding an extra output statement to your program.

I added such a statement below. In addition, I included header <format>, and switched to header <cmath>, which should generally be preferred over <math.h> in C++ programs.

#include<cmath>
#include<format>
#include<iostream>
using namespace std;
int main()
{
    int n;
    cout << "Decimal : ";
    cin >> n;
    int ans = 0;
    int i = 0;
    while (n != 0)
    {
        int bit = n % 2;
        std::cout << std::format(
            "(bit * pow(10,{})) : {}\n"
            , i
            , static_cast<int>((bit * pow(10, i)))
        );
        ans = (bit * pow(10, i)) + ans;
        n = n / 2;
        i++;
    }
    cout << "Binary : " << ans;
}

Here is the output from a sample run:

Decimal : 5
(bit * pow(10,0)) : 1
(bit * pow(10,1)) : 0
(bit * pow(10,2)) : 100
Binary : 101

In addition, your program has another problem. It will fail for large values of n, because it overflows variable ans.

So that is the answer to your question.

The fix is to avoid using pow. In addition, to handle large values of n, the type for ans should be std::string. I suggest letting std::format do the work for you.

For integral n, this simple format "command" does the trick.

std::string ans;
int n = 5;
ans = std::format("{:b}", n);

You can tune the format specification to meet your needs, for instance, by adding the prefix "0b", or by setting the width, and padding with leading 0s.

Code your own version of pow

Alternatively, you could write a custom version of pow that worked exclusively with type int.

In this answer, I have included header <cmath> just to demonstrate that the custom function pow defined below has a function signature that does not conflict with any version of pow in the Standard Library. When both arguments are type int, the compiler picks the custom version of pow.

Function main is unchanged from the original question.

#include <cassert>
#include <cmath>
#include <format>
#include <iostream>
using namespace std;
int pow(int b, int e)
{
    // There are simple ways to optimize this, but for the 
    // small values of e encountered in this program, I am 
    // going to use "brute force."
    assert(e < 10);
    int p = 1;
    for (int i = e; i--;)
        p *= b;

    // This output proves that the custom version of pow is 
    // being used.
    std::cout << format("pow({}, {}) = {}\n", b, e, p);
    return p;
}
int main()
{
    int n;
    cout << "Decimal : ";
    cin >> n;
    int ans = 0;
    int i = 0;
    while (n != 0)
    {
        int bit = n % 2;
        ans = (bit * pow(10, i)) + ans;
        n = n / 2;
        i++;
    }
    cout << "Binary : " << ans;
}

Here is the output from a sample run:

Decimal : 5
pow(10, 0) = 1
pow(10, 1) = 10
pow(10, 2) = 100
Binary : 101
3
Leif Messinger LOAF On

Solution not listed here: why even convert? It's binary in the computer, so just get the binary from the computer.

#include <iostream>
using namespace std;

int main(){
    cout << "Input a decimal: ";
    int bruh; cin >> bruh;
    
    cout << "Binary: ";
    
    const size_t bits = (sizeof(int)*8);
    for(size_t i = 0; i < bits; ++i){
        const size_t indexTested = (bits-1) - i; //reverse the order in which the bits are printed, so the smallest is last
        if((1 << (indexTested)) & bruh){ //test the indexTested bit
            cout << "1";
        }else{
            cout << "0";
        }
    }
    
    cout << endl;
    
    return 0;
}

Though this can be done better in assembly using the test bit instruction in assembly, and the standard library functions and methods of doing this probably do it that way. It's always better to use library code like making a std::bitset and printing that out, because even if it isn't done the fastest way, sometime someone will make it faster and your program will get a free performance boost.