为什么long long n = 2000*2000*2000*2000;溢出?

2021-12-17 00:00:00 math types literals c++ integer-overflow
long long int n = 2000*2000*2000*2000;    // overflow

long long int n = pow(2000,4);            // works
long long int n = 16000000000000;         // works

为什么第一个溢出(乘以整数文字常量以分配给 long long)?

Why does the first one overflow (multiplying integer literal constants to assign to a long long)?

它与第二个或第三个有什么不同?

What's different about it vs. the second or third ones?

推荐答案

因为 2000 是一个 int 通常是 32 位的.只需使用 2000LL.

Because 2000 is an int which is usually 32-bit. Just use 2000LL.

使用 LL 后缀代替 ll 是@AdrianMole 在评论中建议的,现在已删除.请查看他的答案.

Using LL suffix instead of ll was suggested by @AdrianMole in, now deleted, comment. Please check his answer.

默认情况下,整数文字是可以保存其值但不小于 int 的最小类型.2000 可以很容易地存储在 int 中,因为标准保证它至少是一个有效的 16 位类型.

By default, integer literals are of the smallest type that can hold their value but not smaller than int. 2000 can easily be stored in an int since the Standard guarantees it is effectively at least a 16-bit type.

算术运算符总是使用存在的较大但不小于 int 的类型调用:

Arithmetic operators are always called with the larger of the types present but not smaller than int:

  • char*char 将被提升为 operator*(int,int)->int
  • char*int 调用 operator*(int,int)->int
  • long*int 调用 operator*(long,long)->long
  • int*int 仍然调用 operator*(int,int)->int.
  • char*char will be promoted to operator*(int,int)->int
  • char*int calls operator*(int,int)->int
  • long*int calls operator*(long,long)->long
  • int*int still calls operator*(int,int)->int.

至关重要的是,类型不依赖于结果是否可以存储在推断类型中.这正是您的情况发生的问题 - 乘法是用 ints 完成的,但结果溢出,因为它仍然存储为 int.

Crucially, the type is not dependent on whether the result can be stored in the inferred type. Which is exactly the problem happening in your case - multiplication is done with ints but the result overflows as it is still stored as int.

C++ 不支持像 Haskell 那样基于目的地推断类型,因此赋值无关紧要.

C++ does not support inferring types based on their destination like Haskell does so the assignment is irrelevant.

相关文章