繁体   English   中英

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

[英]Why is absolute of Integer.MIN_VALUE equivalent to Integer.MIN_VALUE

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

为什么会这样?

请阅读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的补码111(-1) is 001(1) ,类似的110(-2) is 010(2) 2的补码110(-2) is 010(2)101(-3) is 011(3) 2的补数101(-3) is 011(3)并且2的100(-4) is 100(-4)的补码100(-4) is 100(-4) ,并且我们可以看出-4是使用3位可能的最小负数。

这就是为什么绝对的理由Integer.MIN_VALUEInteger.MIN_VALUE

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

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

为什么会这样?

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

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

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

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

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

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

在Java指定的表示中(实际上使用了所有其他实用语言),整数类型具有2个N-1个负值和2 大于零的N-1 - 1个值。 具有奇怪属性的值是MIN_VALUE 这种表示称为二进制补码


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

  • 可以有两个零(-0和+0); 例如有符号幅度一个补码表示。 (这使证明的第2步无效:现在有2个零要删除。)

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

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

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

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

您可能期望Integer.MIN_VALUE绝对值为Integer.MAX_VALUE + 1 ,但此值超出原始int大小。 并且Integer.MAX_VALUE + 1再次为Integer.MIN_VALUE 就这样。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM