如何在Java 8和Java 9中使用unsigned Integer?

Pab*_*bce 78 java unsigned java-8

在Oracle"原始数据类型" 页面中,它提到Java 8增加了对无符号整数和长整数的支持:

int:默认情况下,int数据类型是32位带符号的二进制补码整数,其最小值为-2 31,最大值为2 31 -1.在Java SE 8及更高版本中,您可以使用int数据类型表示无符号的32位整数,其最小值为0,最大值为2 32 -1.使用Integer该类将int数据类型用作无符号整数.有关更多信息,请参阅数字类一节.像静态方法compareUnsigned,divideUnsigned等已被添加到Integer类,以支持算术运算的无符号整数.

long:long数据类型是64位二进制补码整数.签名long的最小值为-2 63,最大值为2 63 -1.在Java SE 8及更高版本中,您可以使用long数据类型表示无符号64位long,其最小值为0,最大值为2 64 -1.当需要比int提供的值更宽的值时,请使用此数据类型.本Long类也包含类似的方法compareUnsigned,divideUnsigned等支持算术运算的无符号long.

但是,我发现无法声明无符号长整数或整数.例如,下面的代码给出了编译器错误消息"文字超出范围"(我当然使用的是Java 8),当它应该在范围内时(指定的值恰好是2 64 -1) :

public class Foo {
    static long values = 18446744073709551615L;

    public static void main(String[] args){
        System.out.println(values);
    }  
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有办法声明unsigned int或long?

kaj*_*acx 82

好吧,即使在Java 8中,long并且int仍然签名,只有一些方法将它们视为未签名.如果你想写那样的无符号long文字,你可以这样做

static long values = Long.parseUnsignedLong("18446744073709551615");

public static void main(String[] args) {
    System.out.println(values); // -1
    System.out.println(Long.toUnsignedString(values)); // 18446744073709551615
}
Run Code Online (Sandbox Code Playgroud)

  • @DavidSmiley好点.要对无符号长整数进行排序,请使用[Long.compareUnsigned](https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#compareUnsigned-long-long-),或传递该方法作为排序函数的比较器, (10认同)
  • 我看到的观察结果是排序已损坏.如果我从某个系统得到一个unsigned long(顺便提一下Twitter提供这样的ID)并且想要对它们进行排序,也许是因为我知道它们是按时间顺序排列的,那么Long.MAX_VALUE以外的所有内容实际上都会在0之前显示为负数使用Java的实现:-(相反,它似乎也必须将其向下移动,使得无符号0映射到带符号的Long.MIN_VALUE. (5认同)

Sbo*_*odd 46

根据您发布的文档和本博客文章 - 在声明unsigned int/long和signed签名之间的原语时没有区别."新支持"是在Integer和Long类中添加静态方法,例如Integer.divideUnsigned.如果你没有使用这些方法,那么长于2 ^ 63-1的"无符号"只是一个带有负值的普通旧长度.

从快速浏览,看起来似乎没有办法在+/- 2 ^ 31-1或+/- 2 ^ 63-1之外的范围内声明整数常量.您必须手动计算与超出范围的正值相对应的负值.


blu*_*xff 25

    // Java 8
    int vInt = Integer.parseUnsignedInt("4294967295");
    System.out.println(vInt); // -1
    String sInt = Integer.toUnsignedString(vInt);
    System.out.println(sInt); // 4294967295

    long vLong = Long.parseUnsignedLong("18446744073709551615");
    System.out.println(vLong); // -1
    String sLong = Long.toUnsignedString(vLong);
    System.out.println(sLong); // 18446744073709551615

    // Guava 18.0
    int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString());
    System.out.println(vIntGu); // -1
    String sIntGu = UnsignedInts.toString(vIntGu);
    System.out.println(sIntGu); // 4294967295

    long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615");
    System.out.println(vLongGu); // -1
    String sLongGu = UnsignedLongs.toString(vLongGu);
    System.out.println(sLongGu); // 18446744073709551615

    /**
     Integer - Max range
     Signed: From ?2,147,483,648 to 2,147,483,647, from ?(2^31) to 2^31 – 1
     Unsigned: From 0 to 4,294,967,295 which equals 2^32 ? 1

     Long - Max range
     Signed: From ?9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, from ?(2^63) to 2^63 ? 1
     Unsigned: From 0 to 18,446,744,073,709,551,615 which equals 2^64 – 1
     */
Run Code Online (Sandbox Code Playgroud)

  • 应该添加一些解释,而不仅仅是抛出代码. (8认同)

1ac*_*ac0 18

有没有办法如何来声明一个unsigned long类型或者int在Java中8或Java 9.但有些方法对待他们,好像他们是无符号,例如:

static long values = Long.parseUnsignedLong("123456789012345678");
Run Code Online (Sandbox Code Playgroud)

但这不是变量的声明.

  • 我为什么不知道.他们可以轻松添加uint和ulong类型 (3认同)

Luk*_*der 5

如果使用第三方库是一种选择,则有jOOU(来自jOOQ的衍生库),它为 Java 中的无符号整数提供包装器类型。这与为无符号类型提供原始类型(以及字节码)支持并不完全相同,但对于您的用例来说,它可能仍然足够好。

import static org.joou.Unsigned.*;

// and then...
UByte    b = ubyte(1);
UShort   s = ushort(1);
UInteger i = uint(1);
ULong    l = ulong(1);
Run Code Online (Sandbox Code Playgroud)

所有这些类型都扩展java.lang.Number并可以转换为高阶原始类型和BigInteger.

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