有没有办法在 Java 中声明一个 unsigned int?
或者问题也可以这样表述:Java 中的 unsigned 等价物是什么?
只是为了告诉您我正在查看 Java 的 String.hashcode()
实现的上下文。如果整数是 32 unsigned int,我想测试碰撞的可能性。
>>>
运算符而不是 >>
来右移而不进行符号扩展。
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
类中的这些方法来实现无符号算术。
int 中的值是有符号还是无符号取决于位的解释方式 - Java 将位解释为有符号值(它没有无符号原语)。
如果您有一个想要解释为无符号值的 int(例如,您从 DataInputStream
中读取一个您知道应该被解释为无符号值的 int),那么您可以执行以下技巧。
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;
请注意,十六进制文字是长文字而不是 int 文字很重要 - 因此末尾有“L”。
0xFFFFFF
并保持 int 吗?
我们需要无符号数来对 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 library 中的这些类:
无符号整数
无符号长
它们支持各种操作:
加
减
次
模组
除以
目前似乎缺少的是字节移位运算符。如果您需要这些,您可以使用 Java 中的 BigInteger。
对 16 位无符号整数使用 char
。
也许这就是你的意思?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
获取无符号(0)→ 0
得到无符号(1)→1
getUnsigned(Integer.MAX_VALUE) → 2147483647
getUnsigned(Integer.MIN_VALUE) → 2147483648
getUnsigned(Integer.MIN_VALUE + 1) → 2147483649
2 * (long) Integer.MAX_VALUE + 2
比 0x1_0000_0000L
更容易理解吗?在这方面,为什么不简单地return signed & 0xFFFF_FFFFL;
?
这里有很好的答案,但我没有看到任何按位运算的演示。就像 Visser(当前接受的答案)所说,Java 默认对整数进行签名(Java 8 有无符号整数,但我从未使用过它们)。事不宜迟,让我们开始吧……
RFC 868 示例
如果你需要将一个无符号整数写入 IO 会发生什么?实际示例是当您要根据 RFC 868 输出时间时。这需要一个 32 位、大端、无符号整数,用于编码自 1900 年 1 月 1 日凌晨 12:00 以来的秒数。您将如何编码?
像这样制作自己的无符号 32 位整数:
声明一个 4 字节(32 位)的字节数组
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
这会初始化数组,请参阅 Are byte arrays initialised to zero in Java?。现在,您必须以大端顺序(如果您想破坏大端,则使用小端)来填充数组中的每个字节。假设您有一个 long 包含名为 secondsSince1900
的时间(长整数在 Java 中为 64 位长)(仅使用前 32 位值,并且您已经处理了 Date 引用 1970 年 1 月 1 日上午 12:00 的事实),然后您可以使用逻辑 AND 从中提取位,并将这些位移动到在强制转换为字节时不会被忽略的位置(数字),并且以大端顺序排列。
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 版。
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
这对我来说只是一个小小的“嗯”。我记得你应该这样做Byte[] my32BitUnsignedInteger = new Byte[4]
如果我错了,请纠正我。
byte[] array = new byte[4]
您似乎可以通过在使用它们之前对值执行“逻辑与”来处理签名问题:
示例(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);
}
您可以使用 Math.abs(number) 函数。它返回一个正数。
MIN_VALUE
,则不会
0
,则不会
int
数据类型来表示一个无符号的 32 位整数,其最小值为0
,最大值为2^32-1
。 - 见 docs.oracle.com/javase/tutorial/java/nutsandbolts/… 和 docs.oracle.com/javase/8/docs/api/java/lang/Integer.htmlint
,就好像它是通过各种方法无符号的一样。