Math.abs(x) 无法正常工作,具体为 -2147483648,给出 NumberFormat 异常

问题描述 投票:0回答:2

我写了一个方法来反转有符号整数。如果反转的数字不在 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;
    }
java string numberformatexception
2个回答
7
投票

在 Java 中,整数表示从

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


1
投票

tl;博士

使用

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
等。

© www.soinside.com 2019 - 2024. All rights reserved.