ChatGPT解决这个技术问题 Extra ChatGPT

在 Java 中声明一个 unsigned int

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

或者问题也可以这样表述:Java 中的 unsigned 等价物是什么?

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

Java 中没有无符号类型。
这篇文章可能会对您有所帮助stackoverflow.com/a/4449161/778687
似乎不是AFAICT的一种方式。相关:stackoverflow.com/questions/430346/…
这取决于您要达到的目的。在大多数情况下,Java 中的所有整数都是有符号的。但是,您可以在一种特定情况下将有符号整数处理为无符号:您可以通过使用 >>> 运算符而不是 >> 来右移而不进行符号扩展。

A
Aleksandr Dubinsky

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 类中的这些方法来实现无符号算术。


公平地说,对于许多项目来说,技术要求并不那么严格,你确实可以承受这样“浪费”内存的代价。
我知道,我也明白Java的初衷。但例如智能手机不配置额外的内存。据我所知,他们通常使用 Java。但是,我不想在 Java 程序员和其他人之间挑起一场战争。
对我来说,这不仅仅是浪费钱。当您在位级别上工作时,无符号更容易使用
从 Java 8 开始,这不再是正确的。在 Java SE 8 及更高版本中,您可以使用 int 数据类型来表示一个无符号的 32 位整数,其最小值为 0,最大值为 2^32-1。 - 见 docs.oracle.com/javase/tutorial/java/nutsandbolts/…docs.oracle.com/javase/8/docs/api/java/lang/Integer.html
@7SpecialGems:我已经更新了答案以包含该信息。话虽如此,不可能声明无符号整数或排除负值,只能使用 int,就好像它是通过各种方法无符号的一样。
Z
Zsolt Safrany

int 中的值是有符号还是无符号取决于位的解释方式 - Java 将位解释为有符号值(它没有无符号原语)。

如果您有一个想要解释为无符号值的 int(例如,您从 DataInputStream 中读取一个您知道应该被解释为无符号值的 int),那么您可以执行以下技巧。

int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;

请注意,十六进制文字是长文字而不是 int 文字很重要 - 因此末尾有“L”。


对我来说,这是最好的答案......我的数据来自 NFC 卡 UID,它可以有 4 或 8 个字节......在 4 个字节的情况下,我需要将其转换为无符号整数,但我不能使用 ByteBuffer.getLong 因为它不是 64 位数据。谢谢。
为什么一定要长。你不能只做 0xFFFFFF 并保持 int 吗?
@Displee 想一想。如果你 AND 一个具有 32 位 1 的 int,为什么 Java 会以与原始值不同的方式解释你的新变量?那是 8 个 F,而不是 6 个,顺便说一句,因为 0xF=1111 而你需要其中的 32 个 1)
L
Lukas Eder

我们需要无符号数来对 jOOQ 中 MySQL 的无符号 TINYINTSMALLINTINTBIGINT 进行建模,这就是我们创建 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。希望这可以帮助。

(免责声明:我为这些库背后的公司工作)


这听起来很方便!感谢提及。 :)
r
randers

对于无符号数,您可以使用 Guava library 中的这些类:

无符号整数

无符号长

它们支持各种操作:

模组

除以

目前似乎缺少的是字节移位运算符。如果您需要这些,您可以使用 Java 中的 BigInteger。


M
Molossus Spondee

对 16 位无符号整数使用 char


Char 不是 32 位无符号整数,但 char 是内存增益的一个很好的答案。此链接:stackoverflow.com/questions/1841461/unsigned-short-in-java(来自上面的 jqr)
M
Matthias Ronge

也许这就是你的意思?

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


您正在为使用三元运算符而不是 if 语句的惰性输入而牺牲数百万分之一秒的性能时间。不好。 (开玩笑)
您真的认为 2 * (long) Integer.MAX_VALUE + 20x1_0000_0000L 更容易理解吗?在这方面,为什么不简单地return signed & 0xFFFF_FFFFL;
C
Community

这里有很好的答案,但我没有看到任何按位运算的演示。就像 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 版。


这是新数组的java实现吗? Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s) 这对我来说只是一个小小的“嗯”。我记得你应该这样做Byte[] my32BitUnsignedInteger = new Byte[4]如果我错了,请纠正我。
@Yolomep 是的,它是 Java 语法。将括号附加到类型或名称是可以的。
哇。我不知道。我认为这种数组声明仅适用于 c++。
您的字节是盒装类。您想使用 byte[] array = new byte[4]
A
Artem

您似乎可以通过在使用它们之前对值执行“逻辑与”来处理签名问题:

示例(byte[] header[0] 的值为 0x86 ):

System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));

结果:

Integer -122 = 134

R
Romulo

刚刚制作了这段代码,它将“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);
                    }

P
Peter Mortensen

您可以使用 Math.abs(number) 函数。它返回一个正数。


nitpick:如果您传入 MIN_VALUE,则不会
@kyo722 我无法想象这会在无符号基元范围内返回一个正值。
nitpick #2:如果您传入 0,则不会