代码片段
int x = < an integer value >; System.out.println(x*x);
显示
-131071
。以下哪项是x
的可能值?
显然答案是2^16 - 1
。
我甚至不知道这是一个答案选择。如果没有计算器,我该如何解决这个问题?
声明
System.out.println(Integer.MAX_VALUE);
打印
2147483647
,等于2^31 - 1
。什么是 以下声明打印?System.out.println(Integer.MAX_VALUE + 2);
答案是-2137483546
。我很困惑,不应该因为我们超出界限而导致ArithmeticException吗?
我不是要问你这些问题吗?如果你能给我推理而不仅仅是答案(我已经有了)?我只是对ints
在最大值附近操纵感到困惑。
答案 0 :(得分:1)
我首先以更有用的形式编写-131071:0xfffe0001
现在只需解决x * x == 0xfffe0001
。很明显x
是奇怪的,否则它的方块永远不会是奇数。这个论点可以更进一步:模2 16 得到x * x = 1
,所以x
是1或-1模2 16 ,因为那些是只有1的平方根。
所以低16位只有两种选择,那么高16位呢?
首先让我们尝试0xffff(也就是-1模2 16 )来获得低16位。那(即高16位为零)立即结果起作用,但“通过计算”是一个无聊的原因。这是一个更好的理由:原始数字是2 32 -2 17 +1(从其十六进制表示中很容易看到),这些因素成为(2 16 -1) 2 ,只做常见的“反方形”,所以2 32 是 2 ,-2 17 = 2ab且1 = b 2 。
但这只是一种可能性,还有更多:
还记得底部的16位是多少?这也提供了两种可能性:
不应该导致ArithmeticException,因为我们超出了界限吗?
不是使用标准包装算法,而是查看Math.multiplyExact
和朋友。在普通的操作符中,/
和%
可以抛出,其他的操作非常安全。