0

Java では、整数は 2^31 - 1 から -2^31 の間でなければなりません

したがって、int x = 2 * 1500000000 の場合

論理的な答えは 300000000 になりますが、その値に制限があるため、前に進められ、2^32 mod 3000000000 を使用すると -1294967296 になりますが、前に進められるため、正のフィールドがオーバーフローするため、数値は負になります。 . これが本当だと言うのは正しいですか?

また、変調部分を検索して読み上げました。たとえば、クロック 15 mod 12 == 3 は除算の剰余であるためですが、ここでは 12 が定数であるため、クロックの例としては適切です。

では、2^32 はオーバーフローの整数のすべての変調計算の定数ですか?

4

2 に答える 2

5

簡単にするために、8 ビット整数を使用します。

バイナリでは、8 ビットの範囲は00000000b11111111bです。

00000000b = 0d
11111111b = 255d

では、コンピューターはどのようにして整数に符号を追加するのでしょうか? 2の補数です。

符号なし整数の場合、次の方法11111111bでバイナリからデナリーに変換します。

  11111111b
= 1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 1*128 + 1*64  + 1*32  + 1*16  + 1*8   + 1*4   + 1*2   + 1*1
= 255d

では、符号付き整数は11111111bどうですか? 簡単な方法は次のとおりです。

  v----------(sign flag 1=negative)
  11111111b
= 1*(-2^7) + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 1*(-128) + 1*64  + 1*32  + 1*16  + 1*8   + 1*4   + 1*2   + 1*1
= -1d

一般に、符号付き数値の最上位ビットは符号フラグです。

負のデナリー数を 2 の補数に変換するには:

 -18d
 ========
 without sign     0001 0010
 one's complement 1110 1101 (inverted)
*two's complement 1110 1110 (one's complement + 1)

8 ビットの符号付き整数の範囲は-2^72^7-1です。

オーバーフローとは何ですか?どれどれ:

  01111111b
= 127d

  01111111b + 1
= 10000000b
= 1*(-2^7) + 0*2^6 + 0*2^5 + 0*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0
= 1*(-128) + 0*64  + 0*32  + 0*16  + 0*8   + 0*4   + 0*2   + 0*1
= -128d

  127d + 1d
  =========
  0111 1111 (127d)  +
 +0000 0001 (1d)    +
 ----------
  1000 0000 (-128d) - (overflow)

したがって、最大の 8 ビット符号付き整数に 1 を加算すると、結果は最小の 8 ビット符号付き整数になります。+ve + +ve -> -ve はオーバーフロー エラーです。

引き算はどうですか?45-16? (+ve + -ve -> +ve)

  45d - 16d
  =========
  0010 1101 (45d)   +
 +1111 0000 (-16d)  -
 ----------
1 0001 1101 (29d)   +
^---------------------(discard)

45-64はどうですか?(+ve + -ve -> -ve)

  45d - 64d
  =========
  0010 1101 (45d)   +
 +1100 0000 (-64d)  -
 ----------
  1110 1101 (-19d)  -

-64-64はどうですか?(-ve + -ve -> -ve)

  -64d - 65d
  =========
  1100 0000 (-64d)  -
 +1100 0000 (-64d)  -
 ----------
1 1000 0000 (-128d) +
^---------------------(discard)

-64-65はどうですか?

  -64d - 65d
  =========
  1100 0000 (-64d)  -
 +1011 1111 (-65d)  -
 ----------
1 0111 1111 (127d)  + (underflow)
^---------------------(discard)

したがって、 -ve + -ve -> +ve はアンダーフロー エラーです。

状況は 32 ビット整数の場合と似ていますが、より多くのビットが利用可能です。

あなたの質問について2*1500000000、それらを 32 ビットの符号なし整数として扱うと、結果は次のように3000000000なり、そのバイナリ表現は次のようになります。

  1011 0010 1101 0000 0101 1110 0000 0000
= 1*2^31 + 0*2^30 + ...
= 1*2147483648 + 0*1073741824 + ...
= 3000000000d

しかし、それを 32 ビットの符号付き整数として扱うと、次のようになります。

  v------(Let's recall this is the sign flag)
  1011 0010 1101 0000 0101 1110 0000 0000
= 1*(-2^31) + 0*2^30 + ...
= 1*(-2147483648) + 0*1073741824 + ...
= -1294967296d

追加:符号なし整数のオーバーフロー

符号なし整数のオーバーフローは非常に似ています。

  11111111b
= 255d

  11111111b + 1
= 00000000b
= 0d

  255d + 1d
  =========
  1111 1111 (255d)  +
 +0000 0001 (1d)    +
 ----------
1 0000 0000 (0d)    - (overflow)
^---------------------(discard)

そのため、32 ビット符号なし整数の場合は常にmod 2^32.

ところで、これは Java だけでなく、C/C++ などのほとんどのプログラミング言語でも同様です。PHP/JavaScript のように、他のプログラミング言語の中には、オーバーフローを自動的に処理し、型をより高い精度または浮動小数点に変更するものがあります。

于 2012-07-01T14:36:00.283 に答える
0

2^31 ではなく 2^32 で modding する必要があります。次に、符号付き演算を考慮する必要があります。2^31 より大きい数値は、それらから 2^32 が減算されます。

とにかく、2 * 1500000000 = 3000000000は 2^32 未満ですが、2^31 より大きいので、2^32 を引いて -1294967296 を取得します。

于 2012-07-01T12:06:50.303 に答える