为什么Integer.MIN_VALUE的绝对值等于Integer.MIN_VALUE

时间:2013-09-02 04:00:35

标签: java integer

在java中我说Integer i = Math.abs(Integer.MIN_VALUE)。我得到与答案相同的值,这意味着i包含Integer.MIN_VALUE。 我在C ++中也验证了相同的内容。

为什么会出现这种情况?

6 个答案:

答案 0 :(得分:12)

在Joshua Bloch的Effective Java中阅读。

我找到了这个问题的答案,这里是解释: 计算机使用二进制算术,java中的Math.abs逻辑或任何语言的absolute函数如下所示:

if(num >= 0)
    return num;
else
    return (2's complement of the num);

注意:如何找到2的补码

对于给定的数字,我们首先发现它是1的补码,然后加1。对于例如 考虑我们的号码是10101 1的补码= 01010 2的补码= 01011(在1的补码中加1)

现在,为了使其简单明了,我们假设我们的整数(带符号)大小是3位,那么这里是可以使用四位产生的数字列表:

000 --> 0 (0)
001 --> 1 (1)
010 --> 2 (2)
011 --> 3 (3) 
100 --> 4 (-4)
101 --> 5 (-3)
110 --> 6 (-2)
111 --> 7 (-1)

现在这已经签名,这意味着一半的数字是负数而另一半是正数(负数是第一位1的数字)。让我们从000开始,尝试找到它的负数,它将是000的两个补码。

2's complement of `000` = 1 + `111` = `000`
2's complement of `001` = 1 + `110` = `111`
2's complement of `010` = 1 + `101` = `110`
2's complement of `011` = 1 + `100` = `101`
2's complement of `100` = 1 + `011` = `100`
2's complement of `101` = 1 + `010` = `011`
2's complement of `110` = 1 + `001` = `010`  
2's complement of `111` = 1 + `000` = `001`

从上面的演示中,我们发现111(-1) is 001(1)的2的补码,110(-2) is 010(2)的2的补码,101(-3) is 011(3)的2的补码和100(-4) is 100(-4)的2的补码可以看出-4是使用3位可能的最小负数。

这就是Integer.MIN_VALUE的绝对值为Integer.MIN_VALUE的原因。

答案 1 :(得分:5)

存在固有的不对称性,这是造成这种影响的根本原因。 32位位模式的数量是偶数。其中一种模式用于零。这留下了奇数个非零值。正值的数量和负值的数量不能相等,因为它们的总和是奇数。

在用于Java整数的2的补码表示中,负数的数量比正数的数量大1。除Integer.MIN_VALUE之外的每个负数对应于正数,该正数既是其否定值,也是其绝对值。 Integer.MIN_VALUE保留,没有相应的正int。 Math.abs和否定将它映射到自身。

答案 2 :(得分:4)

  

为什么会这样?

这是所有现代计算机中使用的表示选择的数学结果。

这是一个非正式的证明,为什么 就是这样。

  1. 带有N位的带符号二进制数表示具有2个 N 可能的值;即具有偶数元素的集合整数。

  2. 从集合中删除零。该集合现在具有奇数个元素。

  3. 现在删除{n, -n}形式的所有。每次我们删除一对数字时, 集都包含奇数个元素。

  4. 我们现在留下一个包含奇数个整数的集合,n在集合中,但-n不在集合中。由于设定的大小是奇数,因此不能为空;即具有此属性的至少一个号码。

  5. 在Java指定的表示中(实际上使用了所有其他实用语言),整数类型具有2个 N-1 负值和2个 N-1 - 1个值大于零。具有奇怪属性的值为MIN_VALUE。此表示称为two's complement


    严格地说,整数表示不必具有此异常:

    • 可以有两个零(-0和+0);例如signed magnitudeone's complement表示。 (这使证明的第2步无效:现在有2个零要删除。)

    • 可以排除-2 N-1 ;即使其成为非法价值。 (这使证明的第1步无效:初始集现在具有奇数个值。)

    • 可以指定整数运算,以便(例如)否定MIN_VALUE引发异常。例如,Math.abs(Integer.MIN_VALUE)会抛出异常。

    然而,所有这些都具有重要的性能影响,特别是因为现代计算机硬件本身仅支持二进制补码算法。它们在编写可靠的整数代码方面也存在问题......

答案 3 :(得分:3)

Math.abs(int)docs说如果参数为负数,则返回参数的否定。 JLS 15.15.4。一元减运算符表示对于所有整数值x,-x等于(~x)+1

-Integer.MIN_VALUE = ~Integer.MIN_VALUE + 1 = ~0x80000000 + 1 = 0x7FFFFFFF + 1 = 0x80000000 = Integer.MIN_VALUE

答案 4 :(得分:2)

您可能希望Integer.MIN_VALUE的绝对值为Integer.MAX_VALUE + 1,但此值超出原始int大小。而Integer.MAX_VALUE + 1又是Integer.MIN_VALUE。就是这样。

答案 5 :(得分:1)

这是因为二进制数系统的工作方式。 Integer.MIN_VALUE对应于0x80000000。否定它的标准方法是取其补码(在这种情况下为0x7FFFFFFF)并加1,在这种情况下它会溢出回0x80000000。