Java8およびJava9で符号なし整数を使用するにはどうすればよいですか?


82

Oracleの「プリミティブデータ型」ページでは、Java8がunsignedintおよびlongのサポートを追加すると記載されています。

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

longlongデータ型は64ビットの2の補数整数です。署名さはlong-2の最小値を有し、63 2の最大値63を-1。Java SEの8以降では、使用することができlong、符号なし64ビット表現するデータ・タイプをlong0の最小値及び2の最大値を有し、64 -1。intによって提供される値よりも広い値の範囲が必要な場合は、このデータ型を使用します。Longこのクラスはまた、のような方法が含まれcompareUnsigneddivideUnsigned符号なしのための算術演算をサポートするなどlong

ただし、unsignedlongまたはintegerを宣言する方法が見つかりません。たとえば、次のコードは、範囲内にある必要がある場合(割り当てられた値は正確に2 64 -1)、「リテラルは範囲外です」(もちろんJava 8を使用しています)というコンパイラエラーメッセージを表示します。:

public class Foo {
    static long values = 18446744073709551615L;
    
    public static void main(String[] args){
        System.out.println(values);
    }  
}

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


2
Java 8のLong.MAX_VALUE定数には何が返されますか?
ブルーノフランコ

21
unsignedintegerまたはunsignedlong型はありません。新しいメソッドの1つを使用する場合、そのメソッドは32ビットまたは64ビットの整数を符号なしであるかのように扱います。しかし、それだけです。変数の型は引き続き符号付きであり、符号なしの数値として使用していることを覚えておくのはあなた次第です。符号なしリテラルは追加しませんでしたが、十分な数の人がバグを報告した場合は、Java9に追加する可能性があります。:)
ajb 2014

5
新しいメソッドを追加する以外は、実際には何も変更しませんでした。
ホットリック2014

4
私の知る限り、彼らが行ったのは、符号なしの値を返すことができるメソッドを追加することだけでしたが、符号なしの値を宣言することはできません。あなたが私に尋ねればちょっとばかげている、そして本当の痛み。1つのパラメータが1で、もう1つが符号なしとして扱いたい数値であるInteger.divideUnsignedを使用する方法があるのではないかと思います。私の知る限りではうまくいくでしょうが、本当にばかげたやり方のようです。
cluemein 2016年

@ajb Javaで適切な符号なしを最終的に確認するために、「バグ」プロセスをどのように支援できますか?:)
マシュー

回答:


52

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

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


88

まあ、でも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
}

5
これで私が見る観察は、順序が壊れているということです。あるシステムからunsignedlongを取得し(TwitterはそのようなIDを提供します)、それらを並べ替えたい場合、おそらくそれらが時系列であることがわかっていたため、Long.MAX_VALUEを超えるものはすべて実際には0の前に負として表示されます。Javaの実装で:-(代わりに、1つがまた、署名Long.MIN_VALUEに符号なし0マップということをシフトダウンしなければなりません表示されます。
デビッド・スマイリー

10
@DavidSmiley良い点。、符号なしlong型を並べ替える使用することをLong.compareUnsigned、またはソート機能へのコンパレータとして、そのメソッドを渡す
kajacx

26
    // 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
     */

10
コードを投げるだけでなく、説明を追加する必要があります。
cluemein 2016年

22

どのように方法はありません宣言し、符号なしlongまたはint型のJava 8またはJava 9にしかし、彼らが署名されたかのように、いくつかの方法は、例えば、それらを扱うには:

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

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


3
私はなぜ負傷しませんか。彼らは簡単にuintとulongタイプを追加できたでしょう
EKanadily 2016年

これこのドキュメントの@docesamは詳細な説明です。つまり、Integerクラスに符号なし操作を行うためのメソッドだけが追加されました。そして、もし彼らが簡単に追加できたのなら、なぜ彼らがそれをしないのか分かりません;-)
1ac0 2016年

@ Ladislav DANKO賢明な人もいれば、他の人もいます。この場合、それが賢明であったかどうかはわかりませんが、オラクルはそれほど賢明ではないというのが私の印象です。
EKanadily 2016年

1
@docesamいいえ、「uint型とulong型を簡単に追加」することはできませんでした。そのためには、JLS、JVM仕様、JNI、多くのライブラリ(java.util.Arraysなど)、リフレクションなどをオーバーホールする必要があります。
nayuki 2016年

1
@ Michaelangel007ねえ、私たちはさまざまな背景の仮定でこのトピックに取り組んでいると思います。私にメールを送ってくれれば、詳細について話しますか?
ナユキ2017

4

サードパーティのライブラリを使用することがオプションである場合、Javaで符号なし整数のラッパータイプを提供するjOOUjOOQからのスピンオフライブラリ)があります。これは、プリミティブ型(したがってバイトコード)で符号なし型をサポートすることとまったく同じではありませんが、ユースケースにはそれでも十分です。

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

(免責事項:私はこれらのライブラリの背後にある会社で働いています)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.