十进制转二进制

14

我有一个数字,希望在C语言中将其转换为二进制(从十进制)。

我希望我的二进制始终为5位(十进制永远不会超过31)。我已经有一个手动通过除法实现的函数,但很难将其填充到5位。

是否有更简单的方法?也许使用位移操作?

我还希望以char *的形式表示二进制。

12个回答

19

这里有一个优雅的解决方案:

void getBin(int num, char *str)
{
  *(str+5) = '\0';
  int mask = 0x10 << 1;
  while(mask >>= 1)
    *str++ = !!(mask & num) + '0';
}

这里,我们首先确保字符串以空字符结尾。然后,我们创建一个掩码(mask),其中有一个单一的“1”(它是您期望的掩码,向左移位一次以说明在while条件的第一次运行中的移位)。每次循环时,掩码向右移动一位,然后相应的字符设置为“1”或“0”(!! 确保我们添加了一个0或1到'0')。最后,当掩码中的1被移出数字时,while循环结束。

要测试它,请使用以下代码:

int main()
{
  char str[6];
  getBin(10, str);
  printf("%s\n", str);
  return 0;
}

如果架构使用不同的二进制表示,这会导致程序出错吗? - Monstieur
@Kurian 好的,它将输出 int 中的 5 个最低有效位。虽然我不知道任何架构会将数字 0-31 表示为 int 的意外表示形式。 - Aaron Dufour
@AlexanderCska 这正是它的作用。正如 https://msdn.microsoft.com/en-us/library/474dd6e2.aspx 所示,您可以在C语言中大多数运算符后面添加=来获得赋值版本。 - Aaron Dufour
@AlexanderCska mask&num 是一种_按位_和操作。因为mask只包含一个1位,如果该位在num中为0,则返回0,如果该位在num中为1,则返回非零值。!!0保留为0,将其他任何东西转换为1。最后,'0'是用于表示ASCII中的零字符的数字。 将其加1可得到ASCII中'1'的数字。 - Aaron Dufour
@AlexanderCska 在 C 语言中,char 类型只是一个单字节的数字。printf(或者更准确地说,你的 shell)知道如何将它们解释为 ASCII 码。你可以通过 printf("%d\n", '0'); 来查看它是一个数字。 - Aaron Dufour
显示剩余8条评论

15

如果你不需要前导零,你可以使用itoa(value, outputstring, base)函数。

例如:

char s[9];
itoa(10, s, 2);
printf("%s\n", s);

将打印输出

1010

否则,您可以编写一个非常简单的函数。

void tobin5str(int value, char* output)
{
    int i;
    output[5] = '\0';
    for (i = 4; i >= 0; --i, value >>= 1)
    {
        output[i] = (value & 1) + '0';
    }
}

int main()
{
    char s[6];
    tobin5str(10, s);
    printf("%s\n", s);
    return 0;
}

会打印出

01010

一种更通用的方法是编写一个函数,询问您需要将多少位转换。

void tobinstr(int value, int bitsCount, char* output)
{
    int i;
    output[bitsCount] = '\0';
    for (i = bitsCount - 1; i >= 0; --i, value >>= 1)
    {
        output[i] = (value & 1) + '0';
    }
}

当然,bitsCount必须是1到32之间的值,缓冲字符串必须至少为bitsCount+1个字符分配空间。


7
itoa()在标准C中未定义? - user649198

4
一种方法是这样的:

一个解决方案如下:

unsigned int x = 30;

char bits[] = "00000";

bits[4] = (x & 1) + '0';
x >>= 1;
bits[3] = (x & 1) + '0';
x >>= 1;
bits[2] = (x & 1) + '0';
x >>= 1;
bits[1] = (x & 1) + '0';
x >>= 1;
bits[0] = x + '0';

可能不是最优雅的方法...


1

您始终可以将其分成5位并填充它(这样做是为了填充8位,因为打印像A这样的字符将是数字65)

#include <stdio.h>
#include <math.h>
void main(){
int binary[8], number, i; //for 5 bits use binary[5]
do{
printf("input a number: ");
scanf("%d",&number);
fflush(stdin);
}while(number>256 || number <0); //for 5 bits... 31 use number>31 || number <0
for (i=0; i<=7; i++)  // for 5 bits use i<=4
    {
    binary[i]=number%2;
    number = number/2;
    }
for (i=7; i >=0; i--)  //for 5 bits use i=4
    printf("%d", binary[i]);
number=0; // its allready 0.
for (i=0; i<=7; i++)  //for 5 bits use i<=4
    {
    number=number+binary[i]*pow(2,i);
    }
printf("\n%c",number);
}

