[英]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.