有没有办法在Java中声明unsigned int?
或者问题也可以这样构成: 什么是Java等效的unsigned?
只是告诉你我正在研究Java的String.hashcode()
实现的上下文。如果整数是32 unsigned int,我想测试碰撞的可能性。
答案 0 :(得分:266)
Java没有unsigned integers的数据类型。
如果您需要存储较大的值,则可以定义long
而不是int
。
您也可以使用带符号的整数,就好像它是无符号的一样。 two's complement representation的好处是大多数操作(例如加法,减法,乘法和左移)在二进制级别上对于有符号和无符号整数是相同的。然而,一些操作(除法,右移,比较和铸造)是不同的。从Java SE 8开始,Integer
类中的新方法允许您完全使用int
数据类型to perform unsigned arithmetic:
在Java SE 8及更高版本中,您可以使用int数据类型来表示无符号的32位整数,其最小值为0,最大值为2 ^ 32-1。使用Integer类将int数据类型用作无符号整数。像
compareUnsigned
,divideUnsigned
等静态方法已添加到Integer类中,以支持无符号整数的算术运算。
请注意int
变量在声明时仍然是有符号的,但现在可以使用Integer
类中的那些方法进行无符号算术。
答案 1 :(得分:64)
答案 2 :(得分:58)
int中的值是有符号还是无符号取决于位的解释方式 - Java将位解释为有符号值(它没有未签名的原语)。
如果你有一个想要解释为无符号值的int(例如,你从DataInputStream中读取一个你知道包含无符号值的int),那么你可以执行以下操作。
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffl;
请注意,重要的是十六进制文字是一个长文字,而不是一个字面文字 - 因此' l'最后。
答案 3 :(得分:18)
我们需要无符号数字来模拟jOOQ中MySQL的未签名TINYINT
,SMALLINT
,INT
,BIGINT
,这就是为什么我们有created 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
。希望这会有所帮助。
(免责声明:我为这些图书馆背后的公司工作)
答案 4 :(得分:7)
对于无符号数字,您可以使用 Guava library 中的这些类:
他们支持各种操作:
目前似乎缺少的是字节移位运算符。如果您需要那些,可以使用Java中的BigInteger。
答案 5 :(得分:4)
将char
用于16位无符号整数。
答案 6 :(得分:1)
也许这就是你的意思?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0)
→0 getUnsigned(1)
→1 getUnsigned(Integer.MAX_VALUE)
→2147483647 getUnsigned(Integer.MIN_VALUE)
→2147483648 getUnsigned(Integer.MIN_VALUE + 1)
→2147483649 答案 7 :(得分:1)
刚刚制作了这段代码,并转换了#34; 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);
}
答案 8 :(得分:1)
似乎您可以通过在使用值之前对它们进行“逻辑与”来解决签名问题:
示例(byte[]
header[0]
的值为0x86
):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
结果:
Integer -122 = 134
答案 9 :(得分:1)
这里有很好的答案,但是我看不到按位运算的任何演示。就像Visser(当前接受的答案)所说的那样,Java默认情况下对整数签名(Java 8具有无符号整数,但我从未使用过它们)。事不宜迟,让我们开始吧...
如果您需要向IO写入无符号整数会怎样?实际的例子是您要根据RFC 868输出时间。这需要一个32位,大端无符号的整数,该整数编码自凌晨12:00开始的秒数。 1900年1月1日。如何编码?
声明一个4字节(2 ^ 31位)的字节数组
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
现在,您必须按大端顺序(或小端顺序,如果要破坏数据,则用大端序)填充信息。假设您有一个包含时间的长整数(Java中长整数为64位长),称为secondsSince1900
(仅使用前32位的值,并且您已经处理了Date引用1月1日12:00 AM的事实) (1970),那么您可以使用逻辑与从中提取位,然后将这些位移到以大字节序排列的位置(数字),将其强制转换为字节时将不会被忽略。
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强制为一个字节,所有高于2 ^ 7(十六进制的前两位)的位都将被忽略。
引用的来源:Java网络编程,第4版。
答案 10 :(得分:-18)
您可以使用Math.abs(数字)功能。它返回一个正数。