2

shortの値を左シフトする Java プログラムを次に示します2。2 つの質問があります。

16 ~ 29num << iの値で有効な結果が得られるのはなぜですか? iAshortは -32,768 ~ 32,767 の値のみを保持する必要があります。

だから私は、おそらくa より大きい値としてSystem.out.println解釈すると思いました。しかし、なぜ で予期しない値を生成し始めるのでしょうか?num << ishortnum << 30

public class LeftShift {

    public static void main(String[] args)
    {
        short num = 2;
        for (int i = 0; i < 32; i++) {
            System.out.println("Left-shifting 2 by " + i + " places yields: " 
                                + (num << i));
        }
    }

}

出力:

Left-shifting 2 by 0 places yields: 2
Left-shifting 2 by 1 places yields: 4
Left-shifting 2 by 2 places yields: 8
Left-shifting 2 by 3 places yields: 16
Left-shifting 2 by 4 places yields: 32
Left-shifting 2 by 5 places yields: 64
Left-shifting 2 by 6 places yields: 128
Left-shifting 2 by 7 places yields: 256
Left-shifting 2 by 8 places yields: 512
Left-shifting 2 by 9 places yields: 1024
Left-shifting 2 by 10 places yields: 2048
Left-shifting 2 by 11 places yields: 4096
Left-shifting 2 by 12 places yields: 8192
Left-shifting 2 by 13 places yields: 16384
Left-shifting 2 by 14 places yields: 32768
Left-shifting 2 by 15 places yields: 65536
Left-shifting 2 by 16 places yields: 131072
Left-shifting 2 by 17 places yields: 262144
Left-shifting 2 by 18 places yields: 524288
Left-shifting 2 by 19 places yields: 1048576
Left-shifting 2 by 20 places yields: 2097152
Left-shifting 2 by 21 places yields: 4194304
Left-shifting 2 by 22 places yields: 8388608
Left-shifting 2 by 23 places yields: 16777216
Left-shifting 2 by 24 places yields: 33554432
Left-shifting 2 by 25 places yields: 67108864
Left-shifting 2 by 26 places yields: 134217728
Left-shifting 2 by 27 places yields: 268435456
Left-shifting 2 by 28 places yields: 536870912
Left-shifting 2 by 29 places yields: 1073741824
Left-shifting 2 by 30 places yields: -2147483648
Left-shifting 2 by 31 places yields: 0
4

6 に答える 6

3

複合代入演算子は、結果を割り当てられた型にキャストすることに注意してください。したがって、例を変更します。

public static void main(String[] args) {
    for (int i = 0; i < 32; i++) {
        short num = 2;
        num <<= i; // equivalent to num = (short)(num << i);
        System.out.println("Left-shifting 2 by " + i + " places yields: " + num);
    }
}

これにより、予想とは異なる結果が得られる可能性があります。

于 2012-05-29T13:29:08.747 に答える
3

Java 言語仕様 15.19 から: 「シフト演算子」

シフト式の型は、左側のオペランドの昇格された型です。

昇格型は 5.6 で定義されています: 「数値昇格」:

それ以外の場合、オペランドがコンパイル時の型の byte、short、または char の場合、単項数値昇格は、拡大変換 (§5.1.2) によって int 型の値に昇格します。

于 2012-05-29T13:21:14.670 に答える
3

sに対する算術演算は、それらをキャストし直さない限り、shorts を生成するためです。int例えば、

short value = 2;
short result = value << 31;

にキャストする必要があるというコンパイル エラーが表示されますshort

これにはいくつかの理由があります。

  • バイトコード言語は、より小さな型を実際には扱いません。int
  • そうしないと、shorts に対する操作が頻繁にオーバーフローします。
  • 通常、サブ 32 ビット値で操作を行わないほとんどのハードウェアをより適切にモデル化するため
于 2012-05-29T13:15:40.483 に答える
2

30 の予期しない値は整数オーバーフローであり、MSB が 1 になるため、負の数として解釈されます。

また、演算子 << は s を生成していることにも注意してくださいint(引数が alongでない限り、 a を生成しますlong)。(実際には、は最初shortに拡張され、その後にのみが評価されます。) したがって、結果は期待どおりであり、 ではありません。int<<intshort

于 2012-05-29T13:16:13.963 に答える
1

起こっているのは、オペランドの自動昇格です。Java では、(num << i)例の式の結果は型intです。intこれが、結果が ではなくの範囲にある理由shortです。

に代入しようとすると、コンパイル エラーが発生し、. にキャストし直す必要があり(num << i)ます。shortshort

于 2012-05-29T13:19:30.670 に答える
1

このSOスレッドを参照してください。

この質問に関連する部分は、ここからの引用です。

If an integer operator has an operand of type long, then the other operand is also
converted to type long. Otherwise the operation is performed on operands of type int, if  
necessary shorter operands are converted into int.

これらの拡張変換は情報を失わず、オーバーフローの場合に潜在的に保護できるという考えだと思います。拡大変換と縮小変換の詳細については、Java 言語仕様の第 5 章を参照してください。

于 2012-05-29T13:30:35.930 に答える