[英]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_VALUE
是Integer.MIN_VALUE
。
存在固有的不对称性是这种效应的根本原因。 32位位模式的数量是偶数。 其中一种模式用于零。 这留下了奇数个非零值。 正值的数量和负值的数量不能相等,因为它们的总和是奇数。
在用于Java整数的2的补码表示中,负数的数量比正数的数量大1。 除Integer.MIN_VALUE之外的每个负数对应于正数,该正数既是其否定值,也是其绝对值。 Integer.MIN_VALUE保留,没有相应的正int。 Math.abs和否定将它映射到自身。
为什么会这样?
它是所有现代计算机中使用的表示选择的数学结果。
这就是为什么它是这样一个非正式的证据。
具有N位的带符号二进制数表示具有2 N个可能值; 即具有偶数个元素的集合整数。
从集合中删除零。 该集合现在具有奇数个元素。
现在,删除所有对形式的数字{n, -n}
每次我们删除一对数字时,该集合仍然包含奇数个元素。
我们现在留下一个包含奇数个整数的集合,其中n
在集合中,但-n
不在集合中。 由于设定的大小是奇数,因此不能为空; 即至少有一个具有此属性的数字。
在Java指定的表示中(实际上使用了所有其他实用语言),整数类型具有2个N-1个负值和2 个大于零的N-1 - 1个值。 具有奇怪属性的值是MIN_VALUE
。 这种表示称为二进制补码 。
严格来说,整数表示不必具有此异常:
可以排除-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.