在 C 中将二进制转换为十进制会出错

Posted

技术标签:

【中文标题】在 C 中将二进制转换为十进制会出错【英文标题】:Converting binary to decimal goes wrong in C 【发布时间】:2021-11-16 19:34:42 【问题描述】:

我编写了这个程序,将二进制数传递给函数并打印该二进制数的十进制值。问题是如果二进制数变大(如 11 个数字),该函数会打印完全不同的东西。我现在尝试解决了几个小时,但没有任何效果。

所以我的问题是:如何更改我的程序,以便在二进制数变大的情况下打印正确的十进制数?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdint.h>

int int_log2_64(uint64_t x)  return 63 ^ __builtin_clzll(x); 
#define K(T) (((sizeof(#T) - 1) << 32) - T)
int digit_count(uint32_t x)


    static uint64_t table[] = 
        K(0), K(0), K(0),
        K(10), K(10), K(10),                         // 64
        K(100), K(100), K(100),                      // 512
        K(1000), K(1000), K(1000),                   // 4096
        K(10000), K(10000), K(10000),                // 32k
        K(100000), K(100000), K(100000),             // 256k
        K(1000000), K(1000000), K(1000000),          // 2048k
        K(10000000), K(10000000), K(10000000),       // 16M
        K(100000000), K(100000000), K(100000000),    // 128M
        K(1000000000), K(1000000000), K(1000000000), // 1024M
        K(1000000000), K(1000000000)                 // 4B
    ;

    int lg2 = int_log2_64(x);

    uint64_t n = (uint64_t)(x) + table[lg2];

    return n >> 32;


void binaryToDecimal(long long int bin)

    int l = digit_count(bin);
    char str[l];
    itoa(bin, str, 10);
    float sum[l];
    int x = l - 1;
    float answer;

    for (int i = 0; i < l; i++)
    
        if (str[i] == '1')
        
            sum[i] = pow(2, x);
        
        x--;
    

    for (int i = 0; i < l; i++)
    
        answer = answer + sum[i];
    
    printf("%.0f", answer);


int main()

    long long int bin = 10101101101;
    binaryToDecimal(bin);

附:我把代码改成了这个,它可以工作

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

void binaryToDecimal(char *bin)

    int l = strlen(bin);
    int x = l - 1;
    float sum[l];
    float answer = 0;

    for (int i = 0; i < l; i++)
    
        if (bin[i] == '1')
            answer += pow(2, x);
        else
            sum[i] = 0;
        x--;
    

    printf("%.0f", answer);


int main()

    binaryToDecimal("010101101101");

【问题讨论】:

你想让binaryToDecimal(100)返回4吗?您是否意识到您可以用 64 位表示的最大 int184467440737095516159223372036854775807,如果已签名)? 另外,itoa()(不在标准中,不在 POSIX 中)将int 作为第一个参数。您正在使用long long int,它可能会被转换为警告。打开所有编译器警告。 注意警告 最大无符号 32 位整数是 4294967295,有符号 32 位整数是 2147483647 除了使用 itoa 和使用 float 的所有问题之外,char str[l] 太短了,因为它没有空间容纳空终止符(也没有空间容纳可能导致的减号将long long int 转换为int 时算术溢出)。另外,answer 还没有被初始化。 @hasan void binaryToDecimal(long long int bin)。输入参数应该是一个字符串而不是long long int 【参考方案1】:

如何更改我的程序,以便在二进制数变大的情况下打印正确的十进制数?

通过将bin 变量设为字符串

也就是说,你想要

void binaryToDecimal(const char *str)

   ...

然后你可以调用类似的东西

binaryToDecimal("101111000110000101001110");

在进行基本转换时,我认为使用整数变量作为输入总是错误的。如果我说

int x = 12;

x 是十进制整数”是真的。 x 是一个整数,句号——我只是碰巧使用了一个十进制常量来获取一个值。或者如果我说

int y = 0x7b;

那么说y 是十六进制就没有意义了——同样,y 只是一个整数。

表示整数的基数很重要:

在输入时,当我们使用scanf%d%o%x 格式从用户那里读取数字时 使用标准库atoistrtol 函数转换字符串时 在输出时,当我们使用printf%d%o%x 格式打印数字时

但在所有这些情况下,基数很重要的表示是一串数字字符,而不是整数。

不编写接受整数的“binary to ...”函数有两个原因。一个是,正如您所看到的,它人为且不必要地限制了您可以转换的数字范围。但更大的原因是这会让你的读者感到困惑,因为它只是错误。如果我看到一个函数调用

f(1001)

我想,“好吧,常量值 1001 正在传递给函数 f。”在任何情况下,我都无法想象它实际上是在尝试传递二进制数 9。

【讨论】:

对于初级人类程序员来说,它是“十进制”(在这个阶段是“数字”的同义词)。理解会随着时间而来 谢谢,我把代码改成了几行就可以了!【参考方案2】:

您的代码过于复杂。切勿使用浮点数进行整数计算。

unsigned binaryToDecimal(long long int bin)

    unsigned answer = 0;
    int shift = 0;
    while(bin)
    
        answer += (bin % 10) << shift++;
        bin /= 10;
    
    return answer;


int main()

    long long int bin = 10101101101;
    printf("%u\n", binaryToDecimal(bin));

https://godbolt.org/z/5E8Gv6oqf

或者使用字符串传递二进制数:

unsigned binaryToDecimal(char *str)

    unsigned answer = 0;
    while(*str)
    
        answer <<= 1;
        answer += *str++ == '1';
    
    return answer;


int main()
 
    printf("%u\n", binaryToDecimal("10101101101"));

https://godbolt.org/z/4vfnETY1f

【讨论】:

以上是关于在 C 中将二进制转换为十进制会出错的主要内容,如果未能解决你的问题,请参考以下文章

如何在 c#.net 中将十六进制转换为十进制? [复制]

在 C 中将 int 转换为 2 字节的十六进制值

如何在C中将十六进制字符串转换为二进制字符串?

在C中将大十进制输入转换为256位数组中的十六进制输出

在c ++中将负整数转换为二进制字符串

如何在 C++ 中将十六进制数字转换为二进制?