簡體   English   中英

為什么 Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

[英]why Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

是真的。

我知道 Java 中的整數是 32 位,不能超過 2 31 -1,但我不明白為什么在其MAX_VALUE加 1 會導致MIN_VALUE而不是某種異常。 沒有提到像 Ruby 那樣透明轉換為更大類型的事情。

這種行為是否在某處指定? 我可以依賴它嗎?

因為整數溢出。 當它溢出時,下一個值是Integer.MIN_VALUE 相關JLS

如果整數加法溢出,則結果是數學和的低位,以某種足夠大的二進制補碼格式表示。 如果發生溢出,則結果的符號與兩個操作數值的數學和的符號不同。

正如 JSL 第 3 版中所述,整數存儲溢出,並且沒有以任何方式指示。

內置整數運算符不以任何方式指示上溢或下溢。 如果需要空引用的拆箱轉換(第 5.1.8 節) ,則整數運算符可能會拋出NullPointerException 除此之外,唯一的整數,可以拋出異常運營商(§11)是整數除法運算/ (§15.17.2)和整數余數運算符% (§15.17.3) ,其拋出ArithmeticException如果右手操作數為零,並且遞增和遞減運算符++ (第15.15.1 節,第15.15.2 節)和-- (第15.14.3 節,第15.14.2 節),如果裝箱轉換(第5.1 節)可能會拋出OutOfMemoryError .7)是必需的,並且沒有足夠的可用內存來執行轉換。

4 位存儲中的示例:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000

您必須了解整數值如何以二進制形式表示,以及二進制加法的工作原理。 Java 使用一種稱為二進制補碼的表示,其中數字的第一位表示其符號。 每當您將 1 與位符號為 0 的最大 java Integer 相加時,它的位符號將變為 1,並且該數字變為負數。

這個鏈接解釋了更多細節: http : //www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

——

Java 語言規范在此處處理此行為: http : //docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

如果整數加法溢出,則結果是數學和的低位,以某種足夠大的二進制補碼格式表示。 如果發生溢出,則結果的符號與兩個操作數值的數學和的符號不同。

這意味着您可以依賴此行為。

在大多數處理器上,算術指令在溢出時沒有故障模式。 他們設置了一個必須檢查的標志。 這是一個額外的指令,所以可能會更慢。 為了使語言實現盡可能快,語言經常被指定為忽略錯誤並繼續。 對於 Java,行為在JLS 中指定。 對於 C,該語言沒有指定行為,但現代處理器的行為與 Java 相同。

我相信有關於(尷尬的)Java SE 8 庫的建議可以拋出溢出,以及未簽名的操作。 我相信在 DSP 世界中流行的一種行為是將值限制在最大值,因此Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [不是 Java]。

我確信未來的語言將使用任意精度整數,但暫時還不會。 需要更昂貴的編譯器設計才能快速運行。

當您越過國際日期變更線時日期發生變化的原因相同:那里存在不連續性。 它內置於二進制加法的性質中。

這是一個眾所周知的問題,與整數在二進制層表示為二進制 補碼的事實有關。 當您將二進制補碼數的最大值加 1 時,您會得到最小值。 老實說,在 java 出現之前,所有整數都是這種行為,而為 Java 語言改變這種行為會增加整數數學的開銷,並使來自其他語言的程序員感到困惑。

當您將3 (二進制11 )加到 1(二進制1 )時,您必須將所有二進制1從右側開始更改為0 (二進制0 ),直到得到 0,您應該將其更改為1 Integer.MAX_VALUE所有位置都填充了1因此只剩下0秒。

易於理解的字節示例=> 在此處輸入圖片說明

byte a=127;//max value for byte
byte b=1;

byte c=(byte) (a+b);//assigns -128
System.out.println(c);//prints -128

在這里,我們強制添加並將其轉換為字節。 那么將會發生的情況是,當我們達到 127(一個字節的最大可能值)並加上 1 時,該值從 127 翻轉(如圖所示)並變為 -128。 該值開始圍繞該類型盤旋。

整數也是如此。

此外,整數 + 整數保持整數(與字節 + 字節不同,后者被轉換為 int [除非如上所述強制轉換])。

int int1=Integer.MAX_VALUE+1;
System.out.println(int1); //prints -2147483648
System.out.println(Integer.MIN_VALUE); //prints -2147483648

//below prints 128 as converted to int as not forced with casting
System.out.println(Byte.MAX_VALUE+1);

導致溢出和雙兼容自然計數繼續“第二次循環”,我們在最右邊的位置 2147483647 和 1 后,我們出現在最左邊的位置 -2147483648,下一個遞增是 -2147483647, -2147483646, -214574836 ... 以此類推,直到最右邊,它在這個位深度上的求和機的性質。

一些例子:

int a = 2147483647;

System.out.println(a);

給:2147483647

System.out.println(a+1);

給出:-2147483648(因為溢出和符合兩個性質的計數進入“第二個循環”,我們在最右邊的位置 2147483647 和 1 后,我們出現在最左邊的位置 -2147483648,下一個增量是 -2147483648,- 2147483647、-2147483646、...等等,一次又一次地向最右邊推進,它在這個位深度上的求和機的性質)

System.out.println(2-a); 

給出:-2147483645(-2147483647+2 似乎是數學邏輯)

System.out.println(-2-a);

給出:2147483647(-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 之前答案中描述的一些循環)

System.out.println(2*a);

給出:-2(2147483647+2147483647 -> -2147483648+2147483646 又是數學邏輯)

System.out.println(4*a);

給出:-4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647) ->cord -> 最后一個答案 ->-2`

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM