我写了一个方法来反转有符号整数。如果反转的数字不在 INT_MAX 和 INT_MIN 范围内,它将返回 0。它适用于除 -2147483648 之外的几乎所有情况 在调试时,我发现代码无法正确处理 -2147483648 的符号,而它适用于不同的签名输入。
有人可以解释为什么 Math.abs(x) 对于这个测试用例不能正常工作吗? 下面给出方法。
public int reverse(int x) {
boolean flag = (x>0);
x = Math.abs(x);
String num = new StringBuilder(Integer.toString(x)).reverse().toString();
long temp = Long.parseLong(num);
if(!flag){
temp = -temp;
}
if((Integer.MAX_VALUE < temp) || ( temp < Integer.MIN_VALUE)){
return 0;
}
return (int) temp;
}
Integer.MIN_VALUE
= -2^31
= -2147483648
到 Integer.MAX_VALUE
= 2^31-1
= 2147483647
。
在执行
-2147483648
时,没有与Math.abs(x)
相反的正值可以在Java的整数范围内正确表示。因此,当参数 -2147483648
传递给该方法时,结果会溢出回最小可表示整数,即再次 -2147483648
,因为当该参数为负数时,Math.abs()
只是简单地否定给定参数。因此,在你的行中
String num = new StringBuilder(Integer.toString(x)).reverse().toString();
您实际上将
-2147483648
反转为 8463847412-
,这会导致 NumberFormatException
在执行时被抛出
long temp = Long.parseLong(num);
因为
8463847412-
不是 long
。
Math.absExact
,而不是 Math.abs
。
您的线路:
x = Math.abs(x);
Integer.MIN_VALUE
-2,147,483,648 无效,因为正确答案 2,147,483,648 超出了 int
2,147,483,647 的 Integer.MAX_VALUE
上限 1。您遇到整数溢出。
您可以在代码中捕获整数溢出,而且您应该这么做。
👉🏽养成使用
…exact
课程中的Math
方法的习惯。
ArithmeticException
在这种情况下,请调用
Math.absExact
而不是 Math.abs
。该方法在整数溢出时抛出 ArithmeticException
。
Math.absExact( input )
完整示例:
int input = Integer.MIN_VALUE;
int result = -1;
try
{
result = Math.absExact( input );
System.out.println( "result = " + result );
} catch ( ArithmeticException e )
{
System.out.println( "WHOOPS - Integer overflow on getting absolute value of " + input );
}
同样,使用
Math.addExact
、Math.multiplyExact
、Math.ceilDivExact
、Math.decrementExact
等。