算術右シフト
| 日本語 | 算術右ずらし |
| 英語 | arithmetic right shift、signed right shift |
| ふりがな | さんじゅつみぎしふと |
| フリガナ | サンジュツミギシフト |
右方向にビットシフトする際に、左端のビットには「シフト前の値」をセットする方法。
「>>演算子」によるビットシフト。
右ビットシフトを行う際の、左端のビット処理には2種類ある。
・算術右シフト
「シフト前の値をセットする」方法。左端のビットが0であれば0、1であれば1をセットする。
・論理右シフト
「常に0をセットする」方法。左端のビットに関わらず常に0をセットする。
算術右シフトは左端のビットが1の場合には1をセットする。
これは、プラスマイナスの「符号」が左端のビットにあり、このビットの値をそのまま残すことで「正負を維持する」ことができ、さらに「ビットシフトによる計算」ができるためである。
int型等の整数型は、左端のビットが「符号」を表すビットとなっている。0がプラス、1がマイナスである。
算術右シフトは左端のビットを維持するため、この符号も維持される。つまり、マイナスの値を算術右シフトした結果はマイナスとなる。
さらに、整数型のマイナスの値は「2の補数」という形式で表現されており、いわば0と1が逆の状態となる。そのため、マイナスの場合に左端から1を追加していくことで、プラスの時に0が追加されるのと同じ結果となる。
ビットシフトは「2進数形式で桁を減らす」ことになるため、その結果は「シフト数だけ2で割る」こととなる(ただし余りが出る場合もある)。
マイナスの値の場合、左端に1を追加していくことでこの計算を行うことができる。
つまり、算術右シフトを行うことで、マイナスの場合にも「シフト数だけ2で割る」という計算を行うことができる。
この「計算ができる」という点が「算術」の理由である。
算術右シフトはこのように「計算を行うためのビットシフト」である。
純粋に「ビットを移動したい」という場合には不便なため、その場合には「論理右シフト」を使用した方がいいだろう。
左方向は「<<演算子」による「左シフト」のみである。「算術左シフト」「論理左シフト」は存在しない。
符号のビットは左端にあり、右端のビットは単なる「2進数での一番小さい桁」である。そのため、「<<演算子」は常に0をセットする。「算術」「論理」といった違いが意味をなさないことになる。
「>>演算子」によるビットシフト。
右ビットシフトを行う際の、左端のビット処理には2種類ある。
・算術右シフト
「シフト前の値をセットする」方法。左端のビットが0であれば0、1であれば1をセットする。
・論理右シフト
「常に0をセットする」方法。左端のビットに関わらず常に0をセットする。
算術右シフトは左端のビットが1の場合には1をセットする。
これは、プラスマイナスの「符号」が左端のビットにあり、このビットの値をそのまま残すことで「正負を維持する」ことができ、さらに「ビットシフトによる計算」ができるためである。
int型等の整数型は、左端のビットが「符号」を表すビットとなっている。0がプラス、1がマイナスである。
算術右シフトは左端のビットを維持するため、この符号も維持される。つまり、マイナスの値を算術右シフトした結果はマイナスとなる。
さらに、整数型のマイナスの値は「2の補数」という形式で表現されており、いわば0と1が逆の状態となる。そのため、マイナスの場合に左端から1を追加していくことで、プラスの時に0が追加されるのと同じ結果となる。
ビットシフトは「2進数形式で桁を減らす」ことになるため、その結果は「シフト数だけ2で割る」こととなる(ただし余りが出る場合もある)。
マイナスの値の場合、左端に1を追加していくことでこの計算を行うことができる。
つまり、算術右シフトを行うことで、マイナスの場合にも「シフト数だけ2で割る」という計算を行うことができる。
この「計算ができる」という点が「算術」の理由である。
算術右シフトはこのように「計算を行うためのビットシフト」である。
純粋に「ビットを移動したい」という場合には不便なため、その場合には「論理右シフト」を使用した方がいいだろう。
左方向は「<<演算子」による「左シフト」のみである。「算術左シフト」「論理左シフト」は存在しない。
符号のビットは左端にあり、右端のビットは単なる「2進数での一番小さい桁」である。そのため、「<<演算子」は常に0をセットする。「算術」「論理」といった違いが意味をなさないことになる。
参考サイト
- (参考サイトはありません)
// Sample.java
public class Sample
{
public static void main( String[] args )
{
long l;
// -8を右に2ビットシフトします。
// 左端に1が入っていることを確認してください。
l = -8;
System.out.println( l );
outputLongBit( l );
// -8
// 1111111111111111111111111111111111111111111111111111111111111000
l = l >> 2;
System.out.println( l );
outputLongBit( l );
// -2
// 1111111111111111111111111111111111111111111111111111111111111110
// このように、>>演算子による「算術右シフト」を行うと、
// 符号が維持されます。
// さらに、シフト数だけ2で割った値になります。
// このように「計算」を行うために使用するため「算術右シフト」と
// いいます。
// 参考:>>>演算子による「論理右シフト」の場合。
l = -8;
l = l >>> 2;
System.out.println( l );
outputLongBit( l );
// 4611686018427387902
// 0011111111111111111111111111111111111111111111111111111111111110
// このように、左端のビットに0がセットされることで、
// 値としては変になりますが、ビットとしてはむしろ
// こちらの方が希望する結果でしょう。
}
/**
* long型変数をビット形式で出力します。
*/
private static void outputLongBit( long l )
{
// long型変数をビット形式で文字列化します。
String source = Long.toBinaryString( l );
// 左0埋めします。
StringBuffer strbuf = new StringBuffer();
for( int iF1 = source.length(); iF1 < 64; ++iF1 )
{
strbuf.append( "0" );
}
strbuf.append( source );
System.out.println( strbuf.toString() );
}
}
public class Sample
{
public static void main( String[] args )
{
long l;
// -8を右に2ビットシフトします。
// 左端に1が入っていることを確認してください。
l = -8;
System.out.println( l );
outputLongBit( l );
// -8
// 1111111111111111111111111111111111111111111111111111111111111000
l = l >> 2;
System.out.println( l );
outputLongBit( l );
// -2
// 1111111111111111111111111111111111111111111111111111111111111110
// このように、>>演算子による「算術右シフト」を行うと、
// 符号が維持されます。
// さらに、シフト数だけ2で割った値になります。
// このように「計算」を行うために使用するため「算術右シフト」と
// いいます。
// 参考:>>>演算子による「論理右シフト」の場合。
l = -8;
l = l >>> 2;
System.out.println( l );
outputLongBit( l );
// 4611686018427387902
// 0011111111111111111111111111111111111111111111111111111111111110
// このように、左端のビットに0がセットされることで、
// 値としては変になりますが、ビットとしてはむしろ
// こちらの方が希望する結果でしょう。
}
/**
* long型変数をビット形式で出力します。
*/
private static void outputLongBit( long l )
{
// long型変数をビット形式で文字列化します。
String source = Long.toBinaryString( l );
// 左0埋めします。
StringBuffer strbuf = new StringBuffer();
for( int iF1 = source.length(); iF1 < 64; ++iF1 )
{
strbuf.append( "0" );
}
strbuf.append( source );
System.out.println( strbuf.toString() );
}
}
// Sample.java
public class Sample
{
public static void main( String[] args )
{
long l;
// -8を右に2ビットシフトします。
// 左端に1が入っていることを確認してください。
l = -8;
System.out.println( l );
outputLongBit( l );
// -8
// 1111111111111111111111111111111111111111111111111111111111111000
l = l >> 2;
System.out.println( l );
outputLongBit( l );
// -2
// 1111111111111111111111111111111111111111111111111111111111111110
// このように、>>演算子による「算術右シフト」を行うと、
// 符号が維持されます。
// さらに、シフト数だけ2で割った値になります。
// このように「計算」を行うために使用するため「算術右シフト」と
// いいます。
// 参考:>>>演算子による「論理右シフト」の場合。
l = -8;
l = l >>> 2;
System.out.println( l );
outputLongBit( l );
// 4611686018427387902
// 0011111111111111111111111111111111111111111111111111111111111110
// このように、左端のビットに0がセットされることで、
// 値としては変になりますが、ビットとしてはむしろ
// こちらの方が希望する結果でしょう。
}
/**
* long型変数をビット形式で出力します。
*/
private static void outputLongBit( long l )
{
// long型変数をビット形式で文字列化します。
String source = Long.toBinaryString( l );
// 左0埋めします。
StringBuffer strbuf = new StringBuffer();
for( int iF1 = source.length(); iF1 < 64; ++iF1 )
{
strbuf.append( "0" );
}
strbuf.append( source );
System.out.println( strbuf.toString() );
}
}




