質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1341閲覧

Javaのシフト演算(右)で、0が連続して出力される理由がわからない

karino_nao

総合スコア17

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

0クリップ

投稿2019/04/06 11:51

編集2019/04/06 12:10

前提・実現したいこと

javaでシフト演算(右)を理解したい

発生している問題・エラーメッセージ

シフト演算(右 >>)をint型の変数(値は8)で、1つずつ行ったとき
想定として、ローテートが起こり、
1ビットが右に移動し、1の後は最上位の桁に移動すると思い、
8(2^3)→4(2^2)→2(2^1)→1(2^0)→2147483648(2^31)→1073741824(2^31)…
が出力されると思っていました。

が、結果としては
8(2^3)→4(2^2)→2(2^1)→1(2^0)→0→0→0→…→8(32回右シフトした)
と0が続いていました。

なぜ0が出力されるのでしょうか?

ソース※抜粋

System.out.println("◇シフト演算(右)");

System.out.println("・循環");
int r = 0; // 結果表示
int c = 33;
for (int i = 0; i < c; i++) {
r = 8 >> i;
System.out.println("結果:" + r + ":i=" + i);
}

結果

◇シフト演算(右)
・循環
結果:8:i=0
結果:4:i=1
結果:2:i=2
結果:1:i=3
結果:0:i=4
結果:0:i=5
結果:0:i=6
結果:0:i=7
結果:0:i=8
結果:0:i=9
結果:0:i=10
結果:0:i=11
結果:0:i=12
結果:0:i=13
結果:0:i=14
結果:0:i=15
結果:0:i=16
結果:0:i=17
結果:0:i=18
結果:0:i=19
結果:0:i=20
結果:0:i=21
結果:0:i=22
結果:0:i=23
結果:0:i=24
結果:0:i=25
結果:0:i=26
結果:0:i=27
結果:0:i=28
結果:0:i=29
結果:0:i=30
結果:0:i=31
結果:8:i=32

keicha_hrs👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

javaでのローテートはライブラリで提供されています。以下のrotateLeftとrotateRightを参考に。
クラスInteger

投稿2019/04/06 12:07

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

karino_nao

2019/04/06 12:16

ありがとうございます。 ローテートはライブラリがあったのですね…。 これを読む限り、シフト演算(>>>)とrotateLeftは同じ挙動をすると思っていいのでしょうか?
karino_nao

2019/04/06 12:39

0011を右にうごかすとき、以下のような挙動をするということでしょうか? ・ローテート:0011→1001→1100→0110→0011 ・シフト  :0011→0001→0000
cateye

2019/04/06 12:44

そういうことです。
cateye

2019/04/06 13:23

(>Д<)ゝ”ラジャー!!
karino_nao

2019/04/06 13:30

シフトとローテートの違いがようやく判りました。 ありがとうございました!
cateye

2019/04/06 15:10

シフトやローテートはどんなCPUにも有る命令です(たぶんw)・・・プログラムもアセンブラから入ればいいのですが・・・今誰も教えないんだろうなぁ・・・
karino_nao

2019/04/06 22:03

本音を言えばアセンブラから勉強をしたい、という気持ちがあるのですが…。 自分ではわからないことが多すぎる&教えていただける場所・人もおらず、という状況で…。 やれることをひとつずつやっていく、というのが現状です…。
pepperleaf

2019/04/06 23:18

まあ、C言語が、アセンブラじゃ大変で生まれたようなところがあるので、C言語の系譜(C++, Java, etc)は、色濃く引きづっている気がしますが。 特にC言語だと、裏にアセンブラが透けて見えますね。
guest

0

ベストアンサー

シフト(ずらす)とローテート(回転)は違います。シフトは一方方向だけです。
多くの言語では、シフトしか演算子がないですね。ローテート演算子がある高級言語は見たこと無いです。

投稿2019/04/06 11:56

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

karino_nao

2019/04/06 12:02

なるほど。そこから勘違いしていましたか…。 あくまでずらす、のですね。 …ん?とすると、右にずらし続けると0だけが出続けるのは 1bitがなくなり、0だけになったから、なのでしょうか? しかし、だとすると、32回ずらし続けると、再び8が表示されるのはなんでなんでしょうか?
pepperleaf

