はじめに
この実験では、C++ の演算子の使い方を学びます。算術演算子、比較演算子、論理演算子、ビット演算子の使い方を学びます。
コンテンツプレビュー
基本的な数値と論理データに対して、演算子を使って操作します。他の言語と同様に、C++ は演算子に対して十分なサポートを提供しています。これから学んでいきましょう。
- 算術演算
- 混合型演算
- 複合代入演算子
- 型キャスト
- 比較演算子と論理演算子
算術演算
C++ は数値に対して次の算術演算子をサポートしています。
| 演算子 | 説明 | 使い方 | 例 |
|---|---|---|---|
| * | 乗算 | expr1 * expr2 | 2 * 3 → 6; 3.3 * 1.0 → 3.3 |
| / | 除算 | expr1 / expr2 | 1 / 2 → 0; 1.0 / 2.0 → 0.5 |
| % | 余り (剰余) | expr1 % expr2 | 5 % 2 → 1; -5 % 2 → -1 |
| + | 加算 | expr1 + expr2 | 1 + 2 → 3; 1.1 + 2.2 → 3.3 |
| - | 減算 | expr1 - expr2 | 1 - 2 → -1; 1.1 - 2.2 → -1.1 |
上記の演算子はすべて 2 項演算子で、2 つのオペランドを取ります。乗算、除算、余りは加算と減算よりも優先順位が高いです。
int/int は int を生成し、結果が切り捨てられることに注意することが重要です。1/2 → 0 (0.5 ではありません)。
混合型演算
算術演算のオペランドの両方が同じ型に属する場合、演算はその型で行われ、結果もその型に属します。ただし、2 つのオペランドが異なる型に属する場合、コンパイラは小さい方の型の値を大きい方の型に昇格させます(暗黙的な型キャストと呼ばれます)。その後、演算は大きい方の型で行われます。
| 型 | 例 | 演算 |
|---|---|---|
| int | 2 + 3 | int 2 + int 3 → int 5 |
| double | 2.2 + 3.3 | double 2.2 + double 3.3 → double 5.5 |
| 混合 | 2 + 3.3 | int 2 + double 3.3 → double 2.0 + double 3.3 → double 5.3 |
| int | 1 / 2 | int 1 / int 2 → int 0 |
| double | 1.0 / 2.0 | double 1.0 / double 2.0 → double 0.5 |
| 混合 | 1 / 2.0 | int 1 / double 2.0 → double 1.0 + double 2.0 → double 0.5 |
例
/* 混合型算術演算のテスト */
#include <iostream>
#include <iomanip> // 浮動小数点数の書式設定に必要
using namespace std;
int main() {
int i1 = 2, i2 = 4;
double d1 = 2.5, d2 = 5.0;
// 少数第 1 位で固定形式の浮動小数点数
cout<<fixed<<setprecision(1);
cout << i1 << " + " << i2 << " = " << i1+i2 << endl; // 6
cout << d1 << " + " << d2 << " = " << d1+d2 << endl; // 7.5
cout << i1 << " + " << d2 << " = " << i1+d2 << endl; // 7.0 <==
cout << i1 << " - " << i2 << " = " << i1-i2 << endl; // -2
cout << d1 << " - " << d2 << " = " << d1-d2 << endl; // -2.5
cout << i1 << " - " << d2 << " = " << i1-d2 << endl; // -3.0 <==
cout << i1 << " * " << i2 << " = " << i1*i2 << endl; // 8
cout << d1 << " * " << d2 << " = " << d1*d2 << endl; // 12.5
cout << i1 << " * " << d2 << " = " << i1*d2 << endl; // 10.0 <==
cout << i1 << " / " << i2 << " = " << i1/i2 << endl; // 0 <==
cout << d1 << " / " << d2 << " = " << d1/d2 << endl; // 0.5
cout << i1 << " / " << d2 << " = " << i1/d2 << endl; // 0.4 <==
return 0;
}
出力:
2 + 4 = 6
2.5 + 5.0 = 7.5
2 + 5.0 = 7.0
2 - 4 = -2
2.5 - 5.0 = -2.5
2 - 5.0 = -3.0
2 * 4 = 8
2.5 * 5.0 = 12.5
2 * 5.0 = 10.0
2 / 4 = 0
2.5 / 5.0 = 0.5

