-5

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++

Abhi
  • 7
  • 1
  • 8
    `(bit * pow(10,i))` you're mixing floating point and integer calculation. This will give you rounding errors. (see : [is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken)). Make your own integer power of 10 function. Also know your value is already binary in memory so you only have to check the bits with a mask, shift and 'logical and` operations no need to do all this computations. Or just use [std::bit_set](https://en.cppreference.com/w/cpp/utility/bitset)'s tostring method. – Pepijn Kramer Aug 11 '23 at 17:38
  • 2
    "Converting" five into one hundred and one is not a decimal-to-binary conversion. – molbdnilo Aug 11 '23 at 17:43
  • 1
    Since your goal is to print a series of zeros and ones that are the binary representation of a given number, your code should do just that. Use your loop to create a string not a fake binary number. – john Aug 11 '23 at 17:57
  • In any case your problem is with the `pow` function which (a) doesn't work the way you think it it does, and (b) isn't necessary to solve this problem. – john Aug 11 '23 at 17:59
  • 2
    I reopened this because it's not a "floating point math is broken" issue. The pow function works very reliably well for whole numbers. What the OP's issue is that they are trying to represent binary in base-10 and running out of bits in the variable they are using. It's an integer overflow issue, not a floating point issue per se. – selbie Aug 11 '23 at 18:02
  • 2
    @selbie Whether `pow` work reliably for whole numbers depends on your platform. Also I see no evidence that integer widths are the problem the OP is having (obviously it is a problem in general with this approach). The OP says the program works for input above 7. It's doesn't work for 5 to 7, that's not 5 to 7 digits, it's literally the numbers 5, 6 and 7. – john Aug 11 '23 at 18:09
  • @PaulMcKenzie - your link is broken. – selbie Aug 11 '23 at 18:31
  • [Here is the link](https://godbolt.org/z/cs3xvn5de) to using `std::bitset`. – PaulMcKenzie Aug 11 '23 at 18:46
  • You can elimnate the `pow` function call by using a `power` variable. Initialize `power` to 1 before the loop. At the bottom of the loop, multiply the `power` variable by 10. Your calculation would look like: `(bit * power);`. – Thomas Matthews Aug 11 '23 at 19:44

3 Answers3

2

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;     
selbie
  • 100,020
  • 15
  • 103
  • 173
  • Your answer doesn't answer the question. The OP is asking why the posted code doesn't work for input 5. The binary representation is 101. That should fit into an int. The question is: _"Why not work for 5 to 7 input"_ and you didn't answer the question. We are talking about `n = 5`, `n = 6` or `n = 7`. You can see the problem in the screenshot in the question. The values are `Decimal: 5, Binary: 100`. That's the actual problem. – jabaa Aug 11 '23 at 19:41
  • @selbie FYI: Your solution does not work for negative values of n. I suggest using `ans = std::format("{:b}", n);`, as I did in my answer. Otherwise, you could troubleshoot, and figure out where to take the absolute value of n, and then figure out how to add the sign back into `ans`. – tbxfreeware Aug 12 '23 at 00:01
  • @tbxfreeware - My assumption is that the OP is completing an academic exercise and needed to demonstrate bitwise operations to do the conversion and the negative number support was up to him. Also, I wanted to give the OP encouragement to use as much of his own code as possible. Otherwise, I agree, std::format or similar library call gets the job done. – selbie Aug 12 '23 at 00:08
  • 1
    @selbie writes: "Also, I wanted to give the OP encouragement to use as much of his own code as possible." I like this. It is why I posted an alternative answer that allows him to use function `main` as written, _without making any changes at all!_ Still, it is clear that `ans` should be a `std::string`, and that is something my alternative does not do. – tbxfreeware Aug 12 '23 at 00:35
0

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
tbxfreeware
  • 547
  • 1
  • 9
0

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.

  • This is similar to what I had in my toolbox for a long time. It avoids what could be an "expensive" multiply operation, especially when floating point values are involved. When `n` is negative, your code exposes what is presumably a two's-complement implementation for signed integers. In real life, [every computer uses two's-complement](https://www.youtube.com/watch?v=JhUxIVf1qok), but the C++ Standard still maintains the fiction that some might not, and calls it an implementation detail. On that basis, your code is _nominally_ not portable. In real life, however, it is. – tbxfreeware Aug 12 '23 at 03:14
  • My old program stripped off the sign, used `abs(n)` to make the conversion, and then added back the sign. These days, I'm using `std::format("{:b}", n)`. Both produce a "signed magnitude" result. – tbxfreeware Aug 12 '23 at 03:15
  • Happily, it looks like my information is out-of-date. [According to CppReference](https://en.cppreference.com/w/cpp/language/types), as of C++20, "..., all C++ compilers use two's complement representation, and as of C++20, it is the only representation allowed by the standard." Your code is portable. Some variation of [p0907R1 Signed Integers are Two’s Complement](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r1.html#issues-index) was adopted. Hurray! – tbxfreeware Aug 12 '23 at 04:03