web-dev-qa-db-ja.com

Java 8およびJava 9で符号なし整数を使用する方法は?

Oracleの「Primitive data types」 page では、Java 8がunsigned intおよびlongのサポートを追加することに言及しています。

int:デフォルトでは、intデータ型は32ビットの符号付き2の補数整数であり、最小値は-2です31 および最大値231-1。 Java SE 8以降では、intデータ型を使用して、最小値が0で最大値が符号なし32ビット整数を表すことができます。 232−1。Integerクラスを使用して、intデータ型を符号なし整数として使用します。詳細については、「数字クラス」セクションを参照してください。 compareUnsigneddivideUnsignedなどの静的メソッドは、Integerクラスに追加され、符号なし整数の算術演算をサポートします。

longlongデータ型は、64ビットの2の補数整数です。符号付きlongの最小値は-2です63 および最大値263-1。 Java SE 8以降では、longデータ型を使用して、符号なし64ビットlongを表すことができます。これは、最小値0、最大値264−1。intで提供される値よりも広い範囲の値が必要な場合に、このデータ型を使用します。 Longクラスには、compareUnsigneddivideUnsignedなどのメソッドも含まれており、符号なしのlongの算術演算をサポートします。

ただし、符号なしのlongまたは整数を宣言する方法はありません。たとえば、次のコードは、範囲内にある必要があるときに(リテラルは範囲外です(もちろんJava 8を使用しています)というコンパイラエラーメッセージを返します(割り当てられた値は正確に264−1):

public class Foo {
    static long values = 18446744073709551615L;

    public static void main(String[] args){
        System.out.println(values);
    }  
}

それで、unsigned intまたはlongを宣言する方法はありますか?

77
Pabce

あなたが投稿したドキュメント、および このブログ投稿 -署名されていないint/longと署名されたものの間でプリミティブを宣言するときに違いはありません。 「新しいサポート」とは、IntegerクラスとLongクラスに静的メソッドを追加することです。 Integer.divideUnsigned 。これらのメソッドを使用していない場合、2 ^ 63-1を超える「符号なし」は、負の値を持つ単純な古いlongです。

簡単なスキムから、+ /-2 ^ 31-1またはlongの場合は+/- 2 ^ 63-1の範囲外の整数定数を宣言する方法がないように見えます。範囲外の正の値に対応する負の値を手動で計算する必要があります。

46
Sbodd

Java 8でも、longintはまだ署名されていますが、一部のメソッドだけが署名されていないかのように扱うです。そのような符号なしの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
}
81
kajacx
    // 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
     */
23
blueberry0xff

を宣言する方法はありません nsigned long or int in Java 8またはJava 9.しかし、一部のメソッドは、それらを署名なしのように扱います。例えば:

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

しかし、これは変数の 宣言 ではありません。

17
1ac0

サードパーティのライブラリを使用するオプションがある場合、 jOOjOOQ からのスピンオフライブラリ)があります。これは、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に変換できます。

(免責事項:私はこれらの図書館の背後にある会社で働いています)

3
Lukas Eder