在Java中声明unsigned int

时间:2012-03-24 18:07:35

标签: java integer unsigned

有没有办法在Java中声明unsigned int?

或者问题也可以这样构成: 什么是Java等效的unsigned?

只是告诉你我正在研究Java的String.hashcode()实现的上下文。如果整数是32 unsigned int,我想测试碰撞的可能性。

11 个答案:

答案 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数据类型用作无符号整数。像compareUnsigneddivideUnsigned等静态方法已添加到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的未签名TINYINTSMALLINTINTBIGINT,这就是为什么我们有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 中的这些类:

他们支持各种操作:

  • 减去
  • MOD
  • dividedBy

目前似乎缺少的是字节移位运算符。如果您需要那些,可以使用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具有无符号整数,但我从未使用过它们)。事不宜迟,让我们开始吧...

RFC 868示例

如果您需要向IO写入无符号整数会怎样?实际的例子是您要根据RFC 868输出时间。这需要一个32位,大端无符号的整数,该整数编码自凌晨12:00开始的秒数。 1900年1月1日。如何编码?

像这样制作自己的无符号32位整数:

声明一个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(数字)功能。它返回一个正数。