MENU

Java杂记(八)坑:Math.abs 方法边界问题

June 27, 2018 • Code

前言:在使用 Java API Math.abs() 取绝对值时,需特别注意边界值问题。

源码及分析

Java 中 Math.abs() 返回一个数的绝对值,但是取边界值(即最大或最小值)时,可能会出现负数的情况

源码(以 int 为栗)

public static int abs(int a) {
        return (a < 0) ? -a : a;
}

方法的实现本身并不复制,即负数简单取反。但在计算机中数是以补码形式存在,意味着负数范围比正数多 1,所以当传入数为该基本数据类型最小值时会溢出,返回一个负数。

上述栗子中,int 的范围为 -2147483648 ~ 2147483647,所以当传入的数为 Integer.MIN_VALUE 的时候会溢出。

其实在 JavaDoc 中也早有说明:

Returns the absolute value of an int value. 
If the argument is not negative, the argument is returned. 
If the argument is negative, the negation of the argument is returned.
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.

其它数据类型特例

long

Note that if the argument is equal to the value of Long.MIN_VALUE, the most negative representable long value, the result is that same value, which is negative.

float

Special cases:
If the argument is positive zero or negative zero, the result is positive zero.
If the argument is infinite, the result is positive infinity.
If the argument is NaN, the result is NaN.
In other words, the result is the same as the value of the expression:
    
Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))

double

Special cases:
If the argument is positive zero or negative zero, the result is positive zero.
If the argument is infinite, the result is positive infinity.
If the argument is NaN, the result is NaN.
In other words, the result is the same as the value of the expression:
    
Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)

扩展:原、反、补码图

小结

在使用或编写涉及数字正负值的程序或算法需特别注意边界值问题,以免出现意想不到的情况。

Last Modified: July 5, 2018
Archives QR Code
QR Code for this page
Tipping QR Code