3 * 1000000000 溢出为 int,但变量很长.为什么

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

本文关键字:变量 为什么 int 1000000000 溢出      更新时间:2023-10-16

我有一个简单的 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

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

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

默认情况下,整数常量int s。

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中的事实不会改变您在第二行代码中相乘的数字不是 long long s 的事实,因此它们溢出了。在第三行代码中,常量是一个long long,所以乘法是在long long s上执行的。

编译器看到了这个

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修复它。

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

示例:int * double -> double

您的计划具有:长整 长整 = 整 * 整。

正在发生的事情是 int * int 的结果是一个 int。因此,您的程序将首先乘法,并以有符号整数(最大值 ~= 20 亿,因此它换行为负数(处理结果。然后,这个负值存储在长整型中。

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