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 long
s.
上进行的
整数常量默认为 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 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。
我有一个简单的 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 long
s.
整数常量默认为 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 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。