Java中的compare()和compareUnsigned()有什么区别

问题描述 投票:1回答:4

我知道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)方法相比是否有任何特殊功能,以及它是如何做的。

java
4个回答
1
投票

这可能不是一个完美的答案,因为当你调用Integer.compareUnsigned(-1,2)时,我并不确切知道Java会做什么,但我会尝试解释我认为发生了什么。

首先,我想指出一点

Integer.compareUnsigned(-1, 2)

返回1表示-1大于2.为什么我会在这里解释。

Integer.compare(int, int)

只需像手动一样进行常规整数比较。

在解释Integer.compareUnsigned(int,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时;在我的64位基于Intel的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视为unsigned int。这意味着-1在比较完成之前将转换为非负值。怎么做我不太确定,因为文档没有说,但你不应该指望。我为什么这么说?

Java没有无符号类型,Java中的int能够保持正最大值2,147,483,647(2 ^ 31-1),这大约是unsigned int最大值的一半。因此,即使将-1视为unsigned int,它也可能溢出int变量,这将导致除了无符号版本-1之外的其他内容存储在该变量中。

我的建议是,避免使用该方法,除非你是100%正在做的事情。

NB

一个更有经验的人可能会有更好的答案。我从未使用过这种方法。我刚刚应用了4年前从大学学到的知识来回答这个问题。

参考文献:

https://en.wikipedia.org/wiki/32-bit

编辑

当您在Integer.compareUnsigned(int,int)中发送-1时,Java可以执行的操作是获取无符号等效值-1并将其存储在long中,因为它可能溢出int然后进行比较。


1
投票

好的,所以我已经挖掘了两种方法的来源。这就是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);
}

如果我们看看this SO帖子,我们可以看到无符号值实际意味着什么

引用Pubby在上面刚刚链接的SO帖子中所说的内容,我们可以理解

有符号整数可以表示负数;没有签名不能。

有符号整数如果溢出则具有未定义的行为,而无符号整数则使用模数进行环绕。

有关更多信息,请查看他的答案here


1
投票

签名的int值的范围是-2 ^ 31到2 ^ 31-1。值0位于中间。

无符号int的范围是0到2 ^ 32-1,0是最低的数字。

两者都有2 ^ 32个值,不同之处在于哪个表示最低和最高。

通过将所有值移动-2 ^ 31,(例如0,最低无符号==> -2 ^ 31,最低有符号),无符号范围转移到有符号范围,并且比较像< <= >= > == !=所有工作他们签名的未签名。


0
投票

为此,您应该了解有符号和无符号整数之间的区别,这是您在使用C和C ++研究数据类型时遇到的基本概念,但在java中很难使用。无符号整数是编译器将整数视为始终为正的整数。例如,二进制代码10是01010.(5位)-10的二进制代码是11010,

第一位表示值的符号。 0表示正数,1表示负数。

无符号的作用是将-10读为26(11010无符号位是二进制代码26)

那么compareUnsigned(int x,int y)的作用是将x和y作为无符号整数读取,然后将答案作为Integer中的常规比较函数返回。

© www.soinside.com 2019 - 2024. All rights reserved.