86

Javaが整数を内部的に格納する方法を理解しようとしています。私はすべてのJavaプリミティブ整数が署名されていることを知っています(短いものを除く?)。これは、その数値の1バイトで使用可能なビットが1つ少ないことを意味します。

私の質問は、すべての整数(正と負)が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`

したがって、答えが all2の補数として格納されている数値の場合、次のようになります。

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

ここでも混乱しているのは、どちらも負の数であるという記号です。私はそれを誤解/誤解している可能性がありますか?

編集 私の質問が混乱しているのかわからない。質問を分離することを余儀なくされました:

私の質問は正確に:正の数はに保存されますbinary as isが、負の数はとして保存されtwo's complementますか?

すべてが2の補数に格納されていると言う人もいれば、負の数だけが2の補数として格納されているという回答もあります。

4

10 に答える 10

111

まず、Javaプリミティブデータ型を要約してみましょう。

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

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

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

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

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

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

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

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

ソース

2の補数

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

0000 0111 =72の補数は11111001= -7

それが機能する方法は、MSB(最上位ビット)が負の値を受け取るため、上記の場合

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

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

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

ソース

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

より詳細な答え:

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

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

1.署名された大きさ

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

1011 = -3
0011 = +3

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

2.1の補数

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

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

この表現の問題は、0を表す2つのビットパターン、負の0(1111)正の0(0000)がまだ存在することです。

3.2の補数

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

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

4 = 0100

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

0100 -> 1011

最後に、1ビット追加します

1011 + 1 = 1100.

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

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

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

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

4.バイアス

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

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

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
于 2012-11-16T18:36:48.533 に答える
62

Java整数は32ビットであり、常に符号付きです。これは、最上位ビット(MSB)が符号ビットとして機能することを意味します。anで表される整数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の補数は負の整数を表すための排他的なスキームではなく、整数の2進表現は常に同じであり、最上位ビットの重みを否定するだけであると言えます。そして、そのビットが整数の符号を決定します。

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

別の観点から、2の補数をxas ~x + 1(x + 1ではない)と見なす場合の説明は次のとおりです。

いずれxの場合も、~xはのビット単位の逆でxあるためx1ビットがある場合~x0常にビットがあります(その逆も同様です)。したがって、これらを合計すると、加算にキャリーはなく、合計はすべてのビットがである整数になります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ビットは32ビットに収まらないため(整数のオーバーフロー)、単に破棄されます。それで、

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

したがって、ネガティブは、xで表すことができることがわかります~x + 1。これは、の2の補数と呼ばれxます。

于 2012-11-16T18:39:45.940 に答える
10

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

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の補数を使用しているようです。

于 2012-11-16T18:36:36.930 に答える
5

Oracleは、興味深いと思われるJavaデータ型に関するいくつかのドキュメントを提供しています。具体的には:

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

ところで、shortも2の補数として格納されます。

于 2012-11-16T18:35:49.067 に答える
4

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

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に設定されていることがわかりました。したがって、負の数です。また、MSB以外の2の補数が実行されます。

  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)

これで、バイトキャストは最後のバイトである10000010を取得しました。(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の補数」とは何ですか?

于 2015-02-12T13:23:02.310 に答える
3

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

于 2012-11-16T18:34:23.527 に答える
3

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

于 2012-11-16T18:51:32.727 に答える
2

正の数は2進数として直接格納されます。負の数には2の褒め言葉が必要です。

例えば:

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

これが符号付きビットの違いです。

于 2014-02-07T06:59:52.333 に答える
2

答えてくれてありがとう、dreamcrash https://stackoverflow.com/a/13422442/1065835 ; wikiページでは、正の数の負の対応物の2進表現を見つける方法を理解するのに役立つ例を示しています。

たとえば、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であるため、表される値は負です。

于 2015-01-09T14:01:20.070 に答える
1

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

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

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

于 2016-12-27T17:14:14.220 に答える