B.演算子

 Copyright(C) 13Jan2003 coskx TNCT

演算子についての説明である。内容は以下のとおりである。
1.Javaにおける算術演算子
2.Javaにおけるビット演算子
3.Javaにおける条件の表現

APPENDIX 1 BOOL演算
APPENDIX 2 演算子の優先順位

B.1 Java言語における算術演算子

算術演算子
演算子

意味

=

左辺の値を右辺の変数に代入する
例 x = a+b;  「a+b=x;」とは書けない
(右辺と左辺が等しいと言う意味ではない)

+

加算

-

減算

*

乗算「×」

/

除算「÷」

%

剰余(割ったあまりを求める)
整数演算のみ有効
例 a%b aをbで割ったあまりを求める演算

++

「a++」「++a」は「a=a+1」と同じ
「c=a++;」は「c=a; をして次に a++; をする」の意味
「c=++a;」は「++a; をして次に c=a; をする」の意味

--

「a--」「--a」は「a=a-1」と同じ
「c=a--;」は「c=a; をして次に a--; をする」の意味
「c=--a;」は「--a; をして次に c=a; をする」の意味

+=

「a+=b;」は「a=a+b;」の意味

-=

「a-=b;」は「a=a-b;」の意味

*=

「a*=b;」は「a=a*b;」の意味

/=

「a/=b;」は「a=a/b;」の意味

%=

「a%=b;」は「a=a%b;」の意味

加減乗除の優先順位

加減乗除の優先順位は算数の常識と同じであり,乗除が優先し加減はその後である。
乗除算同士の場合,あるいは加減同士の場合は左から順に行なわれる。
ここでは定数で説明しているが,値の代入された変数の場合でも同様である。

例 100/2*3  →(100/2)*3 →50*3 →150
  100/(2*3)  →100/6 →16
  100/2/5  →(100/2)/5 →50/5 →10
  10*2+2*4 →(10*2)+(2*4) →20+8 →28
  20*(2+2)*4 →20*4*4 →80*4 →320

整数と実数の混合演算

整数と実数の混合演算の時には混合演算が起こる場面で整数が実数化されて演算される。
値の代入された変数の場合でも同様である。


  100/3.0  →100.0/3.0 →33.33333
  100/(2.0*3)  →100/(2.0*3.0)  →100/6.0  →100.0/6.0 →16.66667
  100.0*(1/2)  →100.0*0 →100.0*0.0 →0.0 (1/2は整数演算なので小数点以下は切り捨てられ0になる)
  100*(1.0/2)  →100*(1.0/2.0) →100*0.5 →100.0*0.5 →50.0
  (4/3)*10.0 →1*10.0 →1.0*10.0 →10.0
  (4.0/3)*10 →(4.0/3.0)*10 →1.333333*10 →1.333333*10.0 →13.33333

変数を用いた例
  int a=11,b=12,c;
  double d;
    とする
  c=(a+b)/2 →(11+12)/2 →23/2 →c=11 cには11が入る
  d=(a+b)/2.0 →(11+12)/2.0 →23/2.0 →23.0/2.0 →d=11.5 dには11.5が入る
  c=(a+b)/2.0 →(11+12)/2.0 →23/2.0 →23.0/2.0 →c=11.5 cには11が入る(cはint型なので)
  d=(a+b)/2 →(11+12)/2 →23/2 →d=11 dには11.0が入る

  cast演算(型変換演算)の例
  (double)aの表現は,int型変数aを一時的にdouble型変数とみなせという意味になる

  d=((double)a+(double)b)/2.0 →((double)11+(double)12)/2.0
    →(11.0+12.0)/2.0 →23.0/2.0 →d=11.5 dには11.5が入る
  d=((double)a+b)/2 →((double)11+12)/2 →(11.0+12)/2
    →(11.0+12.0)/2 →23.0/2 →23.0/2.0 →d=11.5 dには11.5が入る

++,--について

「++」「--」は,変数の前に置かれた場合は前置演算子,変数の後に置かれた場合は後置演算子と呼ばれる。

例 後置演算子
 y=x++;   printf("n=%d\n",n++);   *p++=*q++;   i++;
 y=x--;   printf("n=%d\n",n--);   *p--=*q--;   i--;
例 前置演算子
 y=++x;   printf("n=%d\n",++n);   *(++p)=*(++q);   ++i;
 y=--x;   printf("n=%d\n",--n);   *(--p)=*(--q);   --i;

