Java 为什么Integer.MIN_值的绝对值等于Integer.MIN_值
在java中,当我说Java 为什么Integer.MIN_值的绝对值等于Integer.MIN_值,java,integer,Java,Integer,在java中,当我说Integer I=Math.abs(Integer.MIN\u VALUE)时。我得到与答案相同的值,这意味着I包含Integer.MIN\u值。 我也在C++中验证了同样的用法。 为什么会有这种行为?请阅读Joshua Bloch的《有效Java》 我找到了这个问题的答案,下面是解释: 计算机使用二进制算术,java中的Math.abs逻辑或任何语言中的absolute函数如下所示: if(num >= 0) return num; else ret
Integer I=Math.abs(Integer.MIN\u VALUE)
时。我得到与答案相同的值,这意味着I
包含Integer.MIN\u值
。
我也在C++中验证了同样的用法。
为什么会有这种行为?请阅读Joshua Bloch的《有效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)的2的补码是001(1)
,类似地110(-2)的2的补码是010(2)
,101(-3)的2的补码是011(3)
,而100(-4)的2的补码是100(-4)
,并且我们可以看到-4是使用3位可能的最小负数
这就是为什么
整数的绝对值。最小值是整数。最小值这是因为两个补数系统的工作方式<代码>整数。最小值
对应于0x8000000。求反的标准方法是取其1的补码(在本例中为0x7FFFFFFF)并加1,在本例中,它将溢出回0x8000000。您可能期望Integer.MIN\u value
的绝对值为Integer.MAX\u value+1
,但该值超出了原语int
的大小。而Integer.MAX\u值+1
又是Integer.MIN\u值。仅此而已。这种效应的根本原因是内在的不对称性。32位模式的数量是偶数。其中一个模式用于零。这会留下奇数个非零值。正值和负值的数量不能相等,因为它们的总和是奇数
在用于Java整数的2的补码表示法中,负数的数目比正数的数目大一个。除Integer.MIN_值外的每个负数都对应一个正数,该正数既是其负数也是其绝对值。Integer.MIN_值被保留,没有相应的正int.Math.abs和否定映射到它自身。Math.abs(int)文档说,如果参数为负,则返回参数的否定。JLS 15.15.4。一元减号运算符表示所有整数值x,-x等于(~x)+1
-Integer.MIN\u VALUE=~Integer.MIN\u VALUE+1=~0x8000000+1=0x7FFFFFFF+1=0x8000000=Integer.MIN\u VALUE
为什么会有这种行为
这是所有现代计算机所使用的表示选择的数学结果
这里有一个非正式的证据来证明为什么必须这样
具有N位的有符号二进制数表示有2N个可能值;i、 元素数为偶数的一组整数
从集合中删除零。集合现在有奇数个元素
现在删除{n,-n}
形式的所有数字对。每次删除一对数字时,集合中仍然包含奇数个元素
现在剩下的一个集合包含奇数个整数,n
在集合中,但-n
不在集合中。由于设置的大小为奇数,因此不能为空;i、 e.至少有一个数字具有此属性
在Java指定的表示中(实际上使用了所有其他实用语言),整数类型有2N-1个负值和2N-1-1个大于零的值。具有奇怪属性的值是MIN\u value
。这种表示称为
严格来说,整数表示不必有这种异常:
- 可以有两个零(-0和+0);e、 g.或陈述。(这使证明的第2步无效:现在需要删除2个零。)
- 可以排除-2N-1;i、 使其成为非法值。(这使证明的步骤1无效:初始集现在有奇数个值。)
- 可以指定整数算术,以便(例如)对MIN_值求反会引发异常。例如,
Math.abs(Integer.MIN\u VALUE)
将引发异常
然而,所有这些都会对性能产生重大影响,特别是因为现代计算机硬件本身只支持二补运算。他们在编写可靠的整数代码方面也有问题…s/compaind/complement/g。java使用两个“S”补码,但C++实现不需要使用两个“S”补码。如果它使用了一个“-补码,上面的内容将不适用。@ChrisJester-Young感谢您建议编辑。s/赞美/补充/g。虽然为时已晚,但它是值得的。为什么要用Integer.MIN_值加1而不是其他整数呢?@dharam这不是一种特殊处理,我试图解释Integer.MIN_值的绝对值大于可以通过int类型重新呈现的最大整数。@dharam In