应使用 low + (high - low) / 2 替代 (low + high) / 2,避免有符号整型溢出导致 mid 为负、搜索错乱或死循环;Java/C/C++ 等需特别防范,Python 虽无溢出也建议统一写法。
直接用 (low + high) / 2 计算中间索引,在 c/c++、java、c# 等有符号整型固定宽度的语言中,确实可能触发整数溢出——不是逻辑错误,而是底层二进制加法越界导致结果突变为负数,进而让整个搜索范围错乱甚至死循环。排查这类 bug 的关键,是识别“看似正常却在边界场景下崩溃”的行为。
观察搜索行为是否异常偏移
当输入数组极大(例如长度接近 Integer.MAX_VALUE),或搜索范围长期集中在高位索引区域时,注意以下信号:
- mid 值突然变成一个很大的负数(如 -1073741824),而 low 和 high 都是正数且合理
- 搜索过程反复在同一个区间打转,比如
low = 1073741823, high = 1073741824,但 mid 却算出负值,导致low或high被错误更新 - 本该命中目标却返回 -1,或抛出
ArrayIndexOutOfBoundsException(因用负数当索引)
复现溢出的最小测试用例
不用等生产环境出问题,主动构造高风险输入验证逻辑健壮性:
- 在 Java 中尝试:
low = 0; high = Integer.MAX_VALUE - 1;,执行一次mid = (low + high) / 2—— 正常应得约 1073741823,但若后续某步使low变为Integer.MAX_VALUE - 2,再与high = Integer.MAX_VALUE - 1相加,就必然溢出 - C/C++ 中可直接用
INT_MAX构造类似 case;Python 不会溢出,但为跨语言一致性,也建议统一用防溢出写法
检查 mid 计算是否被编译器/解释器优化误导
有些开发者误以为 “除法自动向下取整” 或 “JVM 会兜底”,其实不会:
-
(low + high) / 2先做加法,溢出后得到错误的中间值,再除以 2,结果毫无意义 - 位运算
(low + high) >> 1同样危险——加法先溢出,右移只是对错误结果做位操作 - 真正安全的是绕开加法:用
low + (high - low) / 2或无符号右移(low + (long)high) >> 1(需类型提升)
静态扫描与代码规范强制
人工 review 容易遗漏,建议纳入工程实践:
- 在 CI 流程中加入 lint 规则(如 Java 的
SpotBugs检测ICAST_INTEGER_MULTIPLY_CAST_TO_LONG类似风险) - 团队编码规范明确禁止
(low + high) / 2,统一要求使用low + (high - low) / 2 - 单元测试覆盖
low和high接近类型上限的用例(如Integer.MAX_VALUE - 100和Integer.MAX_VALUE)

















