で異なるx = 31
または32
のJavaでは、次の2つの演算が異なる結果をもたらすのはなぜですか?x=3
と同じ結果になりますか?Javaの結果は、(int)Math.pow(2、x)と1 << x
int x=3;
int b = (int) Math.pow(2,x);
int c = 1<<x;
結果:
x=32: b=2147483647; c=1;
x=31: b=2147483647; c=-2147483648;
x=3: b=8 ; c=8
で異なるx = 31
または32
のJavaでは、次の2つの演算が異なる結果をもたらすのはなぜですか?x=3
と同じ結果になりますか?Javaの結果は、(int)Math.pow(2、x)と1 << x
int x=3;
int b = (int) Math.pow(2,x);
int c = 1<<x;
結果:
x=32: b=2147483647; c=1;
x=31: b=2147483647; c=-2147483648;
x=3: b=8 ; c=8
複数の問題は遊びであります
int
は-2147483648
と2147483647
間の値のみを保存することができます。1 << x
uses the lowest five bits of x
。したがって、1 << 32
は、定義により、1 << 0
と同じです。1 << 31
が否定的なのかを説明します。Math.pow(2, 32)
は、double
を返します。 d
が2147483647
戻り2147483647
("the largest representable value of type int
")よりdouble
大きい(int)(d)
、。このインタビューの質問は何は(int)Math.pow(2, x)
と1 << x
が0
... 30
範囲外x
の値に対して等価でないことを示しています。
P.S. int
の代わりにlong
(および1
の代わりに1L
)の代わりにlong
を使用すると、他の2つの結果とは異なる別の結果が得られることに注意することはおそらく興味深いでしょう。これは、最終結果がint
に変換されても保持されます。
特に最後のポイントは非常に重要です。 –
は、int型の限界を考えてみましょう。どれくらいの数の数字を保持できますか?
左シフトと明示的な2の違いについて質問します。 –
そして、それが符号付きの型であるという事実を' int'の限界に加えてください。 –
文書Math.pow
によれば、doubleとreturn doubleの両方の引数を促進します。明らかに返される結果がdoubleで、それをintにキャストすると最高32ビットしか得られず残りは切り捨てられるので、常に(int) Math.pow(2,x);
という値が得られます。ビットシフトを行うと、常にintで処理されるため、オーバーフローが発生します。
私は仮数の上位32ビットを推測しています。私は間違っているかもしれない。 – asenovm
ええ、そうかもしれません。私はちょうど '2^31-1'を返すように思い出しました。コメントを削除しました:) –
intのサイズは32ビットで、デフォルトで署名されているため、最初のビットが符号として使用されます。左に31ビットシフトすると、Two's Complimentが得られます。これは - (2^32)です。 32ビット左にシフトすると、1に戻ります。intの代わりにlongを使ってこのシフトを実行すると、63 +ビットをシフトするまでの答えが得られます。
ここでは、長い場合のマイクロベンチマークがあります。私のラップトップ(2.8GHz)では、Math.pow
の代わりにシフトを使用すると、7倍以上速くなります。
int limit = 50_000_000;
@Test
public void testPower() {
Random r = new Random(7);
long t = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int p = r.nextInt(63);
long l = (long)Math.pow(2,p);
}
long t1 = System.currentTimeMillis();
System.out.println((t1-t)/1000.0); // 3.758 s
}
@Test
public void testShift() {
Random r = new Random(7);
long t = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int p = r.nextInt(63);
long l = 1L << p;
}
long t1 = System.currentTimeMillis();
System.out.println((t1-t)/1000.0); // 0.523 s
}
微妙な違いは、答えが同じでもpow()が**多く**遅くなることです。 pow()には丸め誤差がありますが、intはオーバーフローしています。 '1L << 32"は '2147483648'と同じです。 –