オーバーフロー / アンダーフロー
// int の範囲は [-2147483648, 2147483647]
int i1 = 2147483647; // int の最大値
cout << i1 + 1 << endl; // -2147483648 (オーバーフロー)
cout << i1 * i1 << endl; // 1
int i2 = -2147483648; // int の最小値
cout << i2 - 1 << endl; // 2147483647 (アンダーフロー)
cout << i2 * i2 << endl; // 0
算術演算では、結果の値がその範囲を超える場合、その値は循環します。C++ ランタイムはエラー/警告メッセージを発行せず、代わりに誤った結果を生成します。オーバーフロー/アンダーフローのチェックはプログラマーの責任であることに注意することが重要です。
複合代入演算子
C++ はまた、次のように列挙されるいわゆる 複合代入演算子 も提供しています。
| 演算子 | 使い方 | 説明 | 例 |
|---|---|---|---|
| = | var = expr | 左辺の値を右辺の変数に代入する | x = 5; |
| += | var += expr | var = var + expr と同じ | x += 5; は x = x + 5 と同じ |
| -= | var -= expr | var = var - expr と同じ | x -= 5; は x = x - 5 と同じ |
| *= | var *= expr | var = var * expr と同じ | x *= 5; は x = x * 5 と同じ |
| /= | var /= expr | var = var / expr と同じ | x /= 5; は x = x / 5 と同じ |
| %= | var %= expr | var = var % expr と同じ | x %= 5; は x = x % 5 と同じ |
| ++ | ++x | 前置インクリメント | y=++x; は x=x+1;y=x と同じ |
| ++ | x++ | 後置インクリメント | y=x++; は oldX=x; x=x+1; y=oldX と同じ |
| -- | --x | 前置デクリメント | y=--x; は x=x-1;y=x と同じ |
| -- | x-- | 後置デクリメント | y=x--; は oldX=x; x=x-1; y=oldX と同じ |
x = 5;
cout << x++ << endl; // x を保存 (5); x をインクリメント (=6); 古い x (5) を出力する。
x = 5;
cout << ++x << endl; // x をインクリメント (=6); x を出力する (6)。
暗黙的な型変換と明示的な型キャスト
基本型(組み込み型)の値を別の基本型の変数に代入する場合、C++ は 2 つの型が互換性がある場合、自動的に値を受け取る型に変換します。例えば、
int型の値をdouble型の変数に代入する場合、コンパイラは自動的にint型の値をdouble型にキャストします(たとえば、1 から 1.0 に)し、それをdouble型の変数に代入します。double型の値をint型の変数に代入する場合、コンパイラは自動的にdouble型の値をint型の値にキャストします(たとえば、1.2 から 1 に)し、それをint型の変数に代入します。小数部分は切り捨てられて失われます。一部のコンパイラは「精度の損失があり得る」という警告/エラーを発行します。他のコンパイラはそうしません。
int i;
double d;
i = 3;
d = i; // int 型の値を double 型に代入
cout << "d = " << d << endl; // 3.0
d = 5.5;
i = d; // double 型の値を int 型に代入
cout << "i = " << i << endl; // 5 (切り捨てられ、警告なし!)
(新しい型) オペランド または 新しい型 (オペランド) の形式のいわゆる単項の 型キャスト演算子 を使って明示的に型キャストを行うことができます。型キャスト演算子は特定の型の 1 つのオペランドを取り、新しい型の等価な値を返します。これは、加算演算子が 2 つのオペランドを使うのと同じように、結果の値を生成する演算であることに注意してください。たとえば、
cout << (double)5 << endl; // int 5 → double 5.0
cout << (int)5.5 << endl; // double 5.5 → int 5
double aDouble = 5.6;
int anInt = (int)aDouble; // 5 を返して anInt に代入。aDouble は変化しません!
// C++ は関数スタイルの型キャストもサポートしています。
cout << double(5) << endl; // 5.0
cout << int(5.5) << endl; // 5
cout << int(aDouble) << endl; // 5
比較演算子と論理演算子
多くの場合、実行するアクションを決定する前に 2 つの値を比較する必要があります。C++ は 6 つの 比較演算子(または 関係演算子)を提供しています。
| 演算子 | 説明 | 使い方 | 例 (x=5, y=8) |
|---|---|---|---|
| == | 等しい | expr1 == expr2 | (x == y) → false |
| != | 等しくない | expr1!= expr2 | (x!= y) → true |
| > | 大きい | expr1 > expr2 | (x > y) → false |
| >= | 大きいか等しい | expr1 >= expr2 | (x >= 5) → true |
| < | 小さい | expr1 < expr2 | (y < 8) → false |
| <= | 小さいか等しい | expr1 <= expr2 | (y <= 8) → true |
| && | 論理積 | expr1 && expr2 | |
| || | 論理和 | expr1 || expr2 | |
| ! | 論理否定 | !expr | |
| ^ | 排他的論理和 | expr1 ^ expr2 |
真理値表は次の通りです。
| 論理積 (&&) | true | false |
|---|---|---|
| true | true | false |
| false | false | false |
| 論理和 (||) | true | false |
|---|---|---|
| true | true | true |
| false | true | false |
| 否定 (!) | true | false |
|---|---|---|
| false | true |
| 排他的論理和 (^) | true | false |
|---|---|---|
| true | false | true |
| false | true | false |
// x が 0 以上 100 以下(両端含む)の場合に true を返す
(x >= 0) && (x <= 100)
// 0 <= x <= 100 を使うのは誤り
// x が 0 以上 100 以下(両端含む)の範囲外の場合に true を返す
(x < 0) \|\| (x > 100) // または
!((x >= 0) && (x <= 100))
// year がうるう年の場合に true を返す
// 年が 4 で割り切れ、かつ 100 で割り切れない、または 400 で割り切れる場合、その年はうるう年である。
((year % 4 == 0) && (year % 100!= 0)) \|\| (year % 400 == 0)
まとめ
この部分は比較的簡単です。前のセクションと関連付けて理解してください。丸暗記する必要はありません。論理を理解しておきましょう。



