3 * 1000000000 作为int溢出,但是变量是long long。为什么?

3 * 1000000000 overflows as an int, but the variable is long long. Why?

我有一个简单的 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。提前致谢。

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

上进行的

整数常量默认为 ints.

1000000000

可以装进 int。所以,这个常量被解析为 int。但是乘以 3 溢出 int.

10000000000

这对于一个整数来说太大了,所以这个常量是一个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

编译器看到了这个

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

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

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

示例:int * double -> double

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

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

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