在Java中是否有声明无符号整数的方法?
或者也可以这样表达问题: Java中的无符号相当于什么?
只是告诉你我正在查看Java的String.hashcode()
实现。如果整数为32位无符号整数,我想测试碰撞的可能性。
Java没有无符号整数的数据类型。
如果需要存储大量数据,您可以定义一个long
而不是int
。
您也可以将有符号整数视为无符号整数使用。 二进制补码表示法 的好处是对于有符号和无符号整数,在二进制级别上执行大多数操作(例如加法、减法、乘法和左移)是相同的。 然而,一些操作(如除法、右移、比较和强制转换)是不同的。 自Java SE 8以来,在Integer
类中的新方法允许您完全使用int
数据类型执行无符号算术运算:
compareUnsigned
, divideUnsigned
等静态方法以支持无符号整数的算术运算。请注意,当声明时,int变量仍然带有符号,但是现在可以通过使用Integer类中的这些方法进行无符号运算。int类型的值是有符号还是无符号取决于如何解释这些比特位 - Java将比特位解释为有符号值(它没有无符号基本类型)。
如果你有一个int值,想将其解释为无符号值(例如从DataInputStream
读取一个你知道应该被解释为无符号值的int值),那么可以使用以下技巧。
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;
注意:十六进制字面值应该是long
字面值,而不是int
字面值,因此要在结尾加上'L'。
0xFFFFFF
并保持 int 类型吗? - Displeelong unsignedValue = someObject.getInt();
?将 int
值与 0xFFFFFFFFL 进行“ANDing”的好处是什么? - Mohammad Kholghi0xFFFFFFFFL
的末尾添加 "L"?0xFFFFFFFF
不已经足够了吗? - Mohammad Kholghi我们需要无符号数字来模拟MySQL的无符号TINYINT
、SMALLINT
、INT
和BIGINT
,以便在jOOQ中使用。这就是为什么我们创建了jOOU,这是一个提供Java无符号整数包装类型的极简主义库。例如:
import static org.joou.Unsigned.*;
// and then...
UByte b = ubyte(1);
UShort s = ushort(1);
UInteger i = uint(1);
ULong l = ulong(1);
所有这些类型都扩展自java.lang.Number
,并可以转换为更高级的原始类型和BigInteger
。希望这能帮到你。
(免责声明:我在这些库背后的公司工作)
对于无符号数字,您可以使用来自Guava library 的以下类:
它们支持各种操作:
目前似乎缺少的是字节移位运算符。如果需要这些运算符,可以使用Java中的BigInteger。
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0)
→ 0getUnsigned(1)
→ 1getUnsigned(Integer.MAX_VALUE)
→ 2147483647getUnsigned(Integer.MIN_VALUE)
→ 2147483648getUnsigned(Integer.MIN_VALUE + 1)
→ 21474836492 * (long) Integer.MAX_VALUE + 2
比 0x1_0000_0000L
更易于理解吗?那么,为什么不直接使用 return signed&0xFFFF_FFFFL;
呢? - Holger使用 char
来表示16位无符号整数。
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
这里是数组的初始化,参见 Java中的字节数组是否初始化为零?。现在你需要按照大端序(如果你想要造成混乱,也可以使用小端序)的顺序填充数组中的每个字节,假设你有一个包含时间的长整型变量(Java中的长整型变量长度为64位)叫做secondsSince1900
(它只使用了前32位,并且你已经处理了Date引用1970年1月1日上午12:00的事实),那么你可以使用逻辑与运算符从中提取位,并将这些位移动到不会被忽略的位置(数字),以便在大端序中强制转换为Byte。
my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed
my32BitUnsignedInteger
现在等同于一个符合RCF 868标准的无符号32位大端整数。是的,long数据类型是有符号的,但我们忽略了这个事实,因为我们假设secondsSince1900仅使用了低32位。由于将long强制转换为byte,所有高于2^7(十六进制中的前两个数字)的位都将被忽略。Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
对我来说有点小疑惑。我记得应该这样写 Byte[] my32BitUnsignedInteger = new Byte[4]
如果我错了请纠正我。 - Yolomepbyte[] array = new byte[4]
。 - Antti Haapala -- Слава Україні在使用数值之前,通过对这些值进行“逻辑与”运算,您似乎可以解决签名问题:
例如(byte[]
header[0]
的值为0x86
):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
结果:
Integer -122 = 134
我刚写了这段代码,可以将“this.altura”的负数转换为正数。希望能帮到有需要的人。
if(this.altura < 0){
String aux = Integer.toString(this.altura);
char aux2[] = aux.toCharArray();
aux = "";
for(int con = 1; con < aux2.length; con++){
aux += aux2[con];
}
this.altura = Integer.parseInt(aux);
System.out.println("New Value: " + this.altura);
}
MIN_VALUE
就可以了。 - Dennis Meng0
时才不会。 - genisage
>>>
运算符而非>>
进行右移操作,从而不进行符号扩展。 - Sergey Kalinichenko