1是自然数中的第一个正整数,也是最小的正整数,具有单位元性质,在乘法中保持任何数不变,且是所有正整数的因数。

1 是最直接、最快的方式,前提是 <code>n 是非负整数且不越界。它比 pow(2, n) 或循环乘法快一个数量级以上,且无浮点误差。
为什么 1 就等于 $2^n$
整数在内存中以二进制存储,1 的二进制是 ...0001。左移 n 位,相当于在末尾补 n 个 0,即把 1 变成 100...0(共 n 个 0),这正好是 $2^n$ 的二进制表示。
例如:1 → <code>1000₂ → 8;1 → <code>1,完全符合数学定义。
注意:该等价关系仅对非负整数 n 成立;n 为负时行为未定义,编译器通常不报错但结果不可靠。
1 的类型与溢出风险
默认用 int 做左移,n ≥ 31 时(32 位系统)会触发有符号整数溢出,结果未定义。必须显式使用足够宽的无符号类型:
1U :支持 <code>n到 31(32 位unsigned int)1ULL :推荐,支持 <code>n到 63(64 位unsigned long long)- 若
n ≥ 64,即使1ULL也会溢出,此时需用大数库或模幂(如mod 1000000007)
错误写法:1 (<code>int 溢出)、(1 (先溢出再取模,结果错误)。
和 pow(2, n)、循环乘法对比
pow(2, n) 是浮点函数,返回 double,存在精度丢失(如 n = 53 以上无法精确表示整数),且调用开销大;循环乘法时间复杂度 $O(n)$,而 1ULL 是 $O(1)$ 硬件指令。
实操建议:
- 只在
n已知范围小(如0 ≤ n ≤ 60)且需整数结果时,无条件选1ULL - 若
n来自用户输入,务必加范围检查:if (n 63) { /* 处理错误 */ } - 嵌入式或严格常量场景下,可用
constexpr让编译期计算:constexpr auto x = 1ULL
常见误用与调试线索
现象:1 输出负数、0 或随机大数 —— 这几乎一定是类型溢出或 <code>n 超出位宽。
排查步骤:
- 打印
sizeof(int)和sizeof(unsigned long long)确认平台位宽 - 用
std::numeric_limits<unsigned long>::digits</unsigned>查最大安全n - 避免混合类型:
int a = 1; a 不如直接写 <code>1ULL - 宏定义要小心:
#define POW2(n) (1 在 <code>POW2(3+2)中会变成1 (等价于 <code>(1 ),应加括号:<code>#define POW2(n) (1ULL
真正容易被忽略的不是“怎么写”,而是“谁来保证 n 合法”——边界检查往往被跳过,直到线上遇到 n = 100 导致静默溢出或 UB。










