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

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

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

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

Q&A

解決済

3回答

893閲覧

Javaのシフト演算子で、<<<がない理由

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

0クリップ

投稿2018/03/03 09:34

シフト演算子で

は、符号埋めをしてくれますが、

<<は符号を保とうとしません。

<<は符号を保つ演算にして、
<<<は符号を保たない演算子として、準備しなかった理由はなんでしょうか?

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

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

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

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

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

guest

回答3

0

ベストアンサー

maisumakunさんの回答で解決したわけではなかったのでしょうか・・・


これはJavaに限った話ではなく、より一般的に「2の補数表現を採用している(=つまり殆どの)プロセッサー」の機械語の命令セットの仕様でも同様だと思います。(むしろそこに仕様の本質があると思います)

シフトは「ビット列を負号無し整数値としてとらえた際に2のべき乗で乗算したり除算したりすることと同義」という特徴があります。「2の補数表現」の場合は上記を簡単に「負号あり整数」に拡張することができます。そのために算術右シフトがあるわけです。

さて

(A)符号を保存せずに左にnビットシフトする演算
(B)符号を保存して左シフトする演算

の意味的な違いはなんでしょうか?オーバーフローしないうちはどちらの演算でも結果は同じなので、オーバーフローした場合だけ考えてみます。

text

1(A) 2before: 0100000(2) 64(10) 3after: 1000000(2) -128(10) 4==>左に0を補うと... 5==> 0|1000000(2) 128(10) 6 7(B) 8before: 0100000(2) 64(10) 9after: 0000000(2) 0(10) 10==>MSBを1に変えて左に0を補うと... 11==> 0|1000000(2) 128(10)

オーバーフローした場合、

(A)MSBの左に追加のbitを補うと「正しい値」が再現できます。
(B)MSBを反転した上でMSBの左に追加のbitを補うと「正しい値」が再現できます。

プロセッサーの内部演算が(B)となっている場合、この演算を用いて多倍長演算などの論理を組もうとすると「オーバーフローの際に正しいビットパターンを再現するためにMSBを反転する」という余分な操作が必要になります。それをやるくらいなら最初から論理シフトして

「MSBの左側に追加のビット(元の符号と同じ値のビット)を拡張するだけで演算結果をより大きなビット数での正しい値へ拡張する」

とした方が合理的です。逆に右シフト(除算)の場合は論理シフトしかないと2のべき乗で除算する際に「右シフトしてからMSBを元の符号の値に合わせる」という余分な操作をしなければなりません。それゆえ「元の符号の値を保存する」算術右シフトと論理右シフトをそれぞれ別の機能として用意する意味がでてきます。


さらに言えばこれはシフト演算に限らず加算や減算でも同様の考え方で設計されています。

text

1 0111111(2) 127(10) 2+ 0000001(2) 1(10) 3--------------------- 4 1000000(2) -128(10) 50|1000000(2) 128(10)

上は8bit整数で127に1を加えたら-128になっちゃうという例ですが、オーバーフローした場合、さきほどと同様にMSBの左に追加のbitを補いさえすれば10000000というビットパターンは-128ではなく128と解釈できるビットパターンになるため、「正しい演算結果を構成する一部のビット」としてそのまま使えるわけです。


結論:
右シフトでは符号ビットを保存する演算があると嬉しいので論理・算術シフトの機能がそれぞれ存在する。
左シフトする際に符号ビットが保存されてもうれしい点がないので論理シフトのみしか必要ない。

投稿2018/03/03 10:38

KSwordOfHaste

総合スコア18394

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

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

退会済みユーザー

退会済みユーザー

2018/03/03 11:01

腑に落ちました。 大変勉強になり、何故、このような言語仕様になっているかを根底から理解できました。 ご丁寧にありがとうございます。
guest

0

<<は符号を保とうとしません。

別に回答しましたが、単に左シフトするだけでも、(オーバーフローして入れられない状態にならない限り)符号は保たれます

11111111 charの-1 (2つ左シフト) 11111100 charの-4

投稿2018/03/03 10:27

maisumakun

総合スコア145184

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

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

退会済みユーザー

退会済みユーザー

2018/03/03 10:32 編集

10111111は1つ左シフトすると 01111110で符号が保たれていません。
maisumakun

2018/03/03 10:35

それはオーバーフローしている(元の型に算術シフト後の値が入らない)状態です。
退会済みユーザー

退会済みユーザー

2018/03/03 10:45

オーバーフローしても、もとの型に算術シフト後の値は入る認識です。 もちろん、符号は流れてしまいますが・・・ 例えば、intは32ビットで、2147483647 * 4の結果は符号が代わり、 -4と表示されます。 符号ビットが溢れ、算術シフト後の値は入る認識です。 そこで、なぜ、 Javaの<<は、符号を流してしまうのでしょうか? つまり、<<を符号を保つようにして、別に、 <<<で符号を流すような演算子は準備しなかったのでしょうか?
maisumakun

2018/03/03 10:57

もし(そのような演算がどれだけ必要なのか知りませんが)符号だけ保ちたいなら、もとが正なら& 0x7fffffff、負なら| 0x80000000のようにマスクすればそれで片付きます。 対して、算術右シフトはかんたんに再現できません。
退会済みユーザー

退会済みユーザー

2018/03/03 11:02

長らく、付き合って頂きありがとうございます。
guest

0

Javaを作る人が、不要だ、と判断したのでしょう

投稿2018/03/03 10:18

y_waiwai

総合スコア87774

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

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

退会済みユーザー

退会済みユーザー

2018/03/03 10:34

なぜ、不要だと判断したのでしょうか?
y_waiwai

2018/03/03 10:41

さあ、なんの関係もない私には知る由もありません
退会済みユーザー

退会済みユーザー

2018/03/03 10:48

そうですか(笑) では、下らない回答はよしましょう。
y_waiwai

2018/03/03 10:49

そうですね。くだらない質問はなしにしませんか?
退会済みユーザー

退会済みユーザー

2018/03/03 10:56

まことに申し訳ございませんでした。
y_waiwai

2018/03/03 10:58

はい。これに懲りてこんな質問はやめてきましょうね。
退会済みユーザー

退会済みユーザー

2018/03/03 11:03

誠に、申し訳ございませんでした。 あなたの文章を見るのが辛いので、いじめるのはやめてください。
y_waiwai

2018/03/03 11:04

はい。あなたの文章を見るのは不快なので、すみやかに退出をお願いします
退会済みユーザー

退会済みユーザー

2018/03/03 11:07

まことに、申し訳ございませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問