【问题标题】:What type to use for integers larger than 2^32 in C++?C++ 中大于 2^32 的整数使用什么类型?
【发布时间】:2009-06-01 11:03:21
【问题描述】:

我有一个整数变量,它可以得到一个大于 4294967295 的值。

我应该使用什么类型(long long、double 或其他)?

【问题讨论】:

  • 它会不会特别大?因为人们一直在关注 64 位的问题,但如果你告诉他们你在看天文距离或原子数,答案很快就会变成“双倍”,忘记整数。
  • 很棒的评论!在我的情况下,它不会大于 64 位,但它仍然很有趣,如果它这样做了怎么办?在这种情况下我为什么要使用“double”?

标签: c++ types


【解决方案1】:

使用long long,如果可能的话,添加一个编译时断言这个类型足够宽(smth like sizeof( long long ) >= 8)。

double 是浮点数,不是整数。

【讨论】:

  • long long 不是标准的 C++ 数据类型
  • 根据 ISO/IEC 9899:TC3 - 委员会草案 - 2007 年 9 月 7 日 - 与上一版本相比的主要变化包括:long long int 类型和库函数 long long 类型对象的最大值int LLONG_MAX 9223372036854775807 (2^63 - 1)
  • 那是 C99 文档,不是 C++。
  • @Neil:+1 我一直认为它在 C++ 中是一样的,但似乎不是。根据工作草案,编程语言 C++ 标准 (N2798=08-0308):有五种标准有符号整数类型:“signed char”、“short int”、“int”、“long int”和“long long int” ”。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。
  • 请注意,您引用的 N2798 文档是未经批准的 C++0x 草案 - 标准 C++ 没有长整数。
【解决方案2】:

试试:

http://gmplib.org/ 大号。

http://mattmccutchen.net/bigint/大整数。

我都没有使用过,但我在 Java 中使用过类似的东西。

