SWE · VO Coding

LinkedIn 快速幂 pow(x,n):负指数与 INT_MIN 溢出

按指数位迭代平方,把负指数取反前先扩宽整数,并核对零底数、精度和浮点边界。

题目重点:按指数位迭代平方,把负指数取反前先扩宽整数,并核对零底数、精度和浮点边界。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版返回浮点数,n 为整数;0 的负次方抛 ZeroDivisionError,任何非零底数的零次方及 0⁰ 都按 1.0。具体 0⁰ 契约题目未明确。
  • 代码语言 Python 自带无限精度整数,但文章以 32 位有符号 n 解释 INT_MIN 风险;在 Java/C++ 应先转 64 位再取负。

解题路线

  1. 基线乘 |n| 次是 O(|n|)。快速幂利用 xⁿ:若 n 的低位为 1,将当前 factor 乘入结果;每轮 factor 平方、n 右移一位,O(log |n|) 次。
  2. 负 n 先用宽整数取绝对值,求完正幂后取倒数;不能在 32 位 int 中先写 `-n`,因为 -INT_MIN 无法表示。
  3. 递归版用 n 偶数→pow(x,n/2)²、奇数→x×pow(x,(n-1)/2),深度 O(log |n|);迭代版避免调用栈并易于控制中间溢出。
  4. 真实浮点库还需规定 NaN、±∞、带符号零和 overflow/underflow;面试手写题应先确认是否需要完整 IEEE 754 语义。

手动走一遍

2⁻³:先取宽整数指数 3,二进制 11,依次乘 2 和 4 得 8,再取倒数 1/8。n=−2³¹ 时先转 64 位再取负,可得 2³¹ 这个正指数。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def fast_power(base: float, exponent: int) -> float:
    if base == 0 and exponent < 0:
        raise ZeroDivisionError("zero to negative power")
    if exponent == 0:
        return 1.0
    # In a fixed-width language, widen exponent before negating INT_MIN.
    n = -int(exponent) if exponent < 0 else int(exponent)
    factor = float(base)
    result = 1.0
    while n:
        if n & 1:
            result *= factor
        factor *= factor
        n >>= 1
    return 1.0 / result if exponent < 0 else result

复杂度

迭代 O(log |n|) 乘法、O(1) 额外空间;递归 O(log |n|) 时间和栈。浮点乘法视为 O(1) 是固定字长模型,任意精度数字需计位复杂度。训练代码 20,000 组随机值与 Python 幂运算对照。

易错点与追问

容易失分的边界

  • 在固定宽整数中先 `-INT_MIN`。
  • 负指数忘记取倒数。
  • 0 的负次方默默返回 0。
  • 把平方操作放在判断前导致低位乘错。
  • 声称与标准数学库对 NaN/∞ 完全一致却没有定义。

继续深挖

  • 递归与迭代的栈空间差别?
  • 若结果是整数模 M,如何改成模幂?
  • 大指数下浮点 underflow 如何报告?
  • 0⁰ 在产品 API 中应怎样定义?
✓已复制微信号!