後置演算の意味
 式を評価して作業が終わったら,後置演算を行う。

意味
y=x++;  y=x を実行してから,x=x+1を実行
System.out.printf("n=%d\n",n++); printf("n=%d\n",n) を実行してから,n=n+1
*p++=*q++; *p=*qを実行してから,p=p+1,q=q+1
(演算子の優先順位より,*(p++)=*(q++);の意味になる)
i++;

これは単にi=i+1

前置演算の意味
 先に前置演算を行い,次に式を評価して作業を行う。

意味
y=++x;  x=x+1 を実行してから,y=xを実行
System.out.printf("n=%d\n",++n); n=n+1 を実行してから,printf("n=%d\n",n)
*(++p)=*(++q); p=p+1,q=q+1を実行してから,*p=*q
++i;

これは単にi=i+1 (i++;と動作は同じ)



プログラムの一部 実行結果
int x=100,y=100;
System.out.printf("x=%d y=%d\n",++x,y++);
System.out.printf("x=%d y=%d\n",x,y);
x=101 y=100
x=101 y=101

等号についての補足(中級者向け説明)
「a=b;」は「bの値をaに代入する」という意味であった。
ところでJava言語では式「a=b」そのものが値を持ち,「c= (a=b)」が意味を持つ。『「a=b」そのものの値』とは「左辺に代入された値」のことである。すなわち,「c=(a=b)」では,まず始めにbの値が aに代入され,次に『式「a=b」の値』(それはaの値)がcに代入されるということになる。次のプログラムの実行状況を追跡するとこのことが確認でき る。
List 等号についての補足

class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int a;
        double x=2.5;
        double y;
        y=a=(int)x;
        System.out.printf("x=%.2f a=%d y=%.02f\n",x,a,y);
        y=(a=(int)x);
        System.out.printf("x=%.2f a=%d y=%.02f\n",x,a,y);
        System.out.printf("(a=x) = %d\n",(a=(int)x));
    }
}



/*****実行結果*****
x=2.50 a=2 y=2.00
x=2.50 a=2 y=2.00
(a=x) = 2
******************/


String (文字列)における「+」
文字列の加算は文字列の連結になる。
さらに文字列に数値や変数を加えると,連結された文字列になる。

文字列加算のサンプルプログラム
class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int x=987;
        int y=654;
        System.out.println("abc"+"def");
        System.out.println("abc"+120);
        System.out.println(""+120+130);
        System.out.println(""+(120+130));
        System.out.println("abc"+x);
        System.out.println("abc"+x+y);
        System.out.println("abc"+(x+y));
    }
}
実行結果
abcdef
abc120
120130
250
abc987
abc987654
abc1641


B.2 Javaにおけるビット演算子

ビット演算は整数型変数(char型,int型など)に対して行なわれる演算である。変数のビットパターンに対する演算である。

(1)シフト演算

演算子

意味

<<

左シフト

>>

右シフト(算術右シフト,負の数の場合は最上位ビットに1を埋める)

>>>
右シフト(論理右シフト,負の数の場合でも最上位ビットに0を埋める)

この演算は,整数におけるコンピュータの内部表現において,右や左にずらす演算である。(もともとコンピュータ内部で数値は,2進数で扱われているビットパターンである)
例えば
「12<<3」は12を左に3つずらす意味であり,12はビットパターンで表すと「1100」なので左に3つずらすと「1100000」となりこれは96である。
「12>>2」は12を右に2つずらす意味であり,12はビットパターンで表すと「1100」なので右に2つずらすと「11」となりこれは3である。
一般に整数を左に1つずらすと2倍になり,2つずらすと4倍になり,3つずらすと8倍になり4つずらすと16倍になる。逆に右に1つずらすと1/2倍になり,2つずらすと1/4倍になり,3つずらすと1/8倍になり,4つずらすと1/16倍になる。

int x,y;
の時
y=x/1024;

y=x>>10;
は同じ意味になる。

(2)論理演算

演算子

意味

&

ビットごとのand演算

|

ビットごとのor演算

^

ビットごとのxor演算(排他的OR)

~

全ビット反転


 「157&241」はビットパターンでは「10011101&11110001」となり,以下のように結果は10010001すなわち145となる

  1001 1101
& 1111 0001 ビットごとに縦にアンド演算を行う。繰り上がり繰り下がりはない。
-------------
  1001 0001

 

2進法表現

16進法表現

10進法表現

第1変数

