C++中用于表示大于2^32的整数的数据类型是什么?

13

我有一个整数变量,它可能会取大于4294967295的值。

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


1
它可能会非常大吗?因为人们正在关注64位的问题,但如果你告诉他们你正在研究天文距离或原子数量,答案很快就会变成“双精度”,忘记整数。 - jpinto3912
很好的评论!在我的情况下,它不会超过64位,但如果超过了怎么办呢?为什么在这种情况下应该使用“double”? - Igor
14个回答

14

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

double 适用于浮点数,而不是整数。


9
long long不是标准的C++数据类型。 - anon
6
根据ISO/IEC 9899:TC3 - 委员会草案 - 2007年9月7日的规定,与上一版相比,主要变化包括:long long int类型和库函数。long long int类型对象的最大值为LLONG_MAX,其值为9223372036854775807(2的63次方减1)。 - Ionut Anghelcovici
4
这是一个C99文档,不是C++。 - anon
1
@Neil: +1 我一直以为在C++中是相同的,但事实并非如此。根据《C++编程语言标准工作草案》(N2798=08-0308):有五种标准的带符号整数类型:“signed char”、“short int”、“int”、“long int”和“long long int”。在这个列表中,每种类型提供的存储空间至少与列表中前面的类型相同。 - Ionut Anghelcovici
1
请注意您引用的N2798文档是未通过的C++0x草案 - 标准C++尚未具备长长整型。 - anon
1
long long 可以在 g++ 中使用,所以如果你恰好使用它,那么没问题,并且它也将在 C++0x 中得到支持。 - lothar

13

9

我假设你的数字将适合64位。如果不是,那么你需要一个任意精度算术库,比如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位类型。但实际上,在您可能遇到的任何系统上都会支持它)。

7

在C++中,没有一种可移植的方法来完成这个操作,因为该语言没有指定整数类型的大小(除了sizeof char是1)。您需要查阅编译器文档。


5
并不完全正确。标准确实规定了每种类型的最小量级,因此间接指定了最小比特(而非字节)数。请参见https://dev59.com/TXVC5IYBdhLWcg3whBaj#271132。 - Martin York
1
自从C++11以来,引入了long longunsigned long long类型,它们保证至少有64位宽度,并且还有相应的llull字面量。此外,在cstdint头文件中还提供了int64_tint_least64_tint_fast64_tuint64_tuint_least64_tuint_fast64_t类型别名。 - user4832129

3

Don't use double, because:

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会使用一些位来识别指数,实际上会失去精度(与相同大小的整数类型相比)。 - David Rodríguez - dribeas

3

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

由于我的程序需要可移植性,我会定义自己的类型,以适应我使用的所有编译器(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

1
请注意,这不是Windows问题,而是C++标准问题 - 非Windows平台不保证支持 long long。 - anon
根据MSDN的说法,long long在VC++中等同于__int64,因此您不需要进行定义。 - sharptooth
还要注意,如果使用-pedantic编译g++,它会发出大量警告,我认为大多数C++程序都是这样的(当然应该是这样的)。 - anon
尼尔:为什么会发出警告? - Igor
因为long long不是标准的C++,它是C99的一部分,而g++支持它。使用-pedantic编译C++代码会对此发出警告。 - anon
如果你真的想走这条路,最好使用一个可移植的库(比如ACE),它可以在各种平台和操作系统上提供64位整数(ACE_INT64、ACE_UINT64)。虽然它是非标准的(会检测平台/编译器并使用自己的类型技巧),但它可以在其他系统上工作。 - David Rodríguez - dribeas

2

我使用

uint64_t

但这不是标准做法。


1
实际上,stdint.h 是 C99 的一部分。但是即使过去了10年(还记得10年前的IT行业是什么样子吗?!),许多编译器供应商仍然不愿意支持这个“新”的标准。 - lispmachine
我不知道你的工作如何,但对我而言,只有三家编译器供应商很重要,分别是微软、英特尔和GCC。这三家传统上都很擅长符合“新”的标准。SunW C++、惠普或IBM则不太行,在Windows / Linux领域中,这应该不是问题。15年前,我记得经常会遇到编译器和链接器出错。实际上,DEC花了将近两个月的时间修复一个链接器bug,以便我们能够为WindowsNT Alpha发布Pro/ENGINEER,那时候32 MB可执行文件还是闻所未闻的。 - Chris K

1
尝试使用TTMath。你只需要包含一个头文件,然后声明一个大数类型,例如:
typedef ttmath::UInt<100> BigInt;

这个程序创建了一个类型,可以容纳0到2 ^(32 * 100)-1之间的无符号整数。 然后只需在需要使用int的地方使用BigInt

当然,您可以选择任何模板参数大小。100可能有些过度了;-)

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


我在尝试使用ttmath时遇到了困难,按照您的建议使用了BigInt替换Int,但实际上我收到了这个错误信息“class BigInt has no member called ...”,您认为这是为什么呢? - wxiiir
@wxiir,你在另一篇帖子中说当你的变量名为blah时出现了“BigInt没有名为blah的成员”的错误(这不应该发生)。如果你尝试一个简单的声明,比如ttmath::UInt<100> blah = 0; blah = blah + 10;会发生什么? - HostileFork says dont trust SE

1

如果您不需要负数,无符号长整型听起来是您可以获得的最多的。


1

目前许多C/C++编译器都有stdint.h或inttypes.h头文件。

int_fast64_tint64_t可能是一个选项(在我看来最具可移植性)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接