1
对于31个值,你可以使用查找表而不是进行malloc来分配字符串,然后进行位操作来填充它。
static const char *bitstrings[] = {
    "00000", "00001", "00010", … "11111"
};

那么你的转换就像这样简单:return bitstrings[i]。如果你经常这样做,这将更快(通过避免malloc)。

否则,你实际上不需要任何移位(除了使编写常量更容易);你可以使用按位与:

char *bits = malloc(6);
bits[0] = (i & (1<<4)) ? '1' : '0';   /* you can also just write out the bit values, but the */
bits[1] = (i & (1<<3)) ? '1' : '0';   /* compiler should be able to optimize a constant!     */
⋮
bits[6] = 0; /* null-terminate string*/

如果你假设使用ASCII,那么有一个(也许)微小的优化可以通过加法实现。你也可以在这里使用循环,但是我需要两行注释 :-P。就性能而言,两者都不会有影响。所有时间都花费在malloc上。


0
int main() {
    int n,c,k;
    printf("Enter_an_integer_in_decimal_number_system:_");
    scanf("%d",&n);
    printf("%d_in_binary_number_system_is:_", n);
    for (c = n; c > 0; c = c/2) {
        k = c%2;
        k = (k>0)? printf("1"):printf("0");
    }
    getch();
    return 0;
}

0
#include "stdio.h"
#include "conio.h"

int main(void)
{
int i, d , n = 1;
int store[10];

printf("Please enter a number to be converted to binary:\n");
scanf("%d",&d);

for (i=0;i<8 ;i++ )
  store[i] = 0;

i = 0;

do{
if(d & n ){
    n <<= 1;  //10
    store[i] = 1;
    i++;
}
else {
    n <<= 1;
    store[i] = 0;
    i++;
}

}while(n <= d);

printf("\n");
for (i=7;i>=0 ;i-- ){
  printf("%d",store[i]);
if(i == 4)
    printf(" ");
}
printf("\n");
return 0;
}

请考虑添加一些解释性的文字。 - yacc

0
#include<stdio.h>

int mask = 1;
void decToBi(int);

void decToBi(int n){
    for(int j=15;j>=0;j--){
        int result;
        result = n & (mask<<j);
        if(result)
            printf("1");
        else
            printf("0");
    }    
}    
int main(){
    int n;
    scanf("%d",&n);
    decToBi(n);
    printf("\n");
return 0;
}

希望这能有所帮助


0

这是一个C程序,使用位运算符将任何系统支持的十进制数转换为二进制,并仅占用所需的内存空间

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char **argv) 
{
    int n, t = 0;
    char *bin, b[2] = ""; 
    scanf("%d", &n);
    bin = (char*)malloc(sizeof(char) + 2);
    while (n != 0)
    {
        t = n >> 1;
        t = t << 1;
        t = n - t;
        n = n >> 1;
        itoa(t, b, 10);
        bin = realloc((char*)bin, sizeof(char) + 1);
        strcat(bin, b);
    }
    strrev(bin);
    printf("\n%s\n", bin);

    return 0 ;
}

0

既然你只使用了5位,为什么不使用查找表呢?类似以下的东西:

/* Convert nstr to a number (decimal) and put a string representation of the
 * lowest 5 bits in dest (which must be at least 6 chars long) */
void getBinStr(char *dest, const char *nstr)
{
  char *lkup[32] = { 
    "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111",
    "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111",
    "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111",
    "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111" };
  strcpy(dest, lkup[atoi(nstr) & 0x1f]);
}

或者是一个开关:

void getBinStr(char *dest, const char *nstr)
{
  switch (atoi(nstr)) {
    case 31:  strcpy(dest,"11111"); break;
    case 30:  strcpy(dest,"11110"); break;
    ...
    case 1:   strcpy(dest,"00001"); break;
    case 0:   strcpy(dest,"00000"); break;
    default:  strcpy(dest,"error");
  }
}

或者如果那看起来太长,也许可以考虑以下内容:

void getBinStr(char *dest, const char *nstr)
{
  unsigned x = atoi(nstr);
  dest[0] = (x & 0x10) ? '1' : '0';
  dest[1] = (x & 0x08) ? '1' : '0';
  dest[2] = (x & 0x04) ? '1' : '0';
  dest[3] = (x & 0x02) ? '1' : '0';
  dest[4] = (x & 0x01) ? '1' : '0';
  dest[5] = '\0';
}

通常我会偏向于前两种,但如果出于某些原因其他方式太大(例如用于小型微控制器的代码),最后一种可能更好。

这些都假设您想要左侧填充零到5位的结果。


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