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