理解Java无符号数

5

我希望了解如何将有符号数转换为无符号数。

假设我有以下内容:

byte number = 127; // '1111111'

为了使其无符号,我必须选择“更大”的数据类型“short”,并使用值0x00ff应用AND运算符。
short number2;  
number2 = number & 0x00ff;

为什么会将数字变成无符号数?
3个回答

5

Java实际上没有无符号的基本类型。

值127实际上由“01111111”表示,第一个位是符号(0为正数)。

无符号字节可以保存0到255之间的值,但127是有符号字节的最大值。由于一个字节有8个位,有符号的字节消耗一个位来保存符号。因此,如果您想表示大于127的值,则需要使用具有更多位数的更大类型。更大的类型也有一个保留位用于符号,但至少有8个位用于实际值,因此您可以表示值255。

话虽如此,在Java中应该避免使用byte和short,因为它们存在问题。你会注意到我将结果转换为short,因为运算符实际上返回int。在Java中,您应该只使用int和long,因为它们的实现更好。

编辑:AND运算符使其无符号,因为符号位是short的第一位,并且您将包含字节值的8位复制到short的最后8位。因此,如果您有一个负数,第一个位是1(这意味着它是负数),实际上成为值的一部分。而short始终为正数,因为它的符号位太高的2的幂,因此不受short影响。

 byte:             10101101
                    ||||||| <- actual value
short:     0000000010101101
            ||||||||||||||| <- actual value

编辑2:请注意,由于负值使用二进制补码表示法,所以值可能与您预期的不同。所有正值保持不变。
但是,-128 = 0x10000000将变为128
-127 = 0x10000001将变为129
依此类推,直到-1 = 0x11111111,它将变为255


有关byte和short的问题,有什么参考链接吗?我偶尔会使用byte,但从未真正使用过short。 - Dean J
这里的第一个例子说明了这个观点:http://blog.mpathirage.com/2010/06/27/java-puzzlers-phantom-reference-menace-attack-of-the-clone-revenge-of-the-shift/ 如果您在short类型上使用任何操作符,如+或-,它实际上会转换为int类型,这可能会造成调用重载方法时的问题。 - Andrei Fierbinteanu
2
Java确实有一种无符号原始类型,它被称为“char” :) 但大多数情况下其范围有点受限。 - Jörn Horstmann
1
不,看我的第二次编辑;-127是10000001;第一个1表示它是负数,而0000001则表示它以二进制补码表示(0000001 = 2^n - 127;其中n是该类型的位数,在字节的情况下n=8);因此它是11111111 AND 10000001,即129。 - Andrei Fierbinteanu
1
@shlomjmi;许多编程语言使用二进制补码,因为它非常快速地将数字相加。00000001(一)加上11111110(负一)等于00000000(零)。您可以通过将两者进行“&”(与)操作来进行加法运算,并将溢出向左传递。 - Dean J
显示剩余4条评论

1

Java没有无符号数据类型。你只需要转换为“更大”的数据类型,就可以了。


我问了如何通过这个AND操作使它变成无符号的。 - shlomjmi
它并不会使其成为无符号类型。通过位移操作的魔法最多只能抛弃负数。但这并不会使其成为无符号类型。不管怎样,你认为这是如何发生的?位移操作意外地创建了新的子类或在JVM中进行了黑客攻击吗? - foret

0

如果你只是从负字节转换为整数,那么整数也将是负数。因此,你需要取负整数(或在你的示例中为短整型),并将最高的3个字节(整数)设置为0x00。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接