【问题标题】:3 * 1000000000 overflows as an int, but the variable is long long. Why? [duplicate]3 * 1000000000 作为 int 溢出,但变量是 long long。为什么? [复制]
【发布时间】:2017-03-22 18:50:11
【问题描述】:

我有一个执行以下计算的简单 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。提前致谢。

【问题讨论】:

  • 整数溢出 - 您正在使用适合 int 的整数文字,并且在乘法之后它溢出 - 只有在此之后它才会转换为 long long - 您可以明确强制文字为通过附加ll 后缀将其视为long long
  • 我可以确认我在 VS2015、Windows 10、64 位版本上得到了相同的结果。
  • @Rama 同意你的观点,但这有更好的答案。将更改此问题的标题,使其对搜索更有用。

标签: c++ literals integer-overflow long-long


【解决方案1】:

整数常量默认为ints。

1000000000

这可以放入int。所以,这个常量被解析为int。但是乘以 3 会溢出 int。

10000000000

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      编译器看到了这个

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

      【讨论】:

      • @HolyBlackCat :更正。谢谢
      【解决方案4】:

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

      示例:int * double -> double

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-15
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 2022-01-04
        • 2021-05-27
        • 2020-08-20
        相关资源
        最近更新 更多