0

Below is a function I created to convert a decimal number to binary:

int dtob(int n)
{
    int bin = 0;
    int i=0;
    while(n>=1)
    {
        bin += pow(10,i)*(n%2);
        n=n/2;
        i++;
    }
    return bin;
}

Now this function gives correct binary value for some inputs such as 0 through 3 and then 8 through 11, but gives an incorrect input offset by 1, when dealing with inputs like 4,5,6,12 etc.

Incorrect output

Correct Output

Could someone tell me what flaw there is in the logic that I have used??

  • 1
    For one thing, you might get round-off errors from `pow` but more significantly your maximum so-called "binary" number is `1111111111` for a 32-bit `int`. Try `round(pow(10,i))`. – Weather Vane Sep 16 '22 at 13:11
  • 3
    There is no such thing as a "decimal number" passed to the function. It is already binary. I think you mean you are converting a binary number to a weird decimal representation. – Weather Vane Sep 16 '22 at 13:13
  • you should write the binary digits to a string. `n` is already stored in binary. – yano Sep 16 '22 at 13:13
  • Works for me : https://ideone.com/5PN6Vs . I see correct output for 4 and 6. Please include your main in the question – Sourav Kanta Sep 16 '22 at 13:13
  • All numbers inside a computer are to be regarded as binary. Writing C programs "converting from decimal to binary" doesn't make sense, because everything is already binary. Other number representations only matter when you try to display something to a human user. In such a case it makes sense to convert from binary to a decimal _string_. Storing a number such as `int x = 1010101;` and pretending it is binary has no real-world use. So what is the actual problem you are trying to solve, how to create a binary _string_ or...? – Lundin Sep 16 '22 at 13:16
  • The one in error might be because 10² is giving you 99.99999999 and truncated. – Weather Vane Sep 16 '22 at 13:18
  • 2
    decimal numbers are not "converted" to binary; numbers can be "displayed" as binary or decimal or hex,... – Andrew Sep 16 '22 at 13:20
  • hi everyone, thank you for all the input on the question. the aim was not to actually convert a number into binary. i was just working on a problem someone gave me that included this snippet, a problem that has no real world use. anyway, the problem seems to be in the compiler in my specific machine, as the 'conversion' happens flawlessly in other online IDEs. – Sharvansh Shukla Sep 16 '22 at 13:30
  • 1
    As stated, `round` the `pow` result. – Weather Vane Sep 16 '22 at 13:32
  • It's almost certainly not related to your specific compiler. If you get different results on different compilers/machines, it's very likely because of a bug in your code. – Lundin Sep 16 '22 at 13:32
  • Yes, Rounding of the pow value does it for me, Thank you, Weather Vane! – Sharvansh Shukla Sep 16 '22 at 13:35
  • 1
    You are not converting to binary; you are converting the number to another number such that if it is displayed as decimal but interpreted as binary then it will seem correct to that interpreter. BUT, if you try calculations then it will likely fail. Again, numbers are numbers; ten can be displayed as 10 in decimal or 1010 in binary, but "converting" ten to one thousand and ten is WRONG. Displaying it in decimal and pretending it is displayed in binary does not make it right. If you displayed it in binary ("1111110010") then the wrongness would be obvious! – Andrew Sep 16 '22 at 13:39
  • 1
    @WeatherVane and others: The "weird decimal representation" has been aptly dubbed "decimal coded binary" by [ikegami](https://stackoverflow.com/questions/69774736#69775090). – Steve Summit Sep 16 '22 at 15:12
  • Input and output are both integers... I would use only integer operations, like shifts and bitwise and "&". – linuxfan says Reinstate Monica Sep 16 '22 at 15:28

2 Answers2

1

I think what you are actually looking for is a version without floating point functions like pow(). Something like this:

#include <stdio.h>
#include <stdint.h>

uint32_t bin_to_wannabe_bin (uint32_t bin)
{
  uint32_t result=0;

  for(size_t i=0; i<32; i++)
  {
    result *= 10;
    result |= (bin >> (31-i)) & 1u;
  }
  return result;
}

int main (void)
{
  printf("%u\n", bin_to_wannabe_bin(10));
  printf("%u\n", bin_to_wannabe_bin(123));
}

Output:

1010
1111011

Please note that this holds no error handling so it will easily overflow when you run out of the 10 decimal digits of a 32 bit int.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

This seems to be a compiler issue, as the code works fine on online IDEs. I will be closing the question now. Thanks for the input.

Edit: The issue actually seemed to be due to pow giving a 99.9999-ish value for 10^2 and such, which is why it was truncated and gave an offset result. A simple addition to the code did it for me:

bin += round(pow(10,i))*(n%2);

Thank you for all the input, once again!

  • The way `pow` is implemented in the library varies with the implementation. It is often not very accurate. – Weather Vane Sep 16 '22 at 13:32
  • 1
    And instead of using pow you could just multiply the saved result by 10 each lap in the loop. – Lundin Sep 16 '22 at 13:34
  • see my comment above – Andrew Sep 16 '22 at 13:40
  • OP want C, not C++ – Andrew Sep 16 '22 at 13:43
  • 1
    A clarification, and you may understand this by now, but: It *seems* like a "compiler issue", and the behavior does indeed vary from system to system, but in fact, it was a problem in the particular way you used `pow`. The `pow` function is, rightly or wrongly, allowed to behave like that, so a compiler or run-time library that caused your original code to misbehave is *not* wrong. It's up to you to fix it in your code, perhaps by calling `round`, as you've discovered. – Steve Summit Sep 16 '22 at 15:19