在C语言中将整数转换为32位二进制

3

我正在编写一个程序将整数转换为32位二进制。问题在于输出是反着的。

#include <stdio.h>

int main() {
    long number, binary, num2;

    printf("Enter an integer: ");
    scanf("%ld", &number);

    for (num2 = (number * 2) / 2; num2 > 0; num2 /= 2) {
        binary = num2 % 2;
        printf("%ld", binary);
    }
    putchar('\n');
    return 0;
}

如果我输入'6',它会显示为011,但应该是110。

另外,如何输出其余的'0'?因此,在这种情况下,整个输出应为:

00000000 00000000 00000000 00000110 

数字是整数,因此(number * 2)/ 2等于数字!(假设没有溢出,并且编译器不会优化掉它。) - Mitch Wheat
1
此外,我将您的问题标题输入搜索引擎中,毫不意外地有很多结果! - Mitch Wheat
@MitchWheat 我敢打赌,它们中的大多数由于整数溢出而导致未定义行为。 - M.M
6个回答

2
你需要从右边开始计算数字,这就是为什么输出结果首先显示最右边的数字。下面是一种从左边开始使用位掩码的方法,不需要将值转换为无符号数,这样可能会改变比特位:
#include <stdio.h>
#include <limits.h>

int main()
{
    long number;
    if ( 1 != scanf("%ld", &number) )
        return 1;

    // sign bit  (cannot use 1L left-shift as that causes UB)
    putchar( '0' + (number < 0) );

    // value bits
    for (long bit = 1L << (CHAR_BIT * sizeof number - 2); bit; bit >>= 1)
        putchar( '0' + !!(number & bit) );

    putchar('\n');
}

0
如果您想打印二进制数,应该将位倒过来打印。看这个例子:
6(10): 6/2=3,余数 => 0 3/2=1,余数 => 1 1/2=0,余数 => 1 因此6(2)=110
您正在按正向顺序打印它,这将给您011。所以您应该通过将它们放入一个变量中保留二进制位,并最终将它们打印回来。
试试这个方法。
#include <stdio.h>
  int main(){
  long number, binary, num2;
  int i = 0, j;
  char num[100];

  printf("Enter an integer: ");
  scanf("%ld", &number);

  while (number != 0){
    num[i] = num2 % 2;
    number /= 2;
    i++;
  }
  for (j = 0; j < 32; j++) {
    if (j > i) {
      printf("0");
    }
    else {
      printf("%c", num[i]);
      i--
    }
  }
  printf("\n");
  return 0;
}

0

使用递归函数来完成这个任务会更加容易:

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

void printInBinary(long num, int bit)
{
   if ( bit >= 8*sizeof(num) )
   {
      return;
   }

   printInBinary(num/2, bit+1);
   printf("%ld", num%2);

   if ( bit%8 == 0 )
   {
      printf(" ");
   }
   if ( bit == 0 )
   {
      printf("\n");
   }
}

int main()
{
   int y = 31;
   uint32_t x1 = (1 << y );
   uint32_t x2 = (1u << y );
   printf("x1: %u\n", x1);
   printInBinary(x1, 0);

   printf("x2: %u\n", x2);
   printInBinary(x2, 0);
}

输出:

x1: 2147483648
00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000 
x2: 2147483648
00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000 

如果您使用的是uint32_t而不是long,则将获得32位的输出。


不错!只是有一个小问题,这将以相反的位顺序打印值。您可能希望切换到尾递归以按与原始值相同的位顺序打印... :) - corecase
@corecase,它首先打印高位比特。这样不更有意义吗? - R Sahu
假设使用典型的主机,位顺序通常是小端,因此最重要的位往往是最左边的位。我个人更喜欢按照它们在我的机器上实际表示的顺序打印出这些位,因此这将与该顺序相反... 这有点偏好的问题,也取决于您运行代码的机器的字节序,但根据这个问题的上下文,小端似乎是一个更合理的假设。不过这只是一个非常小的细节! - corecase

0

这里是一个简单的可移植实现,适用于32位数字:

#include <stdio.h>
#include <string.h>

int main() {
    long input;  // at least 32 bits
    unsigned long number;
    int i;

    printf("Enter an integer: ");
    if (scanf("%ld", &input) != 1) 
        return 1;
    /* copy the bit pattern to an unsigned long */
    memcpy(&number, &input, sizeof number);
    for (i = 32; i-- > 0;) {
        if (i > 0 && (i & 7) == 0)
            putchar(' ');
        putchar('0' + (int)((number >> i) & 1));
    }
    putchar('\n');
    return 0;
}

-1

只需按照您希望输出的顺序检查位。我使用了unsigned long类型的转换进行移位,因为将有符号值的位移入符号位的结果是未定义的。

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

    int main() {
        long number = 0;
        int i;

        printf("Enter an integer: ");
        scanf("%ld", &number);
        for(i=0; i<sizeof(number)*CHAR_BIT; i++) {
            if (number < 0)
                printf ("1");
            else
                printf ("0");
            if ((i % CHAR_BIT) == CHAR_BIT - 1)
                printf (" ");
            number = (long)((unsigned long)(number) << 1);
        }
        printf("\n");
    return 0;
    }

程序输出:

Enter an integer: 6
00000000 00000000 00000000 00000110

1
你确实避免了未定义行为;然而(long)((unsigned long)(number) <<= 1)是依赖具体实现的,可能会引发信号。 - M.M
@MattMcNabb 我的第一个解决方案是将 long 赋值给 unsigned long 并在整个过程中使用它,但是解释起来更难。 - Weather Vane
@MattMcNabb 哦,我刚注意到错误的 <<= 并将其编辑掉了,谢谢。 - Weather Vane
嗯,我们都有同样的盲点,我的意思是<<版本会导致实现定义的行为,可能会引发信号(<<=版本是不合法的)。我想这个算法只能依赖于实现在那里做出“明智”的决定。 - M.M

-1
#include <stdio.h>

int main(){
    // Assuming 32 bit architecture.
    unsigned long number;

    // Initialize a null-terminated char-array
    // of zeros (ASCII value 48).
    char binary[33] = {[0 ... 31] = 48, [32] = 0}; 

    printf("Enter an integer: ");
    scanf("%lu", &number);

    for(int i = 0; number > 0; ++i) {
        binary[31 - i] = number % 2;
        number /= 2;
    }
    printf("%s\n", binary);
    return 0;
}

你应该使用'0'代替硬编码ASCII值48。此外,你应避免非可移植的gcc扩展[0 ... 31]。最后,binary[31 - i] = number % 2不能产生数字值,你必须加上'0' - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接