簡體   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