2

I'm trying to understand why this programm after 2^20-1 value goes in overflow. All my variables are declared unsigned long long, but when I enter 1048756 which is 2^20 it goes in overflow , instead of converting it in a binary number. I thought that the range of u-l-l was 2^64-1. I included the limits.h library and the maximum value was 8 bytes.This is the code :

#include <stdio.h>
int main(){
  unsigned long long n = 100000000;
  printf("%llu \n",decimal_binary(n));
  return 0;
}

unsigned long long decimal_binary(unsigned long long n)  
{
  unsigned long long rem, i=1, binary=0;
  while (n!=0)
  {
    rem=n%2; 
    n/=2;
    binary+=rem*i;
    i*=10;
  }
  return binary;
}

And the output is : 14184298036271661312 (Which is not a binary number obviously)

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    @callyalater - regardless of the system, `unsigned long long` has at least the range indicated in the question, that is, from 0 up to 2^64 - 1. – Pete Becker Feb 11 '16 at 17:37
  • 3
    Please indent your code. – Jabberwocky Feb 11 '16 at 17:37
  • `unsigned long long decimal_binary(unsigned long long n)` is not declared before use. Insure warnings are enabled in your compiler. – chux - Reinstate Monica Feb 11 '16 at 17:39
  • But you aren't passing a decimal value. The value `100000000` you assigned has already been converted to binary by the compiler. Why are you trying to convert decimal? And you need a function prototype. – Weather Vane Feb 11 '16 at 17:40
  • @callyalater I'm using ubuntu 15.10 . –  Feb 11 '16 at 17:40
  • 2^64 is 1.8e19 which is less than 10^20. Simple maths. – user3386109 Feb 11 '16 at 17:40
  • 1
    Using OP's method, code will need about an 89-bit integer to properly show the result for `decimal_binary(100000000)`. – chux - Reinstate Monica Feb 11 '16 at 17:44
  • This seems like an XY problem. If your actual goal is to print numbers in binary, then see for example [this question](https://stackoverflow.com/questions/111928). Or search `[c] print binary` for more suggestions. – user3386109 Feb 11 '16 at 17:52
  • @user3386109 why 10^20 ? I think with u-l-l i can convert a number from 0 to 2^64-1. –  Feb 11 '16 at 17:54
  • You're converting a 21 bit binary number into a 21 digit decimal number. The minimum value for a 21 digit decimal number is 10^20. – user3386109 Feb 11 '16 at 17:57
  • 2
    1048756₁₀ is 100000000000000000000₂ (2²⁰). Your `decimal_binary` function is trying to convert that to 100000000000000000000₁₀ (10²⁰). That needs an unsigned integer at least 67 bits wide. The maximum value that will fit in a 64-bit unsigned integer is about 1.8447x10¹⁹. Do you see the problem? – Ian Abbott Feb 11 '16 at 18:18

4 Answers4

5
 18446744073709551615 // 2^64-1 
100000000000000000000 // 2^20 in your funny "decimal binary"

See the problem now?

By the way, if you want to get platform dependence out of this, use uint64_t from stdint.h instead of unsigned long long.

user3386109
  • 34,287
  • 7
  • 49
  • 68
Adam
  • 16,808
  • 7
  • 52
  • 98
  • Note: a compliant C compiler/platfrom does not need to provide `uint64_t` – chux - Reinstate Monica Feb 11 '16 at 17:45
  • 1
    To clarify the previous comment, @chux is being pedantic. All compilers OP is ever likely going to run into *do* support `uint64_t`. You should definitely not use that comment as reason to not use these types. – Adam Feb 11 '16 at 17:53
  • 1
    `unsigned long long` is guaranteed to exist (assuming C99 or later), and is guaranteed to have a range of *at least* 0 to 2**64-1. If you don't need the additional guarantees provided by `uint64_t` (no padding bits, *exactly* 64 bits), there's nothing wrong with using `unsigned long long`. – Keith Thompson Feb 11 '16 at 18:01
  • `uint64_t` introduces a strong platform dependency. It is not allowed unless the target platform has a native 64-bit **hardware** type. `unsigned long long` is always at least 64 bits, as are both `uint_fast64_t` and `uint_least64_t`, and all three exist on conforming compilers for **all** platforms. – Pete Becker Feb 11 '16 at 18:24
  • @PeteBecker do you have a reference for that `uint64_t` requires *hardware* support statement? A quick google doesn't bring up anything and it sounds far fetched to me. We've had `long` on 16-bit architectures, after all. – Adam Feb 11 '16 at 20:53
  • @Adam - whoops, you're right: there's no **hardware** requirement. I should be more careful posting when I'm tired. – Pete Becker Feb 12 '16 at 19:54
3

It seems like what you really want is to output a number in binary format. You can't put the conversion back into an integer type like that. You need to construct a string:

void decimal_binary(unsigned long long n, char str[])
{
  unsigned long long rem, len=0, temp, i;
  while (n!=0)
  {
    rem=n%2;
    n/=2;
    // put the binary digit into the string
    str[len++] = rem ? '1' : '0';
  }
  str[len] = '\x0';
  // the digits were inserted in reverse order, so reverse the string.
  for (i=0;i<=len/2;i++) {
    temp = str[i];
    str[i] = str[len-1-i];
    str[len-1-i] = temp;
  }
}

int main(void){
    char buff[200];
    unsigned long long n = 100000000;
    decimal_binary(n,buff);
    printf("%s \n",buff);
    return 0;
}

Output:

101111101011110000100000000
dbush
  • 205,898
  • 23
  • 218
  • 273
0

Let your code detect about when math is getting too big.

#include <stdio.h>
#include <limits.h>

unsigned long long decimal_binary(unsigned long long n)
{
  unsigned long long rem, i=1, binary=0, n0;
  n0 = n;
  while (n!=0)
  {
    rem=n%2;
    n/=2;
    binary+=rem*i;
    if (i > ULLONG_MAX/10) {
      printf("OF %llu %llu\n", n0 , i);
      return 0;
    }
    i*=10;
  }
  return binary;
}


int main(){
  unsigned long long n = 100000000;
  printf("%llu %llu\n",n,decimal_binary(n));
  n = 100000;
  printf("%llu %llu\n",n, decimal_binary(n));
  return 0;
}

Output

OF 100000000 10000000000000000000
100000000 0 
100000 11000011010100000 
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0
main()
{
unsigned long long n = 100000000;
int i;
for(i=sizeof(unsigned long long int)*8-1;i>=0;printf("%llu",n>>i--&1));`
}
OUTPUT::00000000 00000000 00000000 00000000 00000101 11110101 11100001 00000000
ilango victor
  • 61
  • 1
  • 2