基本的に、四則演算は、常識のとおりに機能する。「+」は足し算、「-」は引き算、「*」は掛け算、「/」は割り算である。ただし、Visual Basicプログラマーはいくつか注意が必要である。これらの演算子は、そのままではオーバーフローをチェックしない。そのため、値が桁あふれを起こした場合、単純にあふれた桁を捨てた値になる。最小値と最大値は、データ型によって異なり、また、符号付きと符号なしでも異なる。ベテラン・プログラマーは、桁あふれ分が消えてしまうことを前提にプログラムを書くこともあるが、完全にオーバーフロー時の動作を把握できない場合は、「オーバーフロー、アンダーフローしないようにプログラムを書く」ということを心掛けよう。そうしなければ、出力結果の3〜5行目、7〜8行目、10〜11行目のような、一見でたらめな結果を得ることになる。
3: 2147483647+1 = -2147483648
4: 2147483647u+1u = 2147483648
5: 4294967295u+1u = 0
6: 3-2 = 1
7: -2147483648-1 = 2147483647
8: 0u-1u = 4294967295
9: 3*2 = 6
10: 2147483647*2 = -2
11: 2147483647u*2u = 4294967294
割り算には別の注意がある。整数と整数の割り算は整数になり、端数が出ても小数形式に変換されたりしない。小数の割り算を行う場合は、浮動小数点数と浮動小数点数の割り算として行わなければならない。12〜13行目が整数の割り算で、14行目が浮動小数点数の割り算である。
12: 6/3 = 2
13: 6/5 = 1
14: 6.0/5.0 = 1.2
「%」は割り算を行ったときの余りを得る演算子である。出力結果の15行目は6割る3の余りが0であることを示す。16行目は6割る5の余りが1であることを示す。剰余演算子は整数で使う。
15: 6%3 = 0
16: 6%5 = 1
数値の大小と一致を比較する演算子である。演算の結果は、条件が成立すればtrue、成立しなければfalseという値になる。Visual Basicプログラマーは、一見似て非なる書式に注意しなければならない。Visual Basicでは一致は「=」だが、C#では「==」と2文字のイコール記号を記述する。不一致は、「<>」ではなく、「!=」と書く。また、「=>」や「=<」はVisual Basicでは大丈夫だが、C#では使えない。
17: 1<2 = True
18: 2<1 = False
19: 3<3 = False
20: 1>2 = False
21: 2>1 = True
22: 3>3 = False
23: 1<=2 = True
24: 2<=1 = False
25: 3<=3 = True
26: 1>=2 = False
27: 2>=1 = True
28: 3>=3 = True
29: 1==2 = False
30: 2==1 = False
31: 3==3 = True
32: 1!=2 = True
33: 2!=1 = True
34: 3!=3 = False
「is」は、データの型を判定する。数値計算を行うほかの演算子とは少々性格が異なる。「is」の手前には任意の値を書き、後ろにはデータ型の名前を書く。もちろん、クラス名もOKである。出力結果の35〜36行目を見ると分かるが、整数の1はint型なので、「1 is int」は成立する。成立した場合はtrueの値になる。しかし、1.0は実数表記なので、整数の一種であるint型ではありえない。従って、「1.0 is int」はfalseという値になる。
35: 1 is int = True
36: 1.0 is int = False
「&」はAND演算を、「^」はXOR演算を、「|」はOR演算を行う。出力結果の37〜45行目は、trueとfalseを相手にそれぞれの演算子を適用した場合を示す。AND、XOR、ORの演算子の意味を知っていれば、結果は歴然だろう。分かりにくいのは61〜63行目で、数値を相手にこれらの演算子を使った場合だ。これらは数値を構成するビットごとに論理演算を適用することになる。ビット表現を理解しているプログラマーにのみ意味がある使い方だろう。
37: false&false = False
38: true&false = False
39: true&true = True
40: false^false = False
41: true^false = True
42: true^true = False
43: false|false = False
44: true|false = True
45: true|true = True
61: 1&3 = 1
62: 1^3 = 2
63: 1|3 = 3
この演算子は3つの値を持ち、それらを「?」記号と「:」記号で分離する。「式1?式2:式3」という順番に書き、式1の結果次第で、式2と式3のどちらを解釈するかを決める。プログラミング言語ふうに書けば、「if( 式1 ) 式2 else 式3」という感じだ。そして、この演算子全体が結果として得る値は、式2か式3の中で評価された値ということになる。出力結果の46〜47行目が実際に実行した場合を示す。ここでは式1として、trueやfalseを書いているが、実際には、実行時に値が変化するような式を書く。
46: false ? 1 : 2 = 2
47: true ? 1 : 2 = 1
シフト演算子はビットシフトを行う。「<<」は左シフト、「>>」は右シフトを示し、演算子の後ろに書く値がシフトするビット数を示す。昔は、2のべき乗数の掛け算と割り算をシフトで行うというテクニックがあったが、その程度のことなら、現在ではコンパイラの最適化機能が自動的にやってくれるので意識する必要性はほとんどないだろう。ビット表現を理解するプログラマーだけがシフト演算子を使うべきであり、それ以外のプログラマーは手を出さないほうがよいだろう。
53: 256>>1 = 128
54: 256<<1 = 512
55: 2147483647>>1 = 1073741823
56: 2147483647<<1 = -2
57: 2147483647u>>1 = 1073741823
58: 2147483647u<<1 = 4294967294
59: -2147483648>>1 = -1073741824
60: -2147483648<<1 = 0
単項演算子は値の手前に付ける演算子である。「+」は値の符号を変えないという機能を持つ(つまり何もしない)。「-」は値の符号を反転させる。「!」はtrueとfalseを逆転させる(not演算)。「~」は「!」と似ているが、ビット単位で数値を反転させる(1の補数を取る)。これらは、2項演算子、つまり前後に値が付く使い方をした場合と機能が異なることに注意が必要である。例えば、「x-y」は2項演算子として「-」を使っており、「-x」は単項演算子として「-」を使っている。
48: +(2+3) = 5
49: -(2+3) = -5
50: !true = False
51: !false = True
64: ~1 = -2
65: ~1u = 4294967294
66: ~-1 = 0
変数の前後に「++」あるいは「--」という演算子を付けることができる。「++」は変数の値に1を加え変数に戻す。「--」は変数の値から1を引き変数に戻す。出力結果の68〜71行目を見ると分かるだろう。68行目で0にセットされた変数xの値が、「x++」を表示するごとに増えていく。変数xの値が変わるのは、++演算子の効力によるものだ。同じように76〜79行目を見れば、「--」の働きで値が減っていく様子が分かると思う。
68: set x=0
69: ++x = 1
70: ++x = 2
71: ++x = 3
72: set x=0
73: x++ = 0
74: x++ = 1
75: x++ = 2
76: set x=0
77: --x = -1
78: --x = -2
79: --x = -3
80: set x=0
81: x-- = 0
82: x-- = -1
83: x-- = -2
さてここで問題なのは、「++」や「--」を変数の前に書くか後ろに書くかである。前と後ろでは結果が異なる。68〜71行目と72〜75行目の違いは、「++」をxの手前に書いたか後ろに書いたかの違いだけによるものである。しかし、結果としてはまったく異なっている。「++」を手前に書くと、変数xの値を利用する前に1足される、という意味になる。一方、「++」を後に書くと、変数xの値を利用した後で1が足される、という意味になる。つまり、「出力される前か後か」という相違になる。
「++」と「--」は単独で使われることがある。つまり、「x++」とだけ書いて、その値をまったく利用しないというやり方だ。しかし、変数の中身は書き換えられるので、変数に1を足す(あるいは引く)ときには、「x = x + 1;」よりも「x++;」のほうが簡潔なため、よく用いられる。
Copyright© Digital Advantage Corp. All Rights Reserved.