2019/04/06 12:07

と同じ事を書きかけたのですが、 32bitシフトで、なんで 8になるのでしょうか? また、r の宣言がないので、もしかしたら、byte ? って事?
karino_nao

2019/04/06 12:10

失礼しました。 rは、以下の通りに宣言しています。 int r = 0;
pepperleaf

2019/04/06 12:20

確かに、再現。 ただし、以下のようにすると異なる結果。 int r =8; for (int i = 0; i < 33; i++) { r = r >> 1; } `r = 8 >> 32;` の結果が どうなのかですね。
otn

2019/04/06 12:38 編集

シフト数は、対象が32bit整数の場合は、下位5bitだけが使われます。つまり「Nビットシフトする」は「( Nを32で割った余り)ビットシフトする」になります。 ちょと日本語のJava公式リファレンスが見つけられませんでしたが、英語だと、 https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.19 公式サイトじゃないですが、Wikipediaだと、 https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85 x86の機械語の仕様に合わせているんだと思います。 Cは、x86よりずっと古いので、未定義ですね。
otn

2019/04/06 12:21

32以上だと例外を出すような仕様であっても良かった気がしますが、ちょっと使いづらいか。
karino_nao

2019/04/06 12:52

>ただし、以下のようにすると異なる結果。 こちらでも結果は異なりました。 r = 8 >> 32を超えて、>>33,34としても0のまま表示されました。 なんで? >シフト数は、32bit整数に対しては、下位5bitだけが使われます。 ごめんなさい、うまく理解できているのかわからないですが、 32ビットシフトする場合:0なので、シフトしない 1ビットシフトする場合:1なので、シフトする って理解でいいのでしょうか?
otn

2019/04/06 12:55

それで合ってます。下位ビットという言葉が分からなければ、 > つまり「Nビットシフトする」は「(Nを32で割った余り)ビットシフトする」になります。 と思ってください。 64ビット整数のシフトだと64で割った余りです。
karino_nao

2019/04/06 13:11 編集

1シフト: 1シフトする 2シフト: 2シフトする 3シフト: 3シフトする … 30シフト:30シフトする 31シフト:31シフトする 32シフト: シフトしない 上記を当てはめると 1シフト: 8→4 2シフト: 4→2 3シフト: 2→1 4シフト: 1→0 … 30シフト: 0→0 31シフト: 0→0 32シフト: シフトしない(=8がそのままでる) 33シフト: 8→4 34シフト: 4→2 35シフト: 2→1 36シフト: 1→0 … 62シフト: 0→0 63シフト: 0→0 64シフト: シフトしない(=8がそのままでる) という理解でいいのでしょうか?
otn

2019/04/06 13:09

はい。その通りです。最後は、32*2の計算間違いか、 64シフト: シフトしない(=8がそのままでる) が正しいですけどね。
karino_nao

2019/04/06 13:10

また、以下のソースの通りで、変数rで最終的に0がずっと設定されるのは、 変数rの値8が0になったままなので、 32シフトの場合、シフトはされないが、0となった値が表示される、という理解でいいでしょうか? int r =8; for (int i = 0; i < 33; i++) { r = r >> 1; }
karino_nao

2019/04/06 13:11

>64シフト: シフトしない(=8がそのままでる) 失礼しました、計算間違いです。修正いたしました。
退会済みユーザー

退会済みユーザー

2019/04/06 13:18

1回33ビットシフトしろ → 多いね 1ビットだけシフトを1回するよ 33回1ビットシフトしろ → OK 常に0になるけど1ビットだけシフトを33回するよ
otn

2019/04/06 13:21

> r = r >> 1; シフトしているのは1ビットずつなので、32がどうのこうのという話は関係ないです。
karino_nao

2019/04/06 13:29

了解しました。 ようやくすっきり致しました。 お付き合い頂きありがとうございました!
pepperleaf

2019/04/06 23:14

調べていたら、符号ビットは、別扱いみたいですね。 (-32768 * 32768) >> i とすると、マイナスのまま、2で割った結果。 今まで、シフト演算は、符号無し(or 正数)でしか使った事が無かったので気が付かなかった。 ま、アセンブラにも両方あった気がするが。 (と言うか、無いと割り算が不便)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問