在Java中是否有一种方法来声明无符号整型?
或者这个问题也可以是这样的: Java中与unsigned等价的是什么?
只是为了告诉你上下文,我正在查看Java的String.hashcode()的实现。我想测试如果整数是32 unsigned int,碰撞的可能性。
在Java中是否有一种方法来声明无符号整型?
或者这个问题也可以是这样的: Java中与unsigned等价的是什么?
只是为了告诉你上下文,我正在查看Java的String.hashcode()的实现。我想测试如果整数是32 unsigned int,碰撞的可能性。
当前回答
似乎你可以通过在使用值之前对它们进行“逻辑与”来处理签名问题:
使用实例(byte[] header[0]的值为0x86):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
结果:
Integer -122 = 134
其他回答
这里有很好的答案,但我没有看到任何逐位操作的演示。正如Visser(目前接受的答案)所说,Java默认为整数加符号(Java 8有无符号整数,但我从未使用过它们)。废话不多说,我们开始吧……
RFC 868使用实例
如果需要向IO写入无符号整数会发生什么?实际示例是当您想根据RFC 868输出时间时。这需要一个32位的大端序无符号整数,用于编码从12:00 A.M.开始的秒数1900年1月1日。怎么编码呢?
创建自己的32位无符号整数,如下所示:
声明一个4字节(32位)的字节数组
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.
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位无符号大端整数。是的,长数据类型是有符号的,但是我们忽略了这个事实,因为我们假设secondsSince1900只使用了低32位)。由于将long强制转换为字节,所有高于2^7(十六进制中的前两位)的位将被忽略。
参考资料:Java网络编程,第4版。
也许这就是你的意思?
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 获取未签名(Integer.MIN_VALUE+1) → 2147483649
似乎你可以通过在使用值之前对它们进行“逻辑与”来处理签名问题:
使用实例(byte[] header[0]的值为0x86):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
结果:
Integer -122 = 134
我们需要无符号数字来在jOOQ中建模MySQL的无符号TINYINT, SMALLINT, INT, BIGINT,这就是为什么我们创建了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库:
UnsignedInteger UnsignedLong
它们支持各种操作:
+ - 次 国防部 除以
目前似乎缺少的是字节移位操作符。如果需要,可以从Java中使用BigInteger。