女孩和机器人一起思考

一起动脑筋 · 先看一个小故事

一个玩具计数器只有两位,99 再加 1 就装不下了。计算机的整数类型也有范围。

把过程摊开来看

沿着编号看一遍,再用自己的话讲一遍
  1. 先查范围类型最多能表示多少
  2. 估计结果乘法可能比输入大很多
  3. 选好类型计算前就用足够范围
  4. 再做检查确认输入也合法

整数类型只能表示有限的数。输入都放得下,不代表相加或相乘也放得下。

例如两个接近十万的数相乘,结果接近一百亿,常见的 32 位 int 放不下。

01为什么数字会“装不下”?

计算机用有限数量的 Bit 保存整数,所以每种整数类型能表示的范围也是有限的。

就像只有 3 位十进制数字的计数器最多只能直接显示 999,固定宽度整数也有自己的最大值和最小值。

0232 位 int 大概能有多大?

在最常见的 32 位 int 实现中,范围通常是:

-2,147,483,6482,147,483,647

但再次强调:C++ 标准不保证 int 一定是 32 位。

03有符号整数溢出会怎样?

int x = 2147483647;
x = x + 1;

如果这里的 int 最大值确实是 2147483647,那么这次加法结果超出可表示范围。

04无符号整数为什么不一样?

无符号整数有明确的模运算规则。

对于 N 位无符号整数,结果按模 2^N 计算。

unsigned int x = UINT_MAX;
x = x + 1;   // 结果回到 0

这叫回绕(wraparound),是语言定义好的行为。

05怎样减少溢出风险?

选更合适的类型

需要更大范围时使用更宽整数类型。

先估算范围

理解输入和中间结果最大可能多大。

运算前检查

必要时先判断是否会越界。

注意中间结果

最终结果能装下,中间计算也可能先溢出。

06为什么 long long 常常有用?

在信奥题中,long long 常用于需要更大整数范围的场景。

C++ 标准保证 long long 至少有 64 位的数值宽度要求,现代常见实现通常是 64 位。

long long total = 1000000000LL * 1000000000LL;

这里的 LL 让字面量参与更宽的整数运算,避免先用较小类型计算。

07中间结果为什么最容易被忽略?

int a = 100000;
int b = 100000;
long long c = a * b;

即使 clong long,右边的 a * b 仍可能先按 int 计算并溢出。

更安全的写法之一:

long long c = 1LL * a * b;

你已经知道了什么

  • 整数类型只能表示有限范围。
  • 有符号整数溢出在 C++ 中属于未定义行为。
  • 无符号整数按模 2^N 回绕。
  • 更宽类型可以扩大范围,但也要注意中间表达式的类型。
  • 信奥中 long long 很常用,但仍要学会估算范围。

本专题完成:下一专题可以继续进入“程序流程”。

轮到你来试一试

先用 int 做乘法,最后存进 long long,就一定安全吗?

想好了吗?点开看解释

不一定。乘法可能已在 int 中溢出。要让运算在足够大的类型中进行,而不只是把最终容器换大。