情報学部 菅沼ホーム 全体目次 演習解答例 付録 索引

第4章 演算子

  1. 4.1 関係演算子,等値演算子,及び,論理演算子
    1. (プログラム例 4.1 ) 関係式と論理式
  2. 4.2 ビット演算子とシフト演算子
    1. (プログラム例 4.2 ) ビット演算とシフト演算
  3. 4.3 その他の演算子
  4. 演習問題4

  この章では,第3章で説明しなかった Java の演算子について説明します.急ぐ場合には,4.1 節を除いて,この章を読み飛ばしても構いません.

  演算の実行は,優先順位の高い演算子から,また,左から順に行われるのが基本です.しかし,あまり演算子の優先順位に頼り複雑な式を書くと,非常に読みにくくなります.できる限り,カッコを付けて書くことを勧めます.

4.1 関係演算子,等値演算子,及び,論理演算子

  関係演算子等値演算子は,2 つの数値などを比較し,その結果に従い,真または偽を返す演算を行います.真,偽を表す論理値は boolean 型で表現され,truefalse という論理型定数が定義されています.そのため,論理値に対して,C/C++ のように整数として加減乗除を行うことは不可能です(プログラム例 4.1 参照).Java で使用できる関係演算子には,以下のようなものがあります.
>  より大きい  a > b   式 a の値が式 b の値より大きいとき真
<  より小さい  a < b   式 a の値が式 b の値より小さいとき真
>= 以上     a >= b  式 a の値が式 b の値以上のとき真
<= 以下     a <= b  式 a の値が式 b の値以下のとき真		
また,等値演算子には,以下のようなものがあります.
== 等しい    a == b  式 a の値と式 b の値が等しいとき真
!= 等しくない  a != b  式 a の値と式 b の値が等しくないとき真		
  論理演算子は,論理演算(論理和,論理積,否定)を行うための演算子であり,以下のようなものがあります.
|| 論理和  x || y  式 x が真か,または,式 y が真のとき真
&& 論理積  x && y  式 x が真で,かつ,式 y が真のとき真
!  否定    ! x      式 x が偽のとき真		
  よく犯す誤りに以下のようなものがあります.例えば,x の値が 0 と 5 の間にあるか(つまり,数学的に書けば,0 < x < 5 )否かを調べたいとします.このとき,数学と全く同じように,
0 < x < 5		
と書いてしまう人を多く見受けます.「演算子は,前から順番に実行される」ということを思い出してください.上のように記述すると,まず,「 0 < x 」の演算が行われます.次に,「その結果 < 5 」の演算が行われます.例えば,x の値が -1 である場合について考えてみます.「 0 < x 」の演算により結果は false になります.次に,「 false < 5 」の演算が行われることになりますが,false と 整数との比較は出来ませんので.コンパイルエラーになってしまいます.目的とする判断を行わせるためには,
(0 < x) && (x < 5)		
と記述してやる必要があります(カッコは必ずしも必要ない).

(プログラム例 4.1 ) 関係式と論理式 

01	/****************************/
02	/* 関係式と論理式           */
03	/*      coded by Y.Suganuma */
04	/****************************/
05	import java.io.*;
06
07	public class Test {
08		public static void main(String args[])
09		{
10			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
11	
12			try {
13		/*
14				データの入力
15		*/
16				int a = 10, b = 20;
17				System.out.println("a = " + a + "  b = " + b);
18				System.out.print("整数データを1つ入力して下さい ");
19				int x = Integer.parseInt(in.readLine());
20		/*
21					出力
22		*/
23	//			System.out.println("a < -1 < b ? " + (a < -1 < b));
24				System.out.println("a < x < b ? " + ((a < x) && (x < b)));
25				System.out.println("x < a or x > b ? " + ((x < a) || (x > b)));
26	//			System.out.println("~(a + b + x) ? " + (!(a + b + x)));   許されません
27				System.out.println("a = b ? " + (a == b));
28				System.out.println("a ≠ b ? " + (a != b));
29			}
30			catch (IOException ignored) {}
31		}
32	}
		
16 行目

  int 型変数 a,b に対する型宣言と共に,初期値として,変数 a,b に,10,及び,20 を代入しています.

23, 26 行目

  論理型は整数型とは明確に区別されていますので,このように整数型から論理型に変換することは不可能です.
  入力データとして,15 を与えると,このプログラムは以下の結果を出力します.
a < x < b ? true
x < a or x > b ? false
a = b ? false
a ≠ b ? true		

4.2 ビット演算子とシフト演算子

  ビット演算子は,ビット毎の論理演算(論理和,論理積,排他的論理和等)を行うための演算子です.演算子で結合されたデータ(単項演算子の場合はデータそのもの)の対応するビット同士で与えられた演算を行います.以下に示すような演算子を使用できます.
| 論理和      x | y   対応するビットのいずれかが 1 のとき 1,そうでないときは 0
& 論理積      x & y   対応するビットの双方が 1 のとき 1,そうでないときは 0
^ 排他的論理和 x ^ y   対応するビットが異なるのとき 1,そうでないときは 0
~ 1の補数     ~ x      ビット毎に 1 と 0 を反転する		
  論理和は特定のビットを 1 に設定,また,論理積はあるビット列だけを取り出す等のために使用されます.排他的論理和は,繰り上がりを無視した 1 ビット同士の加算に相当します.

  シフト演算子は,整数型または文字型のデータを表すビット列を指定された数だけ左,または,右にシフトするための演算子であり,次の 3 種類が存在します.
