[英]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.