web-dev-qa-db-ja.com

整数は、Javaのビットレベルで内部的にどのように表されますか?

Java整数を内部に格納する方法を理解しようとしています。すべてのJavaプリミティブ整数が署名されていることを知っています。数値のバイトで。

私の質問は、すべての整数(正と負)が2の補数として格納されているのですか、それとも2の補数の負の数だけですか?

仕様にはx bit two's complement number。しかし、私はしばしば混乱します。

例えば:

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010

編集

明確にするために、x = 15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`

したがって、答えがallの場合、数値は2の補数として格納されます。

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

ここでの混乱は、記号が言うように、両方とも負の数です。私はそれを誤解/誤解しているのでしょうか?

編集私の質問がわかりにくいかどうかわかりません。質問を隔離するように強制:

私の質問:正の数はbinary as is負の数はtwo's complement

一部はすべてが2の補数で保存され、1つの答えは負の数のみが2の補数として保存されると言います。

75
Kevin Rave

Javaプリミティブデータ型の要約から始めましょう。

byte:バイトデータ型は、8ビットの符号付き2の補数整数です

Short:Shortデータ型は、16ビットの符号付き2の補数整数です

int:Intデータ型は32ビット符号付き2の補数整数です

long:longデータ型は、64ビットの符号付き2の補数整数です

float:floatデータ型は、単精度32ビットIEEE 754浮動小数点です。

double:doubleデータ型は倍精度64ビットIEEE 754浮動小数点です。

boolean:booleanデータ型は、1ビットの情報を表します

char:charデータ型は、単一の16ビットUnicode文字です。

ソース

2の補数

「良い例は wiki からです。2の補数との関係は256 = 255 + 1であり、(255 − x)はxの1の補数であることに注意してください。

0000 0111 = 7 2の補数は1111 1001 = -7

動作方法は、MSB(最上位ビット)が負の値を受け取るため、上記の場合

-7 = 1001 = -8 + 0+ 0+ 1

正の整数は、通常、単純な2進数(1は1、10は2、11は3など)として格納されます。

負の整数は、絶対値の2の補数として格納されます。正の数の2の補数は、この表記法を負の数で使用する場合です。

ソース

この回答に対していくつかの点を受け取ったので、さらに情報を追加することにしました。

より詳細な答え:

とりわけ、正数と負数を2進数で表すには、主に4つのアプローチがあります。

  1. 署名された大きさ
  2. 補数
  3. 2の補数
  4. バイアス

1。符号付き大きさ

最上位ビットを使用して符号を表し、残りのビットを使用して絶対値を表します。ここで、は正数を表し、1負の数、例:

1011 = -3
0011 = +3

この表現はより単純です。ただし、10進数を追加するのと同じ方法で2進数を追加することはできないため、ハードウェアレベルでの実装が難しくなります。さらに、このアプローチでは2つのバイナリパターンを使用して、0、100 ... 0、および0 .... 0を表します。

2。補数

この表現では、与えられた数のすべてのビットを反転して、その相補性を見つけます。例えば:

010 = 2, so -2 = 101 (inverting all bits).

この表現の問題は、0(00..0および11..1)を表す2つのビットパターンがまだ存在することです。

3。二の補数

この表現で負の数を見つけるには、すべてのビットを反転してから1ビットを追加します。 1ビットを追加すると、0を表す2ビットパターンの問題が解決します。この表現では、1つ(00 ... 0)しかありません。

たとえば、4ビットを使用して4(10進数)のバイナリ負表現を見つけたいとします。まず、4をバイナリに変換します。

4 = 0100

次に、すべてのビットを反転します

0100 -> 1011

最後に、少し追加します

1011 + 1 = 1100.

したがって、4ビットで2の補数のバイナリ表現を使用している場合、1100は10進数で-4に相当します。

補完を見つけるより速い方法は、最初のビットを値1として固定し、残りのビットを反転することです。上記の例では、次のようになります。

0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

2の補数表現は、0の表現が1つだけであることに加えて、10進数の場合と同じ方法で、異なる符号を持つ偶数の場合でも2つのバイナリ値を追加します。それでも、オーバーフローのケースをチェックする必要があります。

4。バイアス

この表現は、浮動小数点のIEEE 754ノルムで指数を表すために使用されます。すべてのビットがゼロのバイナリ値が最小値を表すという利点があります。そして、すべてのビットが1のバイナリ値が最大値を表します。名前が示すように、値はバイアス(通常は2 ^(n-1)または2 ^(n-1)-1)のnビットのバイナリでエンコード(正または負)されます。

したがって、8ビットを使用している場合、10進数の値1は、2 ^(n-1)のバイアスを使用して、次の値でバイナリで表されます。

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
90
dreamcrash

Java整数は32ビットであり、常に符号付きです。これは、最上位ビット(MSB)が符号ビットとして機能することを意味します。 intで表される整数は、ビットの加重和に他なりません。重みは次のように割り当てられます。

Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

MSBの重みは負(実際には最大の負)であるため、このビットがオンの場合、整数(重み付き合計)は負になります。

4ビットの数値でシミュレートしましょう。

Binary    Weighted sum            Integer value
0000       0 + 0 + 0 + 0           0
0001       0 + 0 + 0 + 2^0         1
0010       0 + 0 + 2^1 + 0         2
0011       0 + 0 + 2^1 + 2^0       3
0100       0 + 2^2 + 0 + 0         4
0101       0 + 2^2 + 0 + 2^0       5
0110       0 + 2^2 + 2^1 + 0       6
0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
1001      -2^3 + 0 + 0 + 2^0      -7
1010      -2^3 + 0 + 2^1 + 0      -6
1011      -2^3 + 0 + 2^1 + 2^0    -5
1100      -2^3 + 2^2 + 0 + 0      -4
1101      -2^3 + 2^2 + 0 + 2^0    -3
1110      -2^3 + 2^2 + 2^1 + 0    -2
1111      -2^3 + 2^2 + 2^1 + 2^0  -1

したがって、2の補数は、負の整数を表すための排他的なスキームではなく、整数のバイナリ表現は常に同じであると言え、最上位ビットの重みを否定するだけです。そして、そのビットは整数の符号を決定します。

Cには、unsigned int x;の宣言に使用できるキーワードunsigned(Javaでは使用不可)があります。符号なし整数では、MSBの重みは負ではなく正(2^31)です。その場合、unsigned intの範囲は0から2^32 - 1ですが、intの範囲は-2^31から2^31 - 1です。

別の観点から、xの2の補数を~x + 1(x x 1ではない)と見なす場合、ここに説明があります。

xの場合、~xxのビット単位の逆であるため、x1- bit、~xを持っているところはどこでもそこに0-ビットがあります(逆も同様です)。したがって、これらを合計すると、加算では桁上げが発生せず、合計はすべてのビットが1である整数になります。

32ビット整数の場合:

x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
           = 1 0000 0000 0000 0000 0000 0000 0000 0000

左端の1- bitは、32ビットに収まらないため(整数オーバーフロー)、単に破棄されます。そう、

x + ~x + 1 = 0
-x = ~x + 1

したがって、負のx~x + 1で表すことができ、これをxの2の補数と呼びます。

56
0605002

私はそれを知るために次のプログラムを実行しました

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}

出力は

1010
11111111111111111111111111110110

出力から、2の補数を使用しているようです。

10
Dungeon Hunter

Oracleは、Java Datatypes に関する興味深いドキュメントを提供しています。具体的には:

int:intデータ型は、32ビットの符号付き2の補数整数です。最小値は-2,147,483,648で、最大値は2,147,483,647(両端を含む)です。

ちなみに、ショートも2の補数として格納されます。

4
matsev

このドキュメント によれば、すべての整数は署名され、Javaの2の補数形式で格納されます。信頼性は確かではありません。

3
Joel

最上位ビット(32番目)は、数値が正または負であることを示します。 0の場合、数値が正であり、実際のバイナリ表現に格納されていることを意味します。ただし、1の場合、数値は負であり、その2の補数表現で格納されます。したがって、32ビットに重み-2 ^ 32を与え、そのバイナリ表現から整数値を復元すると、実際の答えが得られます。

2

正の数はそのまま保存/取得されます。

e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                               (0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve, 
so the value will be taken as it is. 

ただし、負の数は2の補数(MSBビット以外)の後に格納され、MSBビットは1に設定されます。

例)-10を保存する場合

  0-000 0010  -> (1's complement) -> 0-111 1101 
              -> (2's complement) 0-111 1101 + 1 -> 0-111 1110
  Now MSB will be set to one, since it is negative no -> 1-111 1110

検索すると、MSBが1に設定されていることがわかりました。また、2の補数はMSB以外で実行されます。

  1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
  Since MSB representing this is negative 10 --> hence  -10 will be retrived.

鋳造

また、int/shortをbyteにキャストする場合、最後のバイトだけが最後のバイトMSBとともに考慮されることに注意してください。

例「-130」を短くすると、次のように保存されます

(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110

これで、バイトキャストは0111 1110である最後のバイトを取りました。(0-MSB)MSBが+ ve値であると言うので、そのまま取られます。 126です(+ ve)。

別の例「130」を短くすると、以下のように保存されます

  0-000 000 1000 0010     (MSB = 0)

現在、バイトキャストは1000 0010である最後のバイトを取りました。 (1 = MSB)MSBは-ve値であると言うので、2の補数が実行され、負の数が返されます。この場合、-126が返されます。

 1-000 0010  -> (1's complement) -> 1-111 1101 
             -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
               = -126

(int)(char)(byte)-1 AND(int)(short)(byte)-1の差分

(byte)-1       -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

同様に

(short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

しかし

(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
since char is unsigned; MSB won't be carry forwarded. 

そして

(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded. 

参照資料

負の数を表すのに2の補数が使用される理由

「2の補数」とは?

2

ありがとう、dreamcrash回答 https://stackoverflow.com/a/13422442/1065835 ; on wikiページ 彼らは、正の数の負の対応物のバイナリ表現を見つける方法を理解するのに役立つ例を与えます。

たとえば、1バイト(= 2ニブル= 8ビット)を使用すると、10進数の5は次のように表されます。

0000 01012最上位ビットは0であるため、パターンは負でない値を表します。 2の補数表記で-5に変換するには、ビットを反転します。 0は1になり、1は0になります。

1111 1010この時点で、数字は10進数値-5の1の補数です。 2の補数を取得するには、結果に1が追加され、次のようになります。

1111 1011結果は、2の補数形式の10進数値-5を表す符号付き2進数です。最上位ビットは1であるため、表される値は負です。

2
Maksim Dmitriev

正の数は、バイナリとして直接保存されます。負の数には2の賛辞が必要です。

例えば:

15:00000000 00000000 00000000 00001111
-15:11111111 11111111 11111111 11110001

ここに符号付きビットの違いがあります。

1
Siva Padhy

正の整数の2 '補数の値は、MSBビット0 (like +14 2'complement is 01110)と同じです。

負の整数のみについては、2 'の補数値(-14= 10001+1 = 10010)を計算しています。

したがって、最終的な答えは、values(+ve and -ve)の両方が2 'の補数形式でのみ格納されるということです。

1
Mangesh Gawali