为什么 Java 整数在接近 2^31-1 的值时会错误地起作用?

Why does Java integer act erroneously at values near 2^31-1?

我正在尝试编写一个 Java 程序来计算整数 x 的平方根,而不使用 Math.pow() 等内置函数。这是我尝试过的方法 -

class Solution {
    public int mySqrt(int x) {
        
        if(x==0 || x==1)
            return x;
        
        // if(x>=2147395600)
        //     return 46340;
        
        int i;
        for(i=1 ; i*i<=x ; i++) {}
        return i-1;
        
    }
}

如果没有注释部分,如果 x 在 2147395600 <= x <= 2^31-1 范围内(这是 Java 中 int 值范围的上限),我就会开始出错。例如,对于输入 x=2147395600,预期输出为 46340,但实际输出为 289398。为什么会这样?在此先感谢大家。

PS - 我知道还有其他(更好的)方法可以解决这个问题,但我真的很想知道为什么这段代码会这样。

因为 46340 * 46340 = 2147395600,当 i=46340, x=2147395600 并且你达到条件 i*i<=x 它评估为 true 因为 2147395600 = 2147395600。所以循环计数器将增加 1 和在下一次迭代中,我们将得到 i=46341 并且 i * i 将导致溢出 - 46341*46341 = -2147479015.
循环条件仍然是 true,因为 -2147479015 <= 2147395600,并且循环不会停止。
您可以将 <= 替换为 =,并检查现在可能发生的边缘情况。