Java的addExact方法在赋值给变量时不会检测整数溢出。

huangapple go评论80阅读模式
英文:

Java addExact method does not detect Integer Overflow when assigned to a variable

问题

我有以下的 try 块来检测整数溢出。

try {
    Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);
} catch(ArithmeticException ae) {
    return 0;
}

好的,所以如果我按原样运行上面的代码,会像预期的那样引发一个 ArithmeticException 异常。然而,如果我想将 addExact 的结果赋值给一个整数变量,溢出就永远不会被检测到。

try {
    reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);
} catch(ArithmeticException ae) {
    return 0;
}

有人可以告诉我为什么在赋值给变量时没有捕获到异常吗?是因为赋值过程本身成功,所以没有抛出异常吗?

public static int reverse(int x) {
    int number = Math.abs(x);
    if(number == 0) return number;

    int numberOfDigits = (int) Math.log10(number) + 1;
        
    int reversedNumber = 0;
    for(int i = numberOfDigits - 1; i >= 0; i--) {
        try {
            reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);
        } catch(ArithmeticException ae) {
            return 0;
        }
        number /= 10;
    }

    return x < 0 ? -reversedNumber : reversedNumber;
}

对于输入 1534236469答案应该是 0
英文:

I have the following try block to detect Integer overflow.

    try {

        Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

    } catch(ArithmeticException ae) {

        return 0;

    }

Okay, so if i run the above code as is, it causes an ArithmeticException as expected. However, if I want to assign the result of addExact to an integer variable, the over flow is never detected.

    try {

        reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

    } catch(ArithmeticException ae) {

        return 0;

    }

Can someone tell me why the exception isn't caught upon assignment to a variable? Is it because the assignment process is itself successful so no exception is thrown?

public static int reverse(int x) {

    int number = Math.abs(x);
    if(number == 0) return number;

    int numberOfDigits = (int) Math.log10(number) + 1;
    
    int reversedNumber = 0;
    for(int i = numberOfDigits - 1; i &gt;= 0; i--) {

        try {

            reversedNumber = Math.addExact((number % 10) * (int) Math.pow(10, i), reversedNumber);

        } catch(ArithmeticException ae) {

            return 0;

        }


        number /= 10;

    }

    return x &lt; 0 ? -reversedNumber : reversedNumber;

}

with an input of 1534236469 the answer should be 0.

答案1

得分: 3

这不关乎你是否将其赋值给一个变量。如果你不将它赋值给“reversedNumber”,你的方法对于输入的1534236469是正确返回0的,但原因是错误的。对于1534236469,无论如何addExact都不会抛出异常。

这个“加法”并没有溢出,这就是为什么addExact不会抛出异常的原因。但是(number % 10) * (int) Math.pow(10, i)的乘法是会溢出的。在循环的第一次迭代中,你在计算9 * 1000000,这超出了“int”的范围。

addExact仅检查你传递给它的两个参数相加是否溢出。它不会在计算这两个参数本身的过程中检查溢出。

你需要使用multiplyExact

int powerOf10 = (int) Math.pow(10, i);
int digit = (number % 10);
reversedNumber = Math.addExact(Math.multiplyExact(digit, powerOf10), reversedNumber);
英文:

It's not about whether you assign it to a variable or not. Your method correctly returns 0 for the input 1534236469 for the wrong reason, if you don't assign it to reversedNumber. For 1534236469, addExact does not throw an exception either way.

The addition is not overflowing, which is why addExact does not throw an exception. But the multiplication of (number % 10) * (int) Math.pow(10, i) is overflowing. In the first iteration of the loop, you are multiplying 9 * 1000000, which is out of the range of int.

addExact only checks the overflow of the addition of the two arguments you pass to it. It does not check the overflow during the evaluation of the two arguments themselves.

You need to use multiplyExact:

int powerOf10 = (int) Math.pow(10, i);
int digit = (number % 10);
reversedNumber = Math.addExact(Math.multiplyExact(digit, powerOf10), reversedNumber);]

huangapple
  • 本文由 发表于 2020年6月29日 11:06:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/62630621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定