LoginSignup
10
10

More than 5 years have passed since last update.

Javaのシフト演算は論理シフトや算術シフトとは別物?

Last updated at Posted at 2018-08-19

情報系資格の教本を何気なく見ていて、ビットシフトの項目でふと気になった・・・Javaのビットシフト・・・なんか変じゃない・・・?

Javaのシフト演算子

演算子 意味
<< 符号無し左シフト
>> 符号付き右シフト
>>> 符号無し右シフト

なぜ>>>の記号を左右反転した<<<が存在しないのか・・・
なぜ<<が符号無しシフトなのに、記号を左右反転した>>が符号付きシフトなのか・・・

シフト演算の種類

論理シフト

・空いたビットは0を入れる

2進数 Javaの演算子
もとの値 1010 1010 1010 1010 -
←1論理シフト 0101 0101 0101 0100 <<
→1論理シフト 0101 0101 0101 0101 >>>

算術シフト

最上位ビット(符号ビット)は固定
・左シフトの場合、空いたビットは0を入れる
・右シフトの場合、空いたビットは最上位ビットと同値を入れる

2進数 Javaの演算子
もとの値 1010 1010 1010 1010 -
←1算術シフト 1101 0101 0101 0100 -
→1算術シフト 11 010101 0101 0101 >>

左算術シフトが無いのはそもそもプロセッサのせい?

こんな記事を見つけた

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

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

どうやら(<<<に対応する?)左算術シフトが無いのは、プロセッサ自体が左算術シフトに対応していないかららしい。(詳しくは引用元で解説されています)
要は左算術シフトは余分な処理が必要になるということのようだ。
(らしい とか ようだ とか曖昧なのは完璧には理解していないから)

論理シフト、算術シフトで語るのが間違い?

これも先程の記事から引用

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

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

試しに計算してみる

10進数 2進数 備考
value -1431655766 1010 1010 1010 1010 1010 1010 1010 1010 valueはint型整数
value * 2 1431655764 010 1010 1010 1010 1010 1010 1010 10100 正しい解は-2863311532
int型の最小値は-2147483648
オーバーフローしている
value << 1 1431655764 010 1010 1010 1010 1010 1010 1010 10100 = value * 2
value / 2 -715827883 11010 1010 1010 1010 1010 1010 1010 101
value >> 1 -715827883 11010 1010 1010 1010 1010 1010 1010 101 = value / 2
value >>> 1 1431655765 01010101010101010101010101010101

つまり、
<< nは * 2n
>> nは / 2n
と対応している。

「なぜ<<が符号無しシフトなのに、記号を左右反転した>>が符号付きシフトなのか・・・」という疑問は、論理シフトや算術シフトを基準に考えるのがそもそも間違っていたという事だった。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10