{{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; }