繁体   English   中英

c integer 转二进制数

[英]c integer to binary number

如果有人可以帮助我,我会很高兴...

我应该编写一个程序,在不使用循环的情况下以二进制表示形式打印 integer。 它还需要以 32 位表示形式打印出数字。 对于小数字(例如 256 仍然有效),下面的代码可以正常工作。 对于大数字,我没有得到预期的 output。

有人知道我该如何解决这个问题吗?

非常感谢!

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

void
print_reverse(uint32_t value)
{

    if (value % 10 == 0) {
        if (value == 0) {
            printf("1");
            return;
        } else {
            printf("0");
            print_reverse(value / 10);
        }
    } else {
        if (value == 1) {
            return;
        } else {
            printf("1");
            print_reverse((value - 1) / 10);
        }
    }
    return;
}

int
print_binary1(uint32_t value, uint32_t binary1, int zeros1)
{
    int rest, binary, zeros;
    if (value == 0) {
        zeros = zeros1;
        printf("%0*d", 32 - zeros, 0);
        return binary1;
    } else {
        rest = value % 2;
        if (rest >= 1) {
            binary = binary1 * 10 + 1;
            zeros = zeros1 + 1;
            return print_binary1((value - 1) / 2, binary, zeros);
        } else {
            binary = binary1 * 10;
            zeros = zeros1 + 1;
            return print_binary1(value / 2, binary, zeros);
        }
    }
}

void
print_binary(uint32_t value)
{
    printf("%" PRIu32, value);
    if (value == 0) {
        printf(" = 0b00000000000000000000000000000001");
    } else {
        printf(" = 0b");
        int binary = print_binary1(value, 1, 0);
        print_reverse(binary);
    }
}

int
main(void)
{
    uint32_t value;
    printf("value: ");
    if (scanf("%" SCNu32, &value) != 1) {
        fprintf(stderr,
                "ERROR: While reading the 'uint32_t' value an error occurred!");
        return EXIT_FAILURE;
    }
    printf("\n");
    print_binary(value);
    printf("\n");
    return EXIT_SUCCESS;
}

首先,除非你有 32 个版本的几乎相同的代码行,否则不可能使用循环。

例如,有问题的代码使用递归来实现循环。 (事实上,任何循环都可以使用递归来实现。)但它仍然是循环的(重复执行相同的代码)。

在隐藏循环的同时实现您想要的最简单的方法是使用snprintf


rest 回答了为什么代码不适用于更大的数字。

看起来这会产生我之前所说的“十进制编码的二进制”(参考二进制编码的十进制),其中十进制表示的每个数字代表一个位。 例如,它将十三(1101 base 2)转换为一千一百零一(1101 base 10)。

如果是这样,程序支持的最大输入是 1,1111,1111(以 2 为底),因为 10,0000,0000(以 10 为底)不适合uint32_t 换句话说,32 位 output 支持 floor(log10(2^32-1)) = 9 位输入。 这意味着程序支持编号从 0 到 511,但不能超过。

通过切换到 64 位 output,您可以支持 floor(log10(2^64-1)) = 19 位输入,这仍然不足以满足您的需求。

你需要一种不同的方法。

“没有循环”是一个愚蠢的约束。 如果它是一个编程练习,那么它可能是有意义的,如果建议是使用一些替代循环,比如递归或循环展开,但这些实际上只是戴着假胡子并用明显的口音说话的循环。 您需要 output 32 个字符,只需查看 32 位即可轻松完成。

无论如何,这是一种无需任何循环的方法,因为我只是展开了循环。 (我不会写 32 条语句,所以我稍微作弊并使用表格)。

// a table for 4-bit numbers to get us started...
char *bits[] = {
    "0000",
    "0001",
    "0010",
    "0011",
    "0100",
    "0101",
    "0110",
    "0111",
    "1000",
    "1001",
    "1010",
    "1011",
    "1100",
    "1101",
    "1110",
    "1111",
};

// brute force, which is essentially loop unrolling
void print_bits_brute(uint32_t i)
{
#define B(offset) bits[(i >> offset) & 0xf]
    printf("0b%s%s%s%s%s%s%s%s\n",
           B(28), B(24), B(20), B(16), B(12), B(8), B(4), B(0));
#undef B
}

展开发生在print_bits_brute()中,正如您所看到的,只需一个循环就可以轻松得多。 这样的循环可能如下所示:

void print_bits_loop(uint32_t i)
{
    printf("0b");
    for (int b = 28; b >= 0; b -= 4)
    {
        printf("%s", bits[(i >> b) & 0xf]);
    }
    printf("\n");
}

它做同样的事情。 如果通过展开循环可以获得一些速度,编译器知道如何将循环中的常量转换为适当的东西,因此展开自己可能没有任何好处。

如果你必须递归地做,那很容易。 它是另一个名称的循环。 嗯,不完全是,因为这段代码不是尾递归的,但它足够接近。

// b must be a power of two here...
void print_bits_b(uint32_t i, int b)
{
    if (b == 4)
    {
        printf("%s", bits[i & 0xf]);
    }
    else
    {
        b >>= 1;
        print_bits_b(i >> b, b);
        print_bits_b(i, b);
    }
}

void print_bits_recursive(uint32_t i)
{
    printf("0b");
    print_bits_b(i, 32);
    printf("\n");
}

一个 32 位 integer 可以拆分为两个 16 位整数。 这些 16 位整数可以拆分为 4 个 8 位整数,它们又可以拆分为 8 个 4 位整数。 那些我们可以直接用桌子处理的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM