日期:2026-07-11
标签:#面试 #八股 #后端 #位运算 #场景题
一句话答案
用更宽类型做差,通过差值的符号位和是否为零得到比较结果;使用 long 可避免两个 int 相减溢出。
代码示例
// 返回 1 表示 a 较大,0 表示相等,-1 表示 b 较大
static int comparePositive(int a, int b) {
long diff = (long) a - b;
int negative = (int) ((diff >>> 63) & 1L);
int nonZero = (int) ((diff | -diff) >>> 63);
return nonZero * (1 - (negative << 1));
}
面试口语版
先把 int 转成 long 再相减,避免一般整数比较时溢出。负数的最高位是 1,可以用无符号右移取出;x | -x 在 x 非零时最高位一定为 1,所以能判断是否相等。最后组合得到 1、0、-1。题目说正整数时 int 差值本身也不会越过 int 的正负范围,但使用 long 更通用。
关键细节
- 若允许库函数,
Integer.compare(a,b)最清晰,但题目通常考位运算。 - 直接
a-b对任意 int 可能溢出导致符号错误。 - 位运算答案可读性差,生产代码应优先清晰和可测试。
面试官追问
- 为什么
x | -x能判断非零? - 直接用
a-b有什么溢出问题? - 如果输入是 long 怎么办?
面试官追问参考答案
1. 为什么 x | -x 能判断非零?
x 非零时,x 和其二进制补码负数中至少一个为负,最高位至少一个是 1,按位或后最高位为 1;x 为零时两者都为零。因此无符号右移最高位可得到非零标记。
2. 直接用 a-b 有什么溢出问题?
对一般 int,最大正数减负数可能绕成负数,最小负数减正数可能绕成正数,符号不再代表大小。先提升为 long 再相减可覆盖所有 int 差值。
3. 如果输入是 long 怎么办?
long 相减仍可能溢出,不能直接依赖差值符号。可先比较符号位:异号时正数更大;同号再用无符号减法/借位算法,或生产代码直接使用 Long.compare。
学习清单
- 理解补码、符号位和无符号右移。
- 能主动指出整数溢出边界。