【讨论】:

    【解决方案3】:

    我将假设您的数字适合 64 位。如果没有,那么您需要一个arbitrary-precision arithmetic library,例如GMP

    理论上,在 C++ 中进行 64 位数学运算没有简单、可移植的方法。实际上,大多数 C++ 编译器也支持“老式”C 头文件,而 C99 有一个不错的头文件,称为 stdint.h

    所以先做:

    #include <stdint.h>
    

    然后使用类型int64_t(有符号)和uint64_t(无符号)。

    编辑添加:在我写完这个答案后,C++11 添加了<cstdint> header,它通常*定义 std::int64_t 和 std::uint64_t ,所以如果你有一个现代编译器最好使用这些。

    (* 理论上系统可能根本不支持 64 位类型。但实际上,在您可能遇到的任何系统上都会支持)。

    【讨论】:

      【解决方案4】:

      在 C++ 中没有可移植的方式来执行此操作,因为该语言没有指定整数类型的大小(除了 sizeof char 为 1)。您需要查阅您的编译器文档。

      【讨论】:

      • 不完全正确。该标准确实指定了每种类型的最小幅度,因此暗示了最小位(不是字节)计数,请参阅stackoverflow.com/questions/271076/…
      • 自 C++11 以来,long longunsigned long long 类型保证至少为 64 位宽,以及它们各自的 llull 文字。同样在cstdint 标头中还有int64_tint_least64_tint_fast64_tuint64_tuint_least64_tuint_fast64_t 类型别名可用。
      【解决方案5】:

      这两个提议都不好,因为 long long 不是标准的 C++ 数据类型,而 double 是浮点数。

      由于我的程序必须是可移植的,我将 #define 我自己的类型,以适合我使用的所有编译器(Visual Studio 和 gcc):

      #ifdef WIN32
        #define unsigned_long_long unsigned __int64
        #define long_long __int64
      #else // gcc. Might not work on other compilers!
        #define unsigned_long_long unsigned long long
        #define long_long long long
      #endif
      

      【讨论】:

      • 请注意,这不是 Windows 问题,而是 C++ 标准问题 - 不能保证非 Windows 平台支持 long long。
      • 根据 MSDN long long 相当于 VC++ 中的 __int64 ,所以你不需要那个定义。
      • 另外请注意,如果使用 -pedantic 编译 g++ 会发出很多警告,我认为大多数 C++ 程序都是(它们当然应该是)
      • Neil:为什么会发出警告?
      • 因为 long long 不是标准 C++ - 它是 G++ 支持的 C99 的一部分。使用 -pedantic 编译 C++ 代码将给出关于此的 aq 警告。
      【解决方案6】:

      不要使用双精度,因为:

      cout.setf(ios::fixed);
      cout << LONG_LONG_MAX << endl;
      cout << double(LONG_LONG_MAX) << endl;
      
      cout << LONG_LONG_MAX-100 << endl;
      cout << double(LONG_LONG_MAX-100) << endl;
      

      输出:

      9223372036854775807
      9223372036854775808.000000
      9223372036854775707
      9223372036854775808.000000
      

      【讨论】:

      • 是的,double 将一些位识别指数,实际上失去了精度(与相同大小的整数类型相比)
      【解决方案7】:

      我用

      uint64_t
      

      但这不是标准的。

      【讨论】:

      • 其实 stdint.h 是 C99 的一部分。但是许多编译器供应商即使在 10 年后也不愿意支持“新”标准(有人记得 10 年前 IT 的样子吗?!)。
      • 我不知道你的工作,但对我来说,只有三个编译器供应商很重要。微软、英特尔和 GCC。传统上,这三者都擅长“新”标准合规性。与其说是 SunW C++ 或 HP 或 IBM,但在 Windows/Linux 世界中,这应该不是问题。 15 年前,我记得在早餐时打破编译器和链接器。事实上,DEC 花了两个月的大部分时间来修复一个链接器错误,以便我们可以为 WindowsNT Alpha 发布 Pro/ENGINEER,回到闻所未闻的 32 MB 可执行文件的时代。
      【解决方案8】:

      如果您不需要负数,则 unsigned long long 听起来是您能得到的大多数。

      【讨论】:

        【解决方案9】:

        试试TTMath。您需要做的就是包含一个标头,然后声明一个 bignum 类型,例如:

        typedef ttmath::UInt<100> BigInt;
        

        它创建了一个可以容纳 0 到 2 ^ (32*100)-1 之间的无符号整数的类型。 然后在任何你想使用int的地方使用BigInt

        当然,您可以为模板参数选择任何您喜欢的大小。 100 可能是矫枉过正 ;-)

        刚刚意识到,该库仅适用于 x86 和 x64,但在这些处理器上是操作系统跨平台的。

        【讨论】:

        • 我被困在尝试使用 ttmath 并使用你所说的。您说他需要在使用 Int 的地方使用 BigInt,但事实是我收到此错误“BigInt 类没有名为 ...”的成员,您认为为什么会发生这种情况?
        • @wxiir 您在另一篇文章中说,当您的变量命名为blah 时,您收到错误消息BigInt has no member named blah(这不应该发生)。你尝试像ttmath::UInt&lt;100&gt; blah = 0; blah = blah + 10; 这样的简单声明会发生什么?
        【解决方案10】:

        许多当前的 C/C++ 编译器都有 stdint.h 或 inttypes.h 标头。

        int_fast64_tint64_t 可能是一个选项(恕我直言,最便携)。

        【讨论】:

          【解决方案11】:

          您的程序的可移植性如何? TR1 具有 cstdint 和 stdint.h,因此大多数最新的编译器可能都支持它。如果不支持 cstdint,您应该可以使用 Boost cstdint.hpp。

          【讨论】:

            【解决方案12】:

            双精度数是浮点数。 你应该使用 long long,可能。我不知道哪个别名是首选。

            【讨论】:

              【解决方案13】:

              如果您的编译器没有 long long,您可以使用包含两个 long 的结构自己实现它们,但您需要对进位等进行谨慎处理。您当然可以寻找像 GMP 这样的多精度算术

              【讨论】:

                【解决方案14】:

                只是出于好奇 - 如果您愿意,我认为编写自己的代码不会太难。我的意思是,当然,所有这些数据类型都有预定义的结构,但是您可以使用例如使用指数的double 结构,并执行以下操作:

                要保存一个非常大的数字,超出双倍的比例,请创建一个包含两部分的对象 - 数字和十的幂,

                所以,如果你想存储类似的东西

                1.1230123123 x 10^(100000000000000000000000000000000000),这不受双精度支持,您可以将 1.123 ... 部分存储在双精度中,然后将十的幂作为单独的双精度/整数/浮点数(无论如何西装),然后从那里拿走。当然,这可能不是最好的方法——你可能需要编写很多除法、减法等功能,但它肯定是可移植的,因为你将使用定义的普通数据类型。它的可用性取决于您要实现的目标以及您是否打算在单个项目之外使用它,但我认为如果这些数字是绝对要求,这是一种可行的方法

                【讨论】:

                  猜你喜欢
                  • 2014-12-14
                  • 2019-10-19
                  • 1970-01-01
                  • 2012-09-26
                  • 2012-03-11
                  • 2016-03-03
                  • 1970-01-01
                  • 2019-12-18
                  • 2010-11-27
                  相关资源
                  最近更新 更多