Yihui’s Blog

不能使用大于小于号,如何判断两个正整数大小?

日期: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 可能溢出导致符号错误。
  • 位运算答案可读性差,生产代码应优先清晰和可测试。

面试官追问

  1. 为什么 x | -x 能判断非零?
  2. 直接用 a-b 有什么溢出问题?
  3. 如果输入是 long 怎么办?

面试官追问参考答案

1. 为什么 x | -x 能判断非零?

x 非零时,x 和其二进制补码负数中至少一个为负,最高位至少一个是 1,按位或后最高位为 1;x 为零时两者都为零。因此无符号右移最高位可得到非零标记。

2. 直接用 a-b 有什么溢出问题?

对一般 int,最大正数减负数可能绕成负数,最小负数减正数可能绕成正数,符号不再代表大小。先提升为 long 再相减可覆盖所有 int 差值。

3. 如果输入是 long 怎么办?

long 相减仍可能溢出,不能直接依赖差值符号。可先比较符号位:异号时正数更大;同号再用无符号减法/借位算法,或生产代码直接使用 Long.compare。

学习清单

  • 理解补码、符号位和无符号右移。
  • 能主动指出整数溢出边界。
Maintained by · YihuiEdit on GitHub

Keep reading

View all posts