7

我有一个简单的 c++ 应用程序,它执行以下计算

long long calcOne = 3 * 100000000;     // 3e8, essentially
long long calcTwo = 3 * 1000000000;    // 3e9, essentially
long long calcThree = 3 * 10000000000; // 3e10, essentially

如果我写下每个计算的结果,我会得到以下输出:

calcOne = 300000000
calcTwo = -1294967296
calcThree = 30000000000

那么为什么第二次计算会失败呢?据我所知,它在 long long 类型的范围内(calcThree 更大......)。

我在 Windows 10 上使用 Visual Studio 2015。提前致谢。

4

4 回答 4

11

默认情况下,整数常量是ints。

1000000000

这可以放入一个int. 因此,这个常量被解析为int. 但是将它乘以 3 会溢出 int。

10000000000

这对 int 来说太大了,所以这个常数是 a long long,所以结果乘法不会溢出。

解决方案:显式使用long long常量:

long long calcOne = 3 * 100000000LL;     // 3e8, essentially
long long calcTwo = 3 * 1000000000LL;    // 3e9, essentially
long long calcThree = 3 * 10000000000LL; // 3e10, essentially
于 2017-03-22T18:56:17.443 回答
2

您对结果所做的操作不会影响该结果的计算方式。因此,您将结果存储在 along long中的事实并没有改变您在第二行代码中相乘的数字不是long longs 的事实,因此它们溢出了。在第三行代码中,常数是 a long long,所以对long longs 进行乘法运算。

于 2017-03-22T18:54:46.237 回答
2

编译器看到了这个

long long calcOne = (int) 3 * (int) 100000000;     // 3e8, essentially
long long calcTwo = (int) 3 * (int) 1000000000;    // 3e9, essentially
long long calcThree = (int) 3 * (long long) 10000000000; // 3e10, essentially

因此,calcTwo右手值被推断为一种int类型,然后溢出。您将溢出视为负多头。

long long calcOne = 3LL * 100000000LL;     // 3e8, essentially
long long calcTwo = 3LL * 1000000000LL;    // 3e9, essentially
long long calcThree = 3LL * 10000000000LL; // 3e10, essentially

为避免将来出现这种情况,请明确说明静态值的类型。告诉编译器一个数字是long long用 LL 后修复它。

于 2017-03-22T18:59:41.193 回答
0

大多数编程语言按大小对数字类型进行排名。数值表达式的大小/等级/类型(通常)是表达式中排名最高的值的类型。

示例:int * double -> double

你的程序有:long long int = int * int。

发生的事情是 int * int 的结果是一个 int。所以你的程序将首先乘以一个有符号整数(最大值〜= 20亿,所以它环绕成负数)。然后,这个负值被存储在 long long int 中。

3 亿(您的第一次乘法)适合 int。那里没问题。我猜第三个工作正常,因为编译器足够聪明,知道 300 亿不适合 32 位 int 并自动给它一个 64 位 long long int。

于 2017-03-22T19:38:05.340 回答