无符号整数比较

huangapple go评论71阅读模式
英文:

Unsigned Integer Comparison

问题

我原本以为在下面的示例中,"compareUnsigned" 会返回 0。但实际上它返回的是 -1。为什么 b 被视为比 a 大呢?

    int a = Integer.MAX_VALUE;
    int b = Integer.MAX_VALUE * -1;

    System.out.printf("x 相对于 y 的比较结果:%d%n", Integer.compare(a, b));
    System.out.printf("x 相对于 y 的无符号比较结果:%d%n", Integer.compareUnsigned(a, b));
英文:

I was assuming that "compareUnsigned" in the below example will return 0. But it is returning -1. Why is b treated as greater than a?

    int a = Integer.MAX_VALUE;
    int b = Integer.MAX_VALUE * -1;

    System.out.printf("x compared to y: %d%n", Integer.compare(a, b));
    System.out.printf("x compared to y: %d%n", Integer.compareUnsigned(a, b));

答案1

得分: 4

compareUnsigned不会做你认为它会做的事情。你可能认为它只比较参数的大小,而不考虑它们的符号。然而,它实际上的作用是将这两个整数视为uint(在Java中实际上不存在这个类型,这就是为什么有这个方法的原因!)。

也许文档对此并不是很清楚,它只是说“将值视为无符号的”。这可能被解释为“忽略符号”,但如果你查看compareUnsigned的实现,你会看到它实际上做了什么:

public static int compareUnsigned(int x, int y) {
    return compare(x + MIN_VALUE, y + MIN_VALUE);
}

无论如何,要比较两个uint,我们只需要查看它们的二进制表示。MAX_VALUE在二进制中是31个1(让我们忽略前导零),而它的否定是1个1,后面跟着30个零,再后面是1个1。

1111111111111111111111111111111 // MAX_VALUE
10000000000000000000000000000001 // -MAX_VALUE

很明显,哪个无符号的二进制数字更大。显然是那个位数更多的数字。

<hr>

要实际比较这两个整数而不考虑符号,应用Math.abs然后进行比较(但对于Integer.MIN_VALUE,这种方法不适用,你需要单独检查):

Integer.compare(Math.abs(a), Math.abs(b))
英文:

compareUnsigned does not do what you think it does. You probably thought it compares the magnitudes of the arguments only, without considering their signs. However, what it really does is that it treats the two ints as a uint (which doesn't really exist in Java, which is why this method exists!).

Maybe the documentation isn't really clear on this, it just says "treating the values as unsigned." which could be interpreted as "ignoring the signs", but if you look at the implementation of compareUnsigned, you'll see what it actually does:

public static int compareUnsigned(int x, int y) {
    return compare(x + MIN_VALUE, y + MIN_VALUE);
}

Anyway, to compare two uints, we just have to look at their binary representation. MAX_VALUE in binary is 31 ones (let's ignore leading zeros), whereas the negation of it is 1 one followed by 30 zeros, followed by 1 one.

1111111111111111111111111111111 // MAX_VALUE
10000000000000000000000000000001 // -MAX_VALUE

It is clear which is bigger as an unsigned binary number. It's obviously the one that has more digits.

<hr>

To actually compare the two integers without considering the signs, apply Math.abs then compare (won't work for Integer.MIN_VALUE though, you'd have to check that separately):

Integer.compare(Math.abs(a), Math.abs(b))

huangapple
  • 本文由 发表于 2020年8月31日 10:04:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63663851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定