簡體   English   中英

Java中的compare()和compareUnsigned()有什么區別

[英]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之間的間距不同。

補碼運算有兩條規則:

  1. 使用補碼,可以將符號位和其他位統一處理。

  2. 兩個互補數相加時,如果最高位(符號位)有進位,則舍去進位。

綜上所述,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.

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