10
byte x = -1;
for(int i = 0; i < 8; i++)
{
    x = (byte) (x >>> 1);
    System.out.println("X: " + x);
}

私が理解しているように、Javaはデータを2の補数、つまり-1 = 11111111(ウィキペディアによる)で保存します。

また、Javaドキュメントから:「ビットパターンは左側のオペランドで指定され、右側のオペランドでシフトする位置の数が指定されます。符号なしの右シフト演算子>>>」はゼロを左端にシフトします">>" の後の一番左の位置は符号拡張に依存します。"

つまり、 >>> は毎回 0 を左端にシフトします。したがって、このコードは

反復: x のビット表現

0: 11111111

1: 01111111

2: 00111111

3: 00011111

...すぐ

ただし、私の出力は常に X: -1 です。これは、>>> が符号ビットを一番左の位置に置いていることを意味します (推測します)。それで、>> を試してみると、同じ結果が得られました。

どうしたの?私の出力は、X: -1、x: 127、x: 63 などになると思います。

4

5 に答える 5

28

Javaが発明されたときにバイトに署名する必要があると思った人は誰でも取り出して、泣くまでセロリの濡れた棒で叩く必要があります:-)

intにキャストし、1をトップビットにシフトしないようにすることで、次のように、やりたいことができます。

byte x = -1;
int x2 = ((int)x) & 0xff;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X: " + x2);
}

あなたの特定の問題は、ここに示すように、>>>がシフトを行うためにintにキャストし、次にそれをバイトにキャストバックしているためです。

byte x = -1;
int x2 = ((int)x) & 0xff;
int x3;
int x4 = x2;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X2: " + x2);
    x3 = (x >>> 1);
    x = (byte)x3;
    x4 = (x4 >>> 1);
    System.out.println("X: " + x3 + " " + x + " " + x4);
}

どの出力:

X2: 127
X: 2147483647 -1 127
X2: 63
X: 2147483647 -1 63
X2: 31
X: 2147483647 -1 31
X2: 15
X: 2147483647 -1 15
X2: 7
X: 2147483647 -1 7
X2: 3
X: 2147483647 -1 3
X2: 1
X: 2147483647 -1 1
X2: 0
X: 2147483647 -1 0

xとx3が機能しないことがはっきりとわかります(x3は正しくシフトしますが、xのバイトにキャストバックすると再び-1に設定されます)。x4は完全に機能します。

于 2009-02-19T01:16:34.137 に答える
5

次のことを覚えておいてください。

  • ビット演算のオペランドは、少なくとも int !に常に昇格されます。
  • キャストには常に符号拡張が含まれます。

したがって、(x >>> n) を実行すると、x をバイトとして定義したにもかかわらず、シフトの目的で最初に int に変換されます。変換されるバイトが負の場合、int にするために追加されたすべての「余分なビット」(つまり、結果の int の左端の 24 ビット) が 1 に設定されます。 byte は -1 でした。実際にシフトしているのはintとしての -1 です。つまり、32 ビットすべてが 1 に設定された 32 ビットの数値です。これを右に 1 ~ 8 桁シフトしても、下位 8 ビットがすべて設定されます。したがって、バイトにキャストバックすると、8 ビットすべてが 1 に設定されたバイト、つまりバイト値が -1 になります。

于 2009-02-19T03:25:10.850 に答える
3

これについてはよくわかりません。しかし、私の推測では

x >>> 1 

リテラル「1」はintであるため、バイトからintにプロモートされます。次に、あなたが観察していることは理にかなっています。

于 2009-02-19T01:16:17.680 に答える
0

なぜ機能しないのかわかりませんが、トップビットをクリアする簡単な方法は、(バイナリ)0111111を使用することです。

x = (byte) (x >>> 1) & 0x7F;
于 2009-02-19T01:27:03.613 に答える
0

問題は、前に(ずっと前に)言われたように、シフトを行う前にxがint(符号拡張)にアップキャストされることです。
「ビットからビットへ」の変換を行うと、次のことが役立つはずです。

byte x = -1;
for(int i = 0; i < 8; i++)
{
    x = (byte) ((x & 0xFF) >>> 1);
    System.out.println("X: " + x);
}
于 2009-11-24T20:02:24.273 に答える