Javaでunsigned intを宣言する方法はありますか?
あるいは、この質問は、Javaのunsignedと同等のものとは何でしょうか。
JavaによるString.hashcode()
の実装を見ていたコンテキストをお伝えするだけです。整数が32 unsigned intの場合、衝突の可能性をテストしたいと思いました。
Javaには 符号なし整数 のデータ型はありません。
大きな値を格納する必要がある場合は、long
の代わりに int
を定義できます。
符号なし整数を符号なしのように使用することもできます。 2の補数表現 の利点は、ほとんどの演算(加算、減算、乗算、左シフトなど)が符号付き整数と符号なし整数のバイナリレベルで同一であることです。ただし、いくつかの操作(除算、右シフト、比較、およびキャスト)は異なります。 Java SE 8以降、 Integer
クラスの新しいメソッドを使用すると、int
データ型 を完全に使用して符号なし演算を実行できます :
Java SE 8以降では、intデータ型を使用して、符号なし32ビット整数を表すことができます。この整数の最小値は0、最大値は2 ^ 32-1です。 Integerクラスを使用して、intデータ型を符号なし整数として使用します。符号なし整数の算術演算をサポートするために、
compareUnsigned
、divideUnsigned
etcなどの静的メソッドがIntegerクラスに追加されました。
int
変数は宣言時にまだ署名されていますが、Integer
クラスのこれらのメソッドを使用することで符号なし算術演算が可能になりました。
Java 8には、unsigned IntegerおよびLong用の APIがあります。
Intの値が符号付きか符号なしかは、ビットの解釈方法によって異なります。Javaはビットを符号付き値として解釈します(符号なしプリミティブはありません)。
符号なしの値として解釈するint型がある場合(たとえば、DataInputStreamから符号なしの値が含まれていることがわかっているint型を読み取るなど)、次のトリックを実行できます。
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffl;
16進リテラルはintリテラルではなく、長いリテラルであることが重要であることに注意してください。したがって、最後の 'l'です。
MySQLの符号なしTINYINT
、SMALLINT
、INT
、BIGINT
を jOOQ にモデル化するには、符号なしの数字が必要でした。そのため、Javaで符号なし整数のラッパー型を提供する jOOU を作成しました。 。例:
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ライブラリからこれらのクラスを使用できます。
それらはさまざまな操作をサポートします。
現時点で欠けているように見えるものはバイトシフト演算子です。それらが必要な場合は、JavaのBigIntegerを使用できます。
16ビット符号なし整数にはchar
を使用してください。
おそらくこれはあなたが意味したものですか?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0)
→0getUnsigned(1)
→1getUnsigned(Integer.MAX_VALUE)
→2147483647getUnsigned(Integer.MIN_VALUE)
→2147483648getUnsigned(Integer.MIN_VALUE + 1)
→2147483649ここには良い答えがありますが、ビット単位の操作のデモンストレーションは表示されません。 Visser(現在受け入れられている答え)が言うように、Javaはデフォルトで整数に署名します(Java 8には符号なし整数がありますが、私はそれらを使用したことがありません)。苦労せずに、それをやってみましょう...
IOに符号なし整数を書き込む必要がある場合はどうなりますか?実際の例は、 RFC 868 に従って時間を出力したい場合です。これには、午前12:00以降の秒数をエンコードする32ビットのビッグエンディアンの符号なし整数が必要です。 1900年1月1日。これをどのようにエンコードしますか?
4バイト(2 ^ 31ビット)のバイト配列を宣言します
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
ここで、配列内の各バイトをビッグエンディアンの順序で情報を埋める必要があります(大混乱を引き起こす場合はリトルエンディアン)。 secondsSince1900
と呼ばれる時間を含むlong(Javaでは64ビット長)があると仮定します(これは最初の32ビットの価値のみを利用し、Dateは1月1日午前12:00を参照するという事実を処理しました) 、1970)、論理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ビットのビッグエンディアン整数と同等になりました。はい、longデータ型は署名されていますが、secondsSince1900は下位32ビットのみを使用すると仮定したため、その事実を無視しました。 longをバイトに強制するため、2 ^ 7(16進数の最初の2桁)よりも高いビットはすべて無視されます。
参照元:Java Network Programming、第4版。
このコードを作成すると、 "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);
}
値を使用する前に、値に対して「論理積」をとることで署名の問題を処理できるようです。
例(byte[]
header[0]
の値は0x86
です):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
結果:
Integer -122 = 134