java求绝对值的一个小bug

前一段时间泡博客的时候看到了一个有趣的现象,在此记录下来。

eclipse中输入下面的语句,猜猜结果会是什么?

1
System.out.println(Math.abs(-2147483648));

出人意料!结果还是-2147483648!
这是为什么呢?那就要从绝对值源码来探索了。Math.abs()的实现如下:

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

可以看出,仅仅是最简单的判断取反。那对-2147483648意味着什么呢?
-2147483648其实是Integer.MIN_VALUE,即int能表示的最小值,二进制表示为1000,0000,0000,0000,0000,0000,0000,0000。而取反操作其实就是反码加1,而这个值的反码为111…,加1后又变为其本身。这个问题的本质原因就是int类型的大小限制,与sun公司没有考虑到这一个下界所共同导致的。
那么怎样解决这个问题呢?因为int类型的限制,根本就不可能表示2147483648这个数字,将这个数字转换为long类型才可以正常使用:

1
System.out.println(Math.abs(-2147483648L));

那么到达long类型的上界又怎么办呢?此时可以借助BigInteger这个类来实现我们的需求————而BigInteger类型是解决大数问题最好选择。