【问题标题】:convert integer to 32-bit binary in c在c中将整数转换为32位二进制
【发布时间】:2015-05-18 00:32:43
【问题描述】:

我正在编写一个将整数转换为 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 是一个整数,所以 (number * 2) / 2 等于 number ! (假设没有溢出,并且编译器不会优化它。
  • 另外,我在搜索引擎中输入了你的问题标题,不出所料,点击率很高!
  • @MitchWheat 我敢打赌它们中的大多数会由于整数溢出而导致未定义的行为

标签: c binary converters


【解决方案1】:

您从右边开始计算数字,这就是为什么您的输出首先显示最右边的数字。这是一种从左侧开始的方法,使用位掩码,并且不会将您的值转换为可能会更改位的无符号:

#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');
}

【讨论】:

    【解决方案2】:

    为此使用递归函数要容易得多:

    #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

    PS如果你用uint32_t代替num而不是long,你将得到32位的输出。

    【讨论】:

    • 不错!这只是一个小问题,这将以相反的位顺序打印值。您可能希望将其切换为尾递归,以与原始值相同的位顺序打印... :)
    • @corecase,它首先打印高位。这不是更有意义吗?
    • 假设一个典型的主机,位顺序通常是小端,所以最重要的位往往是最左边的位。我个人更喜欢以与它们在我的机器上实际表示的顺序相同的顺序打印出这些位,所以这将与该顺序相反......这是一种偏好,它也取决于机器的字节序您正在运行代码,但基于这个问题的上下文,小端似乎是一个更合理的假设。虽然这是一个很小的细节!
    【解决方案3】:

    如果要打印二进制数,则应向后打印位。观看:

    6 (10):

    6 / 2 = 3,rem => 0

    3 / 2 = 1, rem => 1

    1 / 2 = 0, rem => 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;
    }
    

    【讨论】:

      【解决方案4】:

      下面是 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;
      }
      

      【讨论】:

        【解决方案5】:

        只需按照您希望它们输出的顺序检查这些位。我使用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
        

        【讨论】:

        • 你确实避免了UB;但是(long)((unsigned long)(number) &lt;&lt;= 1) 是实现定义的,可能会引发信号。
        • @MattMcNabb 我的第一个解决方案是将long 分配给,并始终使用unsigned long,但解释起来更难。
        • @MattMcNabb 啊,刚刚发现不正确的&lt;&lt;= 并编辑了它,谢谢。
        • 嗯,我们都有相同的盲点,我的意思是&lt;&lt; 版本会导致实现定义的行为,这可能会引发信号。 (&lt;&lt;= 版本格式错误)。我想这个算法只需要依靠实现“明智”来做出决定。
        【解决方案6】:
        #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'
        猜你喜欢
        • 2017-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-09
        • 2018-12-11
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多