1001 1101

9D

157

第2変数

1111 0001

F1

241

結果

1001 0001

91

145

例 「157|241」はビットパターンでは「10011101|11110001」となり,以下のように結果は11111101すなわち253となる

  1001 1101
| 1111 0001 ビットごとに縦にオア演算を行う。繰り上がり繰り下がりはない。
-------------
  1111 1101

 

2進法表現

16進法表現

10進法表現

第1変数

1001 1101

9D

157

第2変数

1111 0001

F1

241

結果

1111 1101

FD

253

 「157^241」はビットパターンでは「10011101^11110001」となり,以下のように結果は01101100すなわち108となる

  1001 1101
^ 1111 0001 ビットごとに縦に排他オア演算を行う。繰り上がり繰り下がりはない。
-------------
  0110 1100

 

2進法表現

16進法表現

10進法表現

第1変数

1001 1101

9D

157

第2変数

1111 0001

F1

241

結果

0110 1100

6C

108

例 「~157」はビットパターンでは「~10011101」となり,byte型なら,8ビットのみなので,以下のように結果は01100010すなわち98となる

~ 1001 1101  ビットごとに反転演算を行う。繰り上がり繰り下がりはない。
-------------
  0110 0010

 

2進法表現

16進法表現

10進法表現

第1変数

1001 1101

9D

157

0110 0010

0

62

98

使用例

