在C中添加大数字

时间:2011-03-28 17:31:20

标签: c++ c visual-c++

在添加大数字时,我对c的行为有点困惑。这可能是一个初学者的问题,但会感激任何帮助。

unsigned long total = 0;
total = 1124073472 + 2835349503;
total += 2533359615;
printf("Total: %u\n", total);

上面打印的总数不正确。第一个添加结果很好,但第三个添加会使总数下降。我在想这是因为溢出。我的问题是什么是可能的解决方案?有没有使用第三方库的解决方案?

注意:我已经尝试了各种数据类型。其中一些是DWORD64,INT64,LONG64等。

先谢谢。

9 个答案:

答案 0 :(得分:3)

这三个数字的数学和大于2 32 ,并且您正在使用unsigned long,在Windows上为32位宽(即使您使用64编译程序)位指针 - 这是对微软的C89的故意违反),所以C和C ++标准指定它包装。你得到的数字是1124073472 + 2835349503 + 2533359615 - 2 32

如果使用64位类型,则必须更改printf格式说明符以匹配。此代码将在符合C99的系统上给出数学上预期的答案:

#include <stdio.h>

int main(void)
{
    unsigned long long total = 1124073472 + 2835349503;
    total += 2533359615;
    printf("Total: %llu\n", total);
    return 0;
}

但是,没有任何版本的MSVC符合C99标准。我不知道MSVC的相应类型声明或printf格式说明符。

附录:1)添加指定包含在签名类型的溢出上;这是未定义的行为。当循环限制与数据相关时,这通常会使使用有符号循环索引的人感到厌烦。 2)如果你使用可能大于2 64 的数字进行数学运算,即使long long也不会拯救你。 C和(据我所知)C ++没有真正的“bignum”类型;你需要一个第三方图书馆。

答案 1 :(得分:2)

你是对的,这是因为溢出。使用64位类型将修复它 - 您需要将printf()格式字符串更改为打印64位类型。使total成为unsigned long long可能会使您获得64位类型,但最安全的方法是使用stdint.h中的一个typedef。这是一个示例程序 - 我还使用inttypes.h来获取PRIu64

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

int main(int argc, char **argv)
{
  uint64_t total = 0;
  total = 1124073472 + 2835349503;
  total += 2533359615;
  printf("Total: %"PRIu64"\n", total);

  return 0;
}

答案 2 :(得分:1)

差不多(!)每个人都在那里。我想你也可以看两个页面。这将真正让您更好地了解如何处理真正的 BIG 数字:

答案 3 :(得分:0)

你所看到的确实是因为溢出而是印刷类型正如其他人所提到的那样,因为这个数字适合long

您将能够执行符合long数据类型的操作。如果你想要大于那个你需要某种“大整数”功能,如果你不想使用第三方库,你可以实现自己的,但是你要重新发明轮子并且更好使用经过测试的库。

答案 4 :(得分:0)

您是否尝试过“unsigned long long int”?这肯定是64位,或者使用uint64_t,如果你有stdint.h。 当然,当你选择更大的数字时,你可能遇到新的溢出问题(确实是这样),然后是时候使用像gmp那样的bignum库了。如果您坚持使用64位数字,请在添加之前进行溢出检查。在这种情况下,使用“%lld”打印小数结果。

答案 5 :(得分:0)

这确实是一个溢出。您可能希望创建自己的“BigNumber”类来对任意大数字执行算术运算。但是,如果可能的话,我建议使用库。编写自己的“BigNumber”类可能有点苦差事。查看此处发布的内容 - Class for calculating arbitrarily large numbers?

如果您不使用它们,您至少可以将它们用作指导。

答案 6 :(得分:0)

以下代码应该在Visual C ++下工作:

unsigned __int64 total = 0;
total = 1124073472LL + 2835349503LL;
total += 2533359615LL;
printf("Total: %I64u\n", total);

答案 7 :(得分:0)

代码有两个问题:

  1. 无符号长整数在32位系统中只有32位。您需要使用long long(并在编译器设置中打开C99标准),或INT64或类似的东西。

  2. printf格式字符串中的%u是32位(或更少)位宽的数字。您需要改为使用%llu。

答案 8 :(得分:0)

您的代码有问题。您应该在printf语句中将%u替换为%lu以匹配total的类型。如果您使用的是32位整数和64位长的系统,那就足够了。但是,如果您正在使用其他类型的系统,则可能需要使用unsigned long long,如其他一些答案中所述。