Long Long Decimal Binary Representation using C

拜拜、爱过 提交于 2019-12-11 17:18:10

问题


I've been trying to print out the Binary representation of a long long integer using C Programming

My code is

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

int main()
{
    long long number, binaryRepresentation = 0, baseOfOne = 1, remainder;
    scanf("%lld", &number);
    while(number > 0) {
        remainder = number % 2;
        binaryRepresentation = binaryRepresentation + remainder * baseOfOne;
        baseOfOne *= 10;
        number = number / 2;
    }
    printf("%lld\n", binaryRepresentation);

}

The above code works fine when I provide an input of 5 and fails when the number is 9223372036854775807 (0x7FFFFFFFFFFFFFFF).

1.Test Case

5
101

2.Test Case

9223372036854775807
-1024819115206086201

回答1:


Using a denary number to represent binary digits never ends particularly well: you'll be vulnerable to overflow for a surprisingly small input, and all subsequent arithmetic operations will be meaningless.

Another approach is to print the numbers out as you go, but using a recursive technique so you print the numbers in the reverse order to which they are processed:

#include <stdio.h>

unsigned long long output(unsigned long long n)
{
    unsigned long long m = n ? output(n / 2) : 0;
    printf("%d", (int)(n % 2));
    return m;
}

int main()
{
    unsigned long long number = 9223372036854775807;
    output(number);
    printf("\n");
}

Output:

0111111111111111111111111111111111111111111111111111111111111111

I've also changed the type to unsigned long long which has a better defined bit pattern, and % does strange things for negative numbers anyway.

Really though, all I'm doing here is abusing the stack as a way of storing what is really an array of zeros and ones.




回答2:


As Bathsheba's answer states, you need more space than is available if you use a decimal number to represent a bit sequence like that.

Since you intend to print the result, it's best to do that one bit at a time. We can do this by creating a mask with only the highest bit set. The magic to create this for any type is to complement a zero of that type to get an "all ones" number; we then subtract half of that (i.e. 1111.... - 0111....) to get only a single bit. We can then shift it rightwards along the number to determine the state of each bit in turn.

Here's a re-worked version using that logic, with the following other changes:

  • I use a separate function, returning (like printf) the number of characters printed.
  • I accept an unsigned value, as we were ignoring negative values anyway.
  • I process arguments from the command line - I tend to find that more convenient that having to type stuff on stdin.
#include <stdio.h>
#include <stdlib.h>

int print_binary(unsigned long long n)
{
    int printed = 0;
    /* ~ZERO - ~ZERO/2 is the value 1000... of ZERO's type */
    for (unsigned long long mask = ~0ull - ~0ull/2;  mask;  mask /= 2) {
        if (putc(n & mask ? '1' : '0', stdout) < 0)
            return EOF;
        else
            ++printed;
    }
    return printed;
}

int main(int argc, char **argv)
{
    for (int i = 1;  i < argc;  ++i) {
        print_binary(strtoull(argv[i], 0, 10));
        puts("");
    }
}

Exercises for the reader:

  • Avoid printing leading zeros (hint: either keep a boolean flag that indicates you've seen the first 1, or have a separate loop to shift the mask before printing). Don't forget to check that print_binary(0) still produces output!
  • Check for errors when using strtoull to convert the input values from decimal strings.
  • Adapt the function to write to a character array instead of stdout.



回答3:


Just to spell out some of the comments, the simplest thing to do is use a char array to hold the binary digits. Also, when dealing with bits, the bit-wise operators are a little more clear. Otherwise, I've kept your basic code structure.

int main()
{
    char bits[64];
    int i = 0;
    unsigned long long number;   // note the "unsigned" type here which makes more sense

    scanf("%lld", &number);

    while (number > 0) {
        bits[i++] = number & 1; // get the current bit
        number >>= 1;         // shift number right by 1 bit (divide by 2)
    }

    if ( i == 0 )   // The original number was 0!
        printf("0");

    for ( ; i > 0; i-- )
        printf("%d", bits[i]);  // or... putchar('0' + bits[i])

    printf("\n");
}



回答4:


I am not sure what you really want to achieve, but here is some code that prints the binary representation of a number (change the typedef to the integral type you want):

typedef int shift_t;
#define NBITS   (sizeof(shift_t)*8)

void printnum(shift_t num, int nbits)
{
    int k= (num&(1LL<<nbits))?1:0;
    printf("%d",k);
    if (nbits) printnum(num,nbits-1);
}
void test(void)
{
    shift_t l;
    l= -1;
    printnum(l,NBITS-1);
    printf("\n");
    l= (1<<(NBITS-2));
    printnum(l,NBITS-1);
    printf("\n");
    l= 5;
    printnum(l,NBITS-1);
    printf("\n");
}



回答5:


If you don't mind to print the digits separately, you could use the following approach:

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

void bindigit(long long num);

int main()
{
    long long number, binaryRepresentation = 0, baseOfOne = 1, remainder;
    scanf("%lld", &number);
    bindigit(number);
    printf("\n");

}

void bindigit(long long num) {
  int remainder;
  if (num < 2LL) {
    printf("%d",(int)num);
  } else {
    remainder = num % 2;
    bindigit(num/2);
    printf("%d",remainder);
  }
}



回答6:


Finally I tried a code myself with idea from your codes which worked,

#include<stdio.h>
#include<stdlib.h>

int main() {
   unsigned long long number;
   int binaryRepresentation[70], remainder, counter, count = 0;
   scanf("%llu", &number);
   while(number > 0) {
       remainder = number % 2;
       binaryRepresentation[count++] = remainder;
       number = number / 2;
   }
   for(counter = count-1; counter >= 0; counter--) {
       printf("%d", binaryRepresentation[counter]);
   }
}


来源:https://stackoverflow.com/questions/48662517/long-long-decimal-binary-representation-using-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!