问题
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 thatprint_binary(0)still produces output! - Check for errors when using
strtoullto 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