use*_*319 77 java absolute-value
这段代码:
System.out.println(Math.abs(Integer.MIN_VALUE));
Run Code Online (Sandbox Code Playgroud)
返回 -2147483648
它不应该返回绝对值2147483648吗?
ber*_*lus 33
你指出的行为确实是违反直觉的.但是,此行为是由javadocMath.abs(int)指定的行为:
如果参数不是负数,则返回参数.如果参数为负数,则返回参数的否定.
也就是说,Math.abs(int)应该表现得像以下Java代码:
public static int abs(int x){
if (x >= 0) {
return x;
}
return -x;
}
Run Code Online (Sandbox Code Playgroud)
也就是说,在否定的情况下,-x.
根据JLS第15.15.4节,-x它等于(~x)+1,其中~是按位补码运算符.
要检查这听起来是否正确,让我们以-1为例.
整数值-1可以0xFFFFFFFF在Java中以十六进制表示(使用println或任何其他方法检查).以-(-1)这样得到:
-(-1) = (~(0xFFFFFFFF)) + 1 = 0x00000000 + 1 = 0x00000001 = 1
Run Code Online (Sandbox Code Playgroud)
所以,它的工作原理.
让我们现在尝试一下Integer.MIN_VALUE.知道最低整数可以表示0x80000000,即第一位设置为1而其余31位设置为0,我们有:
-(Integer.MIN_VALUE) = (~(0x80000000)) + 1 = 0x7FFFFFFF + 1
= 0x80000000 = Integer.MIN_VALUE
Run Code Online (Sandbox Code Playgroud)
这就是Math.abs(Integer.MIN_VALUE)回报的原因Integer.MIN_VALUE.还要注意的0x7FFFFFFF是Integer.MAX_VALUE.
也就是说,我们怎样才能避免将来由于这种反直觉的回报价值而产生的问题呢?
正如@Bombe指出的那样,我们可以把它们投射int到long之前.但是,我们必须要么
ints,这是行不通的,因为
Integer.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE).longs以某种方式希望我们永远不会Math.abs(long)用相等的值来调用Long.MIN_VALUE,因为我们也有Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE.我们可以BigInteger在任何地方使用s,因为BigInteger.abs()确实总能返回正值.这是一个很好的选择,比操作原始整数类型要慢一点.
我们可以编写自己的包装器Math.abs(int),如下所示:
/**
* Fail-fast wrapper for {@link Math#abs(int)}
* @param x
* @return the absolute value of x
* @throws ArithmeticException when a negative value would have been returned by {@link Math#abs(int)}
*/
public static int abs(int x) throws ArithmeticException {
if (x == Integer.MIN_VALUE) {
// fail instead of returning Integer.MAX_VALUE
// to prevent the occurrence of incorrect results in later computations
throw new ArithmeticException("Math.abs(Integer.MIN_VALUE)");
}
return Math.abs(x);
}
Run Code Online (Sandbox Code Playgroud)
int positive = value & Integer.MAX_VALUE基本上溢出Integer.MAX_VALUE来0代替Integer.MIN_VALUE)最后一点,这个问题似乎已经有一段时间了.有关相应的findbugs规则,请参阅此条目.
要查看您期望的结果,请转换Integer.MIN_VALUE为long:
System.out.println(Math.abs((long) Integer.MIN_VALUE));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24665 次 |
| 最近记录: |