![](/img/trans.png)
[英]BitSet is not working for Integer.MAX_VALUE and 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.