【问题标题】:Binary Converter Not Working for Large Numbers二进制转换器不适用于大数
【发布时间】:2013-01-15 04:01:21
【问题描述】:

我正在编写从整数转换为其二进制表示的 C 代码,反转二进制,然后再转换回整数。它运行良好,但我需要它来处理高达 10^9 的输入值。现在,它似乎会因为任何大于 10^7 的东西而中断。我的意思是我输入一个数字,例如 10000000,然后输出 17967657062982931584 作为二进制表示(尽管对于较小的整数是准确的)。此外,我不确定我的 int_to_binary 是唯一遇到此问题的函数,或者其他函数是否也需要针对大输入进行优化。有什么想法我哪里出错了吗?谢谢。

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

unsigned long long int_to_binary(unsigned long long k) {
    if (k == 0) return 0;
    if (k == 1) return 1;
    return (k % 2) + 10 * int_to_binary(k/2);
}

unsigned long long reverse_int(unsigned long long l) {
        unsigned long long reversed; 
    reversed = 0;
        while (l > 0) {
                reversed = reversed * 10 + (l%10);
                l = l / 10;
        }
        return reversed;
}

unsigned long long binary_to_int(unsigned long long k) {
    char binaryString[80];
    snprintf(binaryString, 4, "%llu", k);
    unsigned long long decimal = 0;
    int length = strlen(binaryString);
    int i = 0;
    while(i < length) {
        decimal = (decimal << 1) + (binaryString[i] - 0x30);
        i++;
    }
    return decimal;
}

int main() {
    int number;
    printf("Enter a number: ");
    scanf("%d", &number);
    printf("You entered %d\n", number);
    unsigned long long b = int_to_binary(number);
    printf("In Binary, this is %llu\n", b);
    unsigned long long c = reverse_int(b);
    printf("When we reverse it, it looks like this: %llu\n", c);
    unsigned long long d = binary_to_int(c);
    printf("And when we convert that back to an int, it looks like this: %llu\n", d);
        return 0;
}

【问题讨论】:

  • 有时将整数转换为 bcd(和 bco / bch)是有意义的,如果不是为了其他任何东西,但能够使用 printf 打印它。但是在 base-10 中反转二进制文件是多余的(除非是为了学术练习)。在这里,您偶然发现了一个问题,即二进制的以 10 为底的编码需要大约 log2(10)~=3.32 倍的变量来保存原始变量。
  • 嗨@AkiSuihkonen,我确实这样做是我认识的人向我提出的挑战,我觉得很有趣。但是,反转部分似乎没有失败(到目前为止);更有可能是 int_to_binary 和 binary_to_int 方法造成了问题。

标签: c binary type-conversion largenumber


【解决方案1】:

您使用long long 将二进制数表示为十进制数。在许多架构上,这会导致存储的最大值为 2**64-1 = 18446744073709551615。

如果你输入一个十进制数,例如 10000000,它不能表示为 64 位的十进制二进制数。

【讨论】:

  • 取决于您使用结果的目的。如果是出于显示目的,只需使用二进制转换的结果创建一个char* 数组。数组中的每一项都将存储一个 '0' 或 '1' ASCII 字符。
  • 如果我想让我的程序正常工作,我肯定需要一些方法来获取这个二进制值并对其进行操作。问题是,一旦我创建了这个 char* 数组,我如何转换/使用它作为某种小数/int/long?
  • 对不起,我不太明白你的问题。用户输入的数字已经通过您的scanf 调用转换为二进制,并表示为C int。您可以使用|&amp; 等运算符直接操作此int
  • @Potatoswatter OP 采用十进制二进制的想法。我试图提出一种不同的方法。
  • @AustinPhillips,如果只是为了保存位,只需为 int(或 char)数组中的每个位存储一个 0 或 1。
【解决方案2】:

问题是试图将二进制数作为 10 的幂和来操作。直接操作二进制更有效。只需在reverse_int 函数中将10 更改为2

unsigned long long reverse_int(unsigned long long l) {
        unsigned long long reversed; 
        reversed = 0;
        while (l > 0) {
                reversed = reversed * 2 + (l%2);
                l = l / 2;
        }
        return reversed;
}

为了以二进制形式打印数字,编写一个循环,使用模%&amp;&gt;&gt; 等位运算符按顺序测试每个位。

【讨论】:

  • 感谢您的建议,但是我遇到的主要问题不在此函数中,而是在 int_to_binary 函数和 binary_to_int 函数中。 Austin Phillips 的建议是个好主意,我成功地制作了一个包含数字的 char* 数组;但是,由于我想操纵它,我尝试将它转换回 long long,这再次导致我遇到同样的问题。我认为问题在于 long long 类型能够存储什么。
  • @RMartin 是的,这个建议的目的是在long long 的范围内工作(或者实际上long 也足够了)。
  • 是的,这适用于 reverse 函数,但不适用于 int_to_binary 函数,这是 long 似乎被截断(或以其他方式出现乱码)的地方。
  • @RMartin 解决方案是不这样做,并消除在像“long”这样的整数类型中将事物转换为十进制的任何概念。只有在打印数字时才能转换为特定的基数。
  • @RMartin 整数本身并不存在于基数中。如果我有五只鸡,它们是在 base 2 还是 base 10? “将整数转换为二进制”并获得另一个整数的任务基本上是无稽之谈。该函数的作用是通过反转二进制表示获取表示的数字。打印二进制表示将是另一个功能。但是一个数字没有底,只有它的表示有。
猜你喜欢
  • 2021-11-29
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
  • 2021-07-29
  • 2015-05-16
  • 2020-06-19
  • 2012-10-26
相关资源
最近更新 更多