[英]What is the difference between compare() and compareUnsigned() in Java
我知道compare(int a, int b)
如果a > b
返回 1,如果a == b
返回 0,-1 a < b
。 當我面對compareUnsigned()
時,我不知道它是如何工作的。 我已經對 IntelliJ Idea 中關於此方法的此方法的文檔進行了一些研究,並找出了如何做
compareUnsigned()
靜態方法在接收整數 x 和 y 作為參數后工作:
public static int compareUnsigned(int x, int y) {
return compare(x + -2147483648, y + -2147483648);
}
誰能解釋一下與compare(int a, int b)
方法相比,此方法是否有任何特殊功能以及它是如何工作的。
這可能不是一個完美的答案,因為我不太確定當您調用 Integer.compareUnsigned(-1, 2) 時 Java 到底做了什么,但我會嘗試解釋我認為正在發生的事情。
首先我要指出的是
Integer.compareUnsigned(-1, 2)
返回1表示-1大於2 。 為什么我會在這里解釋。
Integer.compare(int, int)
就像您手動執行的那樣進行正常的整數比較。
在解釋 Integer.compareUnsigned(int, int) 之前,讓我們先看看有符號和無符號整數是什么。
Java 使用 32 位來存儲整數。 這意味着一個int
變量最多可以表示 2^32 個數字。 值的范圍將取決於所使用的整數表示法。
對於無符號整數,這將是 0 到 4,294,967,295 (2^32 − 1)。 這意味着 32 位系統上的最小無符號整數為 0,而 32 位系統上的最大無符號整數為 4,294,967,295。
對於有符號整數,將是 −2,147,483,648 (−2^31) 到 2,147,483,647 (2^31 − 1),表示為二進制補碼。
現在您看到 -1 在無符號表示中不存在。 在像 C 這樣具有無符號類型的語言中。 當你做 unsigned int x = -1; 在我的基於 Intel 的 64 位 Mac 上(我在這里是特定的,因為與 Java 不同,C 有點特定於實現),-1 被轉換為 4294967295,這是無符號整數的最大值。 -2 轉換為 4294967294 僅比無符號整數的最大值小 1。
#include <stdio.h>
int main() {
unsigned int x = -1;
unsigned int y = -2;
printf("x = %u\ny = %u\n", x, y);
return 0;
}
輸出
x = 4294967295
y = 4294967294
現在您看到負數在 C 中被轉換為帶符號的等價數。我不太確定這是如何完成的,但您可以查看此答案以進一步了解它https://stackoverflow.com/a/7152835 /4801462
因此,當您調用 Integer.compareUnsigned(-1, 2) 時,我的猜測是 Java 試圖將 -1 視為無符號整數。 這意味着 -1 將在比較完成之前轉換為非負值。 這是如何完成的我不太確定,因為文檔沒有說明,但你不應該指望它。 我為什么這么說?
Java沒有無符號類型,Java 中的int能夠保存正最大值 2,147,483,647 (2^31 − 1),這大約是無符號 int 最大值的一半。 因此,即使 -1 被視為無符號 int,它也可能會溢出 int 變量,這將導致 -1 的無符號版本以外的其他內容存儲在該變量中。
我的建議是,除非你 100% 完成你正在做的事情,否則請避免使用該方法。
注意事項
更有經驗的人可能會有更好的答案。 我從來沒有用過這種方法。 我只是應用我 4 年前從大學學到的知識來回答這個問題。
參考:
https://en.wikipedia.org/wiki/32 位
編輯
當您在 Integer.compareUnsigned(int, int) 中發送 -1 時,Java 可能會做的是獲取 -1 的無符號等效項並將其存儲在long
中,因為它可能會溢出int
然后進行比較。
signed int
值的范圍是 -2^31 到 2^31-1。 值 0 在中間。
unsigned int
的范圍是 0 到 2^32-1,其中 0 是最小的數字。
兩者都有 2^32 個值,區別在於哪個表示是最低的和最高的。
通過將所有值移動 -2^31,(例如 0,最低無符號 ==> -2^31,最低有符號)無符號范圍被移動到有符號范圍並且比較像<
<=
>=
>
==
!=
所有對未簽名的工作都與對已簽名的一樣。
為此,您應該了解有符號整數和無符號整數之間的區別,這是您在研究 C 和 C++ 中的數據類型時遇到的一個基本概念,但在 Java 中幾乎不使用它。 無符號整數是編譯器將整數視為始終為正數的整數。 例如,10 的二進制代碼是 01010。(5 位)-10 的二進制代碼將是 11010,
第一位代表值的符號。 0 表示正數,1 表示負數。
unsigned 的作用是把 -10 讀成 26(沒有符號位的 11010 就是 26 的二進制碼)
那么 compareUnsigned(int x, int y) 所做的就是將 x 和 y 讀取為無符號整數,然后將答案作為 Integer 中的一般比較函數返回。
好的,所以我已經深入研究了這兩種方法的來源。 這是 java 文檔必須說明的內容。
/**
* Compares two {@code long} values numerically treating the values
* as unsigned.
*
* @param x the first {@code long} to compare
* @param y the second {@code long} to compare
* @return the value {@code 0} if {@code x == y}; a value less
* than {@code 0} if {@code x < y} as unsigned values; and
* a value greater than {@code 0} if {@code x > y} as
* unsigned values
* @since 1.8
*/
所以它將值視為無符號,然后比較它們。 這是它的代碼。
public static int compareUnsigned(long x, long y) {
return compare(x + MIN_VALUE, y + MIN_VALUE);
}
如果我們看一下這篇SO 帖子,我們可以看到無符號值的實際含義
引用 Pubby 在我剛剛在上面鏈接的 SO 帖子中所說的話,我們可以理解
有符號整數可以表示負數; 未簽名的不能。
如果有符號整數溢出,則它們具有未定義的行為,而無符號整數使用模數環繞。
有關更多信息,您應該在此處查看他的回答
也許我已經解決了這個問題。 signed int 值的范圍是 -2^31 到 2^31-1。 unsigned int 值的范圍是 0 到 2^32-1。 它們的區別在於最高位是否為符號。
請注意, Java 沒有無符號類型。
我們可以通過Integer.toBinaryString(i)
看到i的二進制補碼表示,左邊的零位可以省略。
該范圍可以分為兩個區間,即[-2^31,-1]和[0,2^31-1]。 任何區間都可以由另一個區間加上 Integer.MIN_VALUE 生成。 示例如下表所示。
第一列是原始值,第二列是它的二進制補碼表示。 第三列是原值加上Integer.MIN_VALUE的值,第四列是它的補碼表示。 第二列和第四列都是32位,只是0-1和0-0之間的間距不同。
補碼運算有兩條規則:
使用補碼,可以將符號位和其他位統一處理。
兩個互補數相加時,如果最高位(符號位)有進位,則舍去進位。
綜上所述,Java使用signed int來解決unsigned比較。
原值 | 補碼 | 結果值 | 補碼 |
---|---|---|---|
-2^31 | 10000000000000000000000000000000 | 0 | 0000000000000000000000000000000 |
-1 | 11111111111111111111111111111111 | 2^31-1 | 01111111111111111111111111111111 |
... | ... | ... | ... |
0 | 00000000000000000000000000000000 | -2^31 | 10000000000000000000000000000000 |
2^31-1 | 01111111111111111111111111111111 | -1 | 11111111111111111111111111111111 |
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.