1. はじめに
「演算子」とは、「足す」「引く」など、計算するためなどの記号ですよね。
Javaでは、複数の演算子があるのでご紹介しますー
2. 演算子
演算子の一覧をのせておきます
高 ↑ 優 先 度 ↓ 低 |
++( 後置 ) | --( 後置 ) | ||||||||||||
++ ( 前置 ) |
-- ( 前置 ) |
+ ( 単項 ) |
- ( 単項 ) |
~ | ! | |||||||||
* | / | % | ||||||||||||
+ | - | |||||||||||||
<< | >> | >>> | ||||||||||||
< | > | <= | >= | |||||||||||
== | != | |||||||||||||
& | ||||||||||||||
^ | ||||||||||||||
| | ||||||||||||||
&& | ||||||||||||||
|| | ||||||||||||||
?: | ||||||||||||||
= | += | -= | *= | /= | %= | &= | ^= | |= | <<= | >>= | >>>= |
上から順番に演算子の優先度は高くなります。
例えば +(加算) より *(乗算)が高い といった感じ。
また、優先度を高くしたい場合は、数学と同様に ( ) で囲んであげれば優先して演算されるようになります。
では、なるべく簡単な順になるよう、いくつかの使用頻度の高い演算子の使い方を紹介します。
2.1. +, - (単項)
単項という補足があるのは変数などの前に演算子を置いたものであり、加算や減算ではないということ。
例えば以下のコードのようなもの。
public class Main {
public static void main(String[] args) {
int i = 10;
// -10と出力
System.out.println(-i);
}
}
出力の際にiの前に「-」をつけたので、「-10」と表示されました。
これに関してはこれぐらいの説明で実際に動かしてみるのが、一番かと。。
2.2. *, /, %, +, -
これらは「算術演算子」です。
計算用の演算子たちです。
+ は「加算」です。
足し算のことですね。
- は「減算」です。
引き算のことです。
* は「乗算」です。
かけ算ですね。
/ は「除算」です。
わり算のことですが、余りは表示されません。
そして、整数同士で除算を行うと、小数点以下は表示されません。
小数点以下を表示したい場合は、どちらか一方を double 型などにしてあげるか、3.0 のように明示的に小数点を記述など色々方法はあります。
% は「剰余」。余りの演算になります。
例とすると、9 % 2 は、 1 になります。
これらを使ったソースを載せておきます。
public class Main {
public static void main(String[] args) {
// 加算
System.out.println(10 + 5); // 15
// 減算
System.out.println(10 - 5); // 5
// 乗算
System.out.println(10 * 5); // 50
// 除算 ( 整数 )
System.out.println(13 / 5); // 2
double i = 13;
// 除算 ( 小数 )
System.out.println(i / 5); // 2.6
// 剰余
System.out.println(13 % 5); // 3
}
}
2.3. =, +=, -=, *=, /=, %=
これらは「代入演算子」と呼ばれるものです。
= は、右辺の値を左辺に代入するというもので、変数の勉強の時何度か使いました。
+= は、( 左辺の値 + 右辺の値 )を代入します。
-= は、( 左辺の値 - 右辺の値 )を代入します。
*= は、( 左辺の値 * 右辺の値 )を代入します。
/= は、( 左辺の値 / 右辺の値 )を代入します。
%= は、( 左辺の値 % 右辺の値 )を代入します。
また、x += y は x = x + y と同じことになります。
-= *= /= %= も同様です。
public class Main {
public static void main(String[] args) {
int i;
// =
i = 100; // i = 100
// +=
i += 100; // i = 100 + 100 = 200
// -=
i -= 50; // i = 200 - 50 = 150
// *=
i *= 3; // i = 150 * 3 = 450
// /=
i /= 15; // i = 450 / 15 = 30
// %=
i %= 4; // i = 30 % 4 = 2
}
}
2.4. ++, --
++ -- は、インクリメントとデクリメントと呼ばれるものです。
++ が「インクリメント」で、 -- が「デクリメント」です。
これら 2 つは、変数の隣にくっつけて使います。
インクリメントは、その変数の値を 1 つ増やし、デクリメントは、反対に 1 つ減らします。 では、実際のソースを見てもらいましょう。
public class Main {
public static void main(String[] args) {
int num = 100;
// インクリメント
num++;
System.out.println(num); // num = 101
// デクリメント
num--;
System.out.println(num); // num = 100
}
}
実行すると、はじめは、1 増えた 101 が表示され、次にそこから 1 減った 100 が表示されたかと思います。
上記のソースでは、++ -- ( 後置 )で解説しましたが、++ -- ( 前置 )は、変数の前につけるインクリメント・デクリメントです。
この後置と前置には、計算される順番に違いがあります。
違いがでるソースを載せておきます。
public class Main {
public static void main(String[] args) {
int num = 100;
// 後置
// 出力は 100
System.out.println(num++); // 出力後、numは 101 になる
// インクリメントされたか確認用
System.out.println(num);
// 前置
// 出力は 102
System.out.println(++num); // 出力前、numは 102 になる
}
}
まず、先に後置の時に画面に出力しているかと思いますが、100 のままかと思います。
後置にした場合、記述した行の後に演算が行われます。
間に確認用で値を出力しています。
101になってるかな?
次に、前置のほうですが、ここでは、102 が表示されているかと思います。
こちらは、後置と反対に画面出力される前に、演算が行われます。
ややこしいけど、意外と大切!
2.5. <, >, <=, >=, ==, !=
これらは「比較演算子」と呼ばれるものです。
左辺と右辺を比較し、条件が成立すれば、true(真)を返します。
反対に、条件が成立しない場合は、false(偽)を返します。
(真と偽は数学で勉強したことあるかも?)
< は、左辺が右辺より小さい時に true を返します。
> は、右辺が左辺より小さい時に true を返します。
<= は、左辺が右辺以下の時に true を返します。
>= は、右辺が左辺以下の時に true を返します。
== は、右辺と左辺の値が等しい場合に true を返します。
!= は、右辺と左辺の値が等しくない場合に true を返します。
以下に、ソースをのせておきます。
また、「以上」と「より大きい」の違いを補足としてソースに記載しておきます。
public class Main {
public static void main(String[] args) {
// < と >
System.out.println(5 < 6); // true
System.out.println(5 > 6); // false
// < と <= の違い
System.out.println(5 < 5); // false
System.out.println(5 <= 5); // true
// == と !=
System.out.println(5 == 5); // true
System.out.println(5 != 5); // false
}
}
<=や>=は同じ値でもtrueにするってことですね。
2.6. &, |, &&, ||, ^, !
これらは「論理演算子」です。
右辺と左辺を評価して、true か false を返します。
& と && は、右辺が true かつ 左辺が true である時のみ、true を返します。
両辺が、true でなければ true は、返されません。
「AND演算子」と呼ばれるものです。
| と || は、右辺が true または 左辺が true である時、true を返します。
どちらかが、true なら true になるということです。
「OR演算子」と呼ばれます。
^ は、いずれかの辺が true かつ もう一方の辺が false の時に、true を返す。
左辺が true で 右辺が true であれば、false になる。
「XOR演算子」と呼ばれます。
! は、真偽値を反転させます。
true であれば、falseにします。
public class Main {
public static void main(String[] args) {
// &
System.out.println(5 < 6 & 10 > 9); // true && true = true
System.out.println(5 < 6 & 10 < 9); // true && false = false
System.out.println(5 > 6 & 10 > 9); // false && true = false
System.out.println(5 > 6 & 10 < 9); // false && false = false
// |
System.out.println(5 < 6 | 10 > 9); // true | true = true
System.out.println(5 < 6 | 10 < 9); // true | false = true
System.out.println(5 > 6 | 10 > 9); // false | true = true
System.out.println(5 > 6 | 10 < 9); // false | false = false
// ^
System.out.println(5 < 6 ^ 10 > 9); // true ^ true = false
System.out.println(5 < 6 ^ 10 < 9); // true ^ false = true
System.out.println(5 > 6 ^ 10 > 9); // false ^ true = true
System.out.println(5 > 6 ^ 10 < 9); // false ^ false = false
// !
System.out.println(!(5 < 6)); // !(true) = false
System.out.println(!(5 > 6)); // !(false) = true
}
}
また、& と && のように 1 つと 2 つには、処理の違いがあります。
10 < 5 && 6 < 4 && 100 < 200 のように記述した場合は、最後まで評価が行われません。
はじめの 10 < 5 の時点でこの式は、false になることが確定したため、6 < 4 && 100 < 200 を評価しても、必ず false なので評価されずに終了します。
少しややこしいですので、基本的には、&& のように 2 つ記述することをおすすめします。
また、|| の場合の処理も同様で、どこかで true が決まれば、それ以降の評価は行われません。
|| も 2 つ書いておく方が、無難です。
public class Main {
public static void main(String[] args) {
// nonは評価が行われていないことを示します
// &&
System.out.println(5 < 6 && 10 > 9); // true && true = true
System.out.println(5 < 6 && 10 < 9); // true && false = false
System.out.println(5 > 6 && 10 > 9); // false && non = false
System.out.println(5 > 6 && 10 < 9); // false && non = false
// ||
System.out.println(5 < 6 || 10 > 9); // true | non = true
System.out.println(5 < 6 || 10 < 9); // true | non = true
System.out.println(5 > 6 || 10 > 9); // false | true = true
System.out.println(5 > 6 || 10 < 9); // false | false = false
}
}
途中まで評価され最後まで評価されずに困るときは以下のようなソースの時ですが、あまりこういう書き方はしないほうがいいですよ。。ほんとに。。
public class Main {
public static void main(String[] args) {
int a = 1, b = 2, c = 3, d = 4;
// nonは評価が行われていないことを示します
// &&
System.out.println(a > b && ++c < ++d); // false && non = false
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
// 再設定
a = 1; b = 2; c = 3; d = 4;
// &&
System.out.println(a < b && ++c < ++d); // true && false = false
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
注目は評価中にインクリメントしたことです。
1度目の評価後ではa~dは変わらず、1~4なのに、
2度目の評価後ではa~dは、1, 2, 4, 5となっています。
微妙な差がバグを生み出したりするので、気を付けてください。
2.7. &, |, ^
これらは、数同士の場合はビット演算として、使われます。
ビット演算というのは、2 進数の 0 と 1 での演算になります。
2進数の計算方法を知らないと少し難しい。
& は「論理積」というもので、2 つの数が 2 進数で同じ位が両方とも 1 の場合、その位を 1 のままに、
もし、それ以外であれば、その位を 0 にするという演算子です。
例えば、0x3a(=58) と 0x0f(=15) の論理積をする場合は、「 0x3a & 0x0f 」と記述します。
この時の結果は、0x0a(=10)となります。
2 進数で見ると、0011 1010(=58) と 0000 1111(=15) の論理積となり、0000 1010(=10) となります。
両方の数の同じ位が 1 なのは、右から 4 番目と 2番目のみなので、結果にはその位置だけを 1 とします。
| は「論理和」といい、2 つの数が 2 進数で同じ位のどちらかが 1 の場合、その位を 1 のままにします。
両方とも 0 の時のみ、その位を 0 にします。
上記の例で言えば、0x3a(=58) と 0x0f(=15) の論理和は、「 0x3a | 0x0f 」と記述します。
この時の結果は、0x3f(=63) になります。
2 進数では、0011 1010(=58) と 0000 1111(=15) の論理和となり、0011 1111(=63) となります。
^ は「排他的論理和」といい、2 つの数が 2 進数で同じくらいの片方が 1 で、もう片方が 0 の場合、その位を 1 にします。
両方 1 や 両方 0 では、その位が 0 になります。
これも上記の例だと、0x3a(=58) と 0x0f(=15) の排他的論理和は、「 0x3a ^ 0x0f 」と記述します。
この時の結果は、0x35(=53) になります。
2 進数では、0011 1010(=58) と 0000 1111(=15) の排他的論理和となり、0011 0101(=53) となります。
プログラムで書くと以下のようになります。
public class Main {
public static void main(String[] args) {
System.out.println(0x3a & 0x0f); // 10
System.out.println(0x3a | 0x0f); // 63
System.out.println(0x3a ^ 0x0f); // 53
}
}
2.8. <<, >>, >>>
これらは「シフト演算」と呼ばれるものです。
コンピュータは、基本的には 0 と 1 のみを使った 2 進数で表現されますが、これを右や左にずらすものをシフト演算といいます。
また、今回の間は、int型の 32 ビットで値を表すと想定として話を進めていきます。
実際には、入れる型などによって結果が変わることがあります。
<< は、左へシフトする演算子になります。
例えば、18 という数字を左へ 3 ビットずらしたい場合は、「 18 << 3 」とすると左へずらされ、144 という値になります。
演算結果を変数に入れたい場合は、
int ans = 0x12 << 3;
int ans = 0x12;
ans <<= 3;
としたり出来ます。
これは、+= や -= と同じ動きですね。
ちなみに、1 ビット左へシフトすると値は、2 倍になります。
>> は、右へシフトする演算子になりますが、シフト移動によって空いた場所に最上位ビットで埋めていく方法になります。
これは「算術シフト」といいます。
計算でシフト演算を用いる場合は、こちらを使ってください。
理由としては、「2 の補数」という方法でマイナス値を表現しているためになります。
例えば、-88 を右へ 4 ビットずらす時は、「 -88 >> 4 」となります。
この演算の結果は、-6 になります。
2 進数だと、1010 1001 (=-88) を右へ 4 ビットシフトすると、1111 1010 (=-6) となります。
一番左のビットが最上位ビットというもので、今回は 1010 1001 の赤色の部分です。1 ですね。
もし、一番左が 0 であれば、シフトした時に空いた場所が 0 で埋まっていきます。
今回は、1 ですので 1で埋まっていきます。
ちなみに、算術シフトで右へ 1 ビットシフトすると、1/2 の半分になります。
>>> は、右へシフトする演算子です。
こちらは「論理シフト」と呼ばれるものになります。
これは、シフト移動によって空いた場所に 0 埋めます。
例えば、上記と同じく -88 を右へ 4 ビットずらす時は、「 -88 >>> 4 」となります。
この演算の結果は、268435450 になります。
こっちは、結果を見ての通り数値が変なことになっています。
2 倍でも 1/2 倍でもないです。
ですので、こちらは計算用で使わない方がいいです。
>>>を使う場合は、数字に意味はなく、ビットに意味がある場合に使う時が多いと思います。
public class Main {
public static void main(String[] args) {
// <<
System.out.println(18 << 3); // 144
// >>
System.out.println(-88 >> 4); // -6
// >>>
System.out.println(-88 >>> 4); // 268435450
}
}
3. おわりに
今回は数学よりのお話が多くて頭がいっぱい...笑
どこかミスがあったら、ご指摘ください。たくさんありそう...
ちなみにString型を使った場合の演算は「注意」があるので、別記事にまとめようかと思います。
別記事 →「Java~String型を使った演算子の注意~」
今回は以上です。
次回は、「配列」について書こうかと思いまーす。
次回 →「Javaのお勉強 ~その7~ 配列」