{{indexmenu_n>202109080003}}
==== 比較演算 ====
変数に読み込んだ値は、比較ができます。これはほとんどのプログラミング言語で共通です。
CPUはプログラム中で値を比較するときは、それぞれ持っているレジスタ同士で比較します。プログラミング言語で比較を行うときもCPU様に気を使って書かなければならないため、(基本的に)一度に2つのものの比較しかできません。
比較は、C++の組み込み型(初めから使える型)の同じ型同士であれば大抵は可能である。
比較は、以下の比較用の演算子(比較演算子)を用いて行う。
|< 40% 20% 10% 10% >|
| 名称| 演算子 | 構文 |
| 小なり| < | a **<** b |
| 小なりイコール| %%<%%= | a %%<%%= b |
| 大なり| > | a **>** b |
| 大なりイコール| >= | a **>=** b |
| 非等価 | != | a **!=** b |
| 等価 | == | a **==** b |
==== サンプルs ====
=== 等価比較 ===
入力した符号付整数が10かどうか判定する
判定式がtrueならその数を表示(10だよね)
(それ以外(falseの時)は何もしない)
#include
int main()
{
int num;
std::cin >> num;
if(num == 10)
{
//num が「10」なら true
std::cout << num << std::endl;
}
return 0;
}
=== 等価比較 ===
入力した浮動小数点数(double)がある数と等価かどうか判定する\\
とかやりたいときは注意が必要。\\
floatやdoubleは計算誤差が発生するので==で数とそのまま比較するのはNG\\
0.2\\
0.1\\
0.3\\
\\
\\
\\
\\
\\
\\
#include
using std::cout;
using std::cin;
using std::endl;
int main() {
double num1=0.2, num2=0.1;
cout << num1 << endl; //num1表示
cout << num2 << endl; //num2表示
cout << num1+num2 << endl; //num1+num2表示
if(num1+num2 == 0.3) //比較演算
{
cout << "num1+num2=" << num1+num2 << endl;
}
}
このように、表示上は0.3と表示されるが(coutの機能で、0.299999が0.3に丸め込まれてる)内部的には(メモリの中では)0.3ぴったりにはなっていない。\\
そのため、$num1+num2 == 0.3$などと等価比較してしまうと、判定はうまくいかない。\\
0.20000000000000001110\\
0.10000000000000000555\\
0.30000000000000004441\\
\\
\\
\\
\\
\\
\\
#include
#include
using std::cout;
using std::cin;
using std::endl;
int main() {
double num1=0.2, num2=0.1;
cout << std::fixed
<< std::setprecision(20)
<< num1 << endl; //num1表示
cout << std::fixed
<< std::setprecision(20)
<< std::setprecision(20)
<< endl; //num2表示
cout << std::fixed
<< std::setprecision(20)
<< num1+num2 << endl; //num1+num2表示
if(num1+num2 == 0.3) //比較演算
{
cout << "num1+num2=" << num1+num2 << endl;
}
}
== 少々考える ==
どうしてこのようなことが起こるか考える。\\
そもそも、整数はメモリ内で2進数で保存されてるが、整数と2進数の変換の間には誤差なく変換を行うことができる。\\
しかしながら、小数点数は、誤差なく1対1で変換することができないので、変換誤差が生じる。\\
([[https://siv3d.jp/web/sample/IEEE754Float32/IEEE754Float32.html|ここ]]で実際にどのように0.1や0.2がメモリに保存されているか見てみよう)\\
よって、それらの四則演算の結果は、数学の理論的な値と異なってくることが多く、計算機による実数計算では、様々なところで気を付けなければならない。(このような分野を扱う学問があり、専門的には数値計算法という分野になっています)\\
== それじゃぁどうすんの? ==
計算誤差をどこまで許すかというのを、自分のプログラムの設計段階で決めます。\\
上の例を見るとわかるとおり、誤差は通常のcoutでの小数点以下1桁表示程度では判定できないくらい小さい桁で発生しています。\\
そのぐらい小さいとこでの誤差は許してしまおう。という解決方法です。\\
例えば$10^{-3}$までの誤差なら許してしまおう。
(上の例で$num1+num2$ が $0.3001$程度なら $0.3$ になってると見なそうという事)\\
なので、計算結果と正解の数の誤差を計算します。\\
fabs((num1 + num2) - 0.3)
fabsは絶対値を求める関数です。\\
double num1 = 0.1, num2 = 0.2;
if( fabs((num1 + num2) - 0.3) <= 1e-3)
{
cout << "true" << endl;
}
== まとめ ==
以上のことを踏まえて、誤差計算で2つの浮動小数点数の等価比較をしてみます。
許容誤差は $10^{-3}$ で計算する。\\
(興味があれば、std::fabs(num1+num2 - 0.3)の値が、どのくらいになるか表示してみて、誤差がどのくらい出ているか調べてみよう)
#include
#include
#include
using std::cout;
using std::cin;
using std::endl;
int main() {
double num1=0.2, num2=0.1;
cout << std::fixed
<< std::setprecision(20)
<< num1 << endl; //num1表示
cout << std::fixed
<< std::setprecision(20)
<< num2 << endl; //num2表示
cout << std::fixed
<< std::setprecision(20)
<< num1+num2 << endl; //num1+num2表示
if(num1+num2 == 0.3)
//比較演算 == でためす
{
cout << "num1+num2=" << num1+num2 << endl;
}
if(std::fabs(num1+num2 - 0.3) < 1e-3)
//比較演算 許容誤差10^-3で誤差計算をする
{
cout << "num1+num2=" << num1+num2 << endl;
}
}
=== 非等価比較 ===
入力した符号付整数が「10以外」かどうか判定する\\
判定式がtrueならその数を表示\\
(それ以外(falseの時つまり10の時)は何もしない)\\
これも、浮動小数点の時は気を付けなければいけないよね?(どうすればいいかは、もうわかるはず!)\\
#include
int main()
{
int num;
std::cin >> num;
if(num != 10)
{
//num が「10以外」なら true
std::cout << num << std::endl;
}
return 0;
}
=== 大小比較 ===
入力した符号付整数が10より大きいかどうかを判定する
判定式がtrueなら、入力した数を表示する
(それ以外(false)の時は何もしない)
#include
int main()
{
int num;
std::cin >> num;
if(num > 10)
{
//num が「10より大きい」なら true
std::cout << num << std::endl;
}
return 0;
}