<< 左にシフト  x << 3  3 ビット左にシフト.x を 23 倍することに相当.
>> 右にシフト  x >> 3  3 ビット右にシフト.x を 23 で割ることに相当.
>>> 右にシフト  x >> 3  3 ビット右にシフト(空いた場所に 0 を補充)		
  左にシフトする場合は,下に示すように,指定された数だけビットをシフトした後,空いた場所に 0 が補充されます.
11111001  →  3 ビット左にシフト  →  11001000		
  しかし,右にシフトする場合は気を付ける必要があります.int 型の最も左のビット(最上位ビット)は符号を表します.従って,左シフトと同様,すべてのビットが右にシフトされ,空いた場所に 0 が補充されると,符号が変わってしまう場合があります.そこで,通常の右シフト演算子 >> においては,最も左のビット(最上位ビット)は変化せず,空いた場所には最上位ビットと同じビットが補充されるようなシフトが行われます.しかし,左シフトと同様,すべてのビットが右にシフトされ,空いた場所に 0 が補充されるようなシフトを行いたい場合もあります.そこで,Java には,そのようなシフトを実行する右シフト演算子 >>> が存在します.
(1)>>    11001111  →  3 ビット右にシフト  →  11111001
(2)>>>   11001111  →  3 ビット右にシフト  →  00011001		

(プログラム例 4.2 ) ビット演算とシフト演算 

/******************************/
/* ビット演算子とシフト演算子 */
/*      coded by Y.Suganuma   */
/******************************/
import java.io.*;

public class Test {
	public static void main(String args[])
	{
	/*
	         ビット演算子
	*/
		int x1 = 0x00000031, x2 = 0xfffffff2;
		int y1 = x1 & 0x0000000f;     // 下位4ビットの取り出し
		int y2 = x2 & 0x0000000f;     // 下位4ビットの取り出し
		int z1 = y1 ^ y2;             // 排他的論理和(和になっている)
		int z2 = ~z1 + 1;             // -3 に対する2の補数表現
		System.out.println("ビット演算子");
		System.out.println("   y1 " + Integer.toHexString(y1) + "(" + y1 +
                           ") y2 " + Integer.toHexString(y2) + "(" + y2 + ")");
		System.out.println("   z1 " + Integer.toHexString(z1) + "(" + z1 +
                           ") z2 " + Integer.toHexString(z2) + "(" + z2 + ")");
	/*
	         シフト演算子
	*/
		int a = -3, b = 3;
		y1 = a << 3;              // 左に3ビットシフト(負)
		y2 = b << 3;              // 左に3ビットシフト(正)
		System.out.println("シフト演算子");
		System.out.println("   y1 " + Integer.toHexString(y1) + "(" + y1 +
                           ") y2 " + Integer.toHexString(y2) + "(" + y2 + ")");
		y2 = y1;                  // -24
		y1 = y1 >> 3;             // 右に3ビットシフト(1/8倍)
		y2 = y2 >>> 3;            // 右に3ビットシフト(1/8倍,0をつめる)
		System.out.println("   y1 " + Integer.toHexString(y1) + "(" + y1 +
                           ") y2 " + Integer.toHexString(y2) + "(" + y2 + ")");
	}
}
		

  このプログラムは以下の結果を出力します.ビット演算子とシフト演算子の働きを十分理解して下さい.なお,上のプログラムにおいて,toHexString は,Integer クラスのメソッドであり,整数を 16 進文字列に変換します.
ビット演算子
   y1 1(1) y2 2(2)
   z1 3(3) z2 fffffffd(-3)
シフト演算子
   y1 ffffffe8(-24) y2 18(24)
   y1 fffffffd(-3) y2 1ffffffd(536870909)		

4.3 その他の演算子

  3.2.2 節で説明した以外にも,ある変数に演算した結果をその変数に記憶する演算子を,「<<」,「>>」,「>>>」,「&」,「|」,及び,「^」に対しても,使用できます.
<<=  x <<= 3  x を 3 ビット左にシフトして,その結果を x に代入
>>=  x >>= 3  x を 3 ビット右にシフトして,その結果を x に代入
>>>=  x >>>= 3  x を 3 ビット右にシフトして,その結果を x に代入(符号ビット無視,C/C++ には無い)
&=   x &= y   x と y のビット毎の論理積を計算し,その結果を x に代入
|=   x |= y   x と y のビット毎の論理和を計算し,その結果を x に代入
^=   x ^= y   x と y のビット毎の排他的論理和を計算し,その結果を x に代入		
  例えば,「もし,y の値が 5 より大きければ,x に 10 を代入し,そうでなければ,20 を代入する」といった処理を行いたいとします.このようなとき,利用されるのが条件演算子です.条件演算子は,一般的に,
式1 ? 式2 : 式3		
と書かれ,式 1 が真のときは式 2 の値がとられ,そうでなければ式 3 の値がとられます.例えば,先の例の場合は,
x = (y > 5) ? 10 : 20;		
と書けば良いことになります.

演習問題4

[問1]次の演算結果がどのようになるかを見るための適当なプログラムを書き,その実行結果から演算結果について説明せよ.
(1)x=(a==10)
(2)(c >='a') && (c<='z')

[問2]整数データの上位 4 ビットと下位 4 ビットを,それぞれ 2 進数 4 ビットの正の整数とみなし,それらを加えて結果を出力するプログラムを書け.

[問3]すべてのビットを反転した後,最上位ビットに 1 をセットするプログラムを,排他的論理和と論理和を使用して書け.

[問4]整数データを 9 倍する演算を,ビットシフトと加算を利用して行うプログラムを書け.

情報学部 菅沼ホーム 全体目次 演習解答例 付録 索引