int k;
のもとで
if (k%256==0) {

if ((k&0xff)==0) {
と同じ意味になる。2のべき乗の時のみ使える

int k,k1,k2,k3;
のもとで

k1=k2=k3=0;
for (k=0; k<10000; k++) {
    k1++;
    k1&=3;
    k2++;
    k2&=7;
    k3++;
    k3&=0xf;
    :
    :
}

では
k1の値は0,1,2,0,1,2,0,1,2,・・・
のように0,1,2を繰り返し,
k2の値は0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,0,1,2,3,・・・
のように0,1,2,・・,7を
繰り返し,
k3の値は0,1,2,3,・・,13,14,15,0,1,2,3,・・,13,14,15,0,1,2,3,・・,13,14,15,0,1,2,3,・・
のように0,1,2,・・,13,14,15を繰り返す。

unsigned int x:
のもとで,

if (x&1==1)  はxの第0ビット(右端)が1だったらと意味になる.
if (x&2==2)  はxの第1ビット(右から2番目)が1だったらと意味になる.
if (x&4==4)  はxの第2ビット(右から3番目)が1だったらと意味になる.
if (x&8==8)  はxの第3ビット(右から4番目)が1だったらと意味になる.
if (x&0x10==0x10)  はxの第4ビット(右から5番目)が1だったらと意味になる.

(3)ビット演算子利用上の注意

ビット演算子の優先順位は低いので「()かっこ」を利用しておくとよい。
例 int k1,k2 のもとで
k2 = k1<<4+1;
はそのままでは
k2 = k1<<(4+1);
のように解釈される。もし
k2 = (k1<<4)+1;
の記述をしたければ,そのように書く必要がある。

同様に
if (k2 == (k1&0xff)) {
の代わりに
if (k2 == k1&0xff) {
はエラーとなる。


(4)「ビット演算子」+「=」

ビット演算子においても「&=」などの表現ができる。

意味

x <<= 3;

x = x<<3;

x >>= 4;

x = x>>4;

x &= 0xf;

x = x&0xf;

x |= 0x55;

x = x|0x55;

x ^= 0xffff;

x = x^0xffff;

B.3 Javaにおける条件の表現

条件式一覧
数学で「ab」と表現される関係をJava言語では「a<=b」と書く。同様な表現を以下の表に示す。
次のような使われ方をする。
while (a<=b)
if (a<=b)
while((b<a)&&(a<c))
数学の表現 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以下
a≧b a>=b aはb以上
a≠b a!=b aはbと等しくない
(a<b)or(c<a) (a<b)||(c<a) aはbより小さいか,またはaはcより大きい
(b<a)and(a<c) (b<a)&&(a<c) aはbより大きく,かつaはcより小さい
(a=b)and(c=d)and(e=f) (a==b)&&(c==d)&&(e==f) aとbが等しく,かつcとdが等しく,かつeとfが等しい
(b<a)and(a≠c) (b<a)&&(a!=c) または
(b<a)&&(!(a==c))
aはbより大きく,かつaはcと等しくない

ドモルガンの定理
ドモルガンの定理により同値な関係
!((a<b)&&(c<d)) (!(a<b))||(!(c<d))
!((a<b)||(c<d)) (!(a<b))&&(!(c<d))

よくある条件式の誤り(その1)
   表現
数学の表現 x<3,7<xの場合は.....
誤ったJavaによる表現 if (x<3,7<x) {
コンパイルエラーとなる

考え方

数学の表現をより論理的に書き直すと
「x<3または7<xの場合は.....」
となる
正しいJavaによる表現 if ( x<3 || 7<x ) {

よくある条件式の誤り(その2)
   表現
数学の表現 3≦x≦7の場合は.....
誤ったJavaによる表現 if (3<=x<=7) {
コンパイルエラーとなる

考え方

数学の表現をより論理的に書き直すと
「3≦xかつx≦7の場合は.....」
正しいJavaによる表現 if ( 3<=x && x<=7 ) {

条件の真偽のJavaでの取り扱い

Javaでは真偽をboolean値で表すことになっていて,偽はfalse,真はtrueということになっている。
例えば次のテストプログラムで「i<3」はboolean値を持ち,表示できる。

List 条件式の値の検証プログラム

class XXXX {
    public static void main(String[] args) {
        XXXX mainprg = new XXXX();
    }
 
    XXXX() {
        int i;
        boolean tf;
        for (i=0;i<5;i++) {
            tf=(i<3);
            System.out.printf("i=%d tf=%b ",i,tf);
            if (i<3) {
                System.out.printf("a i<3 ");
            } else {
                System.out.printf("a 3<=i ");
            }
            if (tf) {
                System.out.printf("b i<3\n");
            } else {
                System.out.printf("b 3<=i\n");
            }
        }
    }
}

/****実行結果****
i=0 tf=true a i<3 b i<3
i=1 tf=true a i<3 b i<3
i=2 tf=true a i<3 b i<3
i=3 tf=false a 3<=i b 3<=i
i=4 tf=false a 3<=i b 3<=i
****************/

例えば,同様に,引数で与えた文字が大文字であるかどうか調べる関数Character.isUpperCase(char ch)は,
偽ならfalse,真ならtrueを返すので
if (
Character.isUpperCase(ch)==true) {......

if (
Character.isUpperCase(ch)) {.........
は同じ意味になるため,通常は後者で記述される。

また永久ループは
while(true) {............
のように記述される。


 APPENDIX 1 BOOL演算

Javaで用いられるブール演算は基本的に4つあり,演算対象とする値はbooleanのtrueとfalseである。
(1)アンド演算(and)プログラム中での表現「&&」

演算

結果

false and false

false

false and true

false

true and false

false

true and true

true

「両方trueの組み合わせのみtrueで,その他の組み合わせはfalse」

演算

結果

x and false

false

x and true

x


(2)オア演算(or)プログラム中での表現「||」

演算

結果

false or false

false

false or true

true

true or false

true

true or true

true

「両方falseの組み合わせのみfalseで,その他の組み合わせはtrue」

演算

結果

x or false

x

x or true

true


(3)ノット演算(not)プログラム中での表現「!」

演算

結果

not false

true

not true

false

(4)イクスクルーシブオア演算(xor)(排他的論理和)プログラム中での表現「^」

演算

結果

false xor false

false

false xor true

true

true xor false

true

true xor true

false

「お互いに値が異なる組み合わせでtrue,お互いに同じ値の組み合わせはfalse」

演算

結果

x xor false

x

x xor true

not x

 APPENDIX 2 演算子の優先順位

Javaの演算子には実行優先順位がある。算術演算において乗算除算が加算減算に優先することも,Javaの演算子の実行優先順位に含まれている。

順位 演算子 説明

1

[ ]  ( )  .  後置 ++ と後置 -- [ ] は配列

2

前置 ++ と前置 -- ~ !

3

new new (型)x

5

*  /  % 2項演算子 乗算、除算、剰余

6

+ - 2項演算子 加算、減算

7

<< >> >>> ビットごとのシフト

8

< > <=  >= instanceof 関係演算子

9

==  != 関係演算子

10

& ビットごとの AND

11

^ ビットごとの排他的 OR

12

| ビットごとの OR

13

&& 条件論理の AND

14

|| 条件論理の OR

15

? : 3項演算子

16

=  *=  /=  %=
+=  -=  <<=  >>=  >>>=
&=  ^=  |=
単純代入と複合代入