C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++における浮動小数点数の比較方法【誤差を考慮した正しい判定手法】

はじめに

本記事では、C++を使って2つの浮動小数点数を比較する方法について解説します。浮動小数点数の比較は、整数の比較とは性質が大きく異なり、単純な等価演算子(==)では正しく判定できない場合がある点に注意が必要です。

なぜ精度を考慮する必要があるのか

浮動小数点数はコンピュータ内部で2進数(IEEE 754形式)として表現されるため、10進数の値を正確に格納できず、微小な誤差が発生することがあります。そのため、2つの浮動小数点値を比較する際には、許容できる誤差の範囲(イプシロン)を考慮に入れる必要があります。

例えば、3.1428と3.1415という2つの数値を考えてみましょう。この2つは、精度0.01(小数第2位)まで見れば同じ値とみなせますが、精度0.001(小数第3位)で比較すると異なる値です。

比較の基本的な手法

誤差を考慮して2つの浮動小数点数を比較するには、以下の手順を踏みます。

  1. 一方の浮動小数点数からもう一方を引く
  2. その差の絶対値を求める
  3. 絶対値が許容誤差(イプシロン)より小さいかどうかを判定する

絶対値がイプシロンより小さければ、2つの値は「実用上等価である」と判断できます。

サンプルコード

#include <iostream>
#include <cmath>
using namespace std;

bool compare_float(float x, float y, float epsilon = 0.01f) {
    if (fabs(x - y) < epsilon)
        return true;   // 誤差が許容範囲内なら同じとみなす
    return false;      // 許容範囲を超えていれば異なるとみなす
}

int main() {
    float x, y;
    x = 22.0f / 7.0f;
    y = 3.1415f;
    if (compare_float(x, y)) {
        cout << "等価です" << endl;
    } else {
        cout << "等価ではありません" << endl;
    }
    if (compare_float(x, y, 0.001f)) {
        cout << "等価です" << endl;
    } else {
        cout << "等価ではありません" << endl;
    }
}

コードのポイント

compare_float関数は、比較対象の2つの値と許容誤差epsilonを引数として受け取ります。デフォルトのepsilonは0.01fに設定されており、呼び出し時に第3引数を指定することで、任意の精度に変更できます。

実行結果

等価です
等価ではありません

結果の解説

22.0f / 7.0fの計算結果は約3.142857...となり、3.1415との差は約0.00136です。デフォルトの許容誤差0.01より小さいため、最初の比較では「等価」と判定されます。一方、許容誤差を0.001に変更した2回目の比較では、差の方が大きくなるため「等価でない」と判定されます。

まとめ

浮動小数点数を比較する際は、誤差の許容範囲(イプシロン)を明確に定義し、差の絶対値で判定することが重要です。用途や求める精度に応じて適切なイプシロン値を選択することで、信頼性の高い比較処理を実現できます。

  1. C++でcomplexクラスを活用したジオメトリ(幾何計算)の実装方法

    この記事では、C++のSTLに含まれるcomplexクラスを使ってPointクラスを作成し、幾何学関連の問題に応用する方法を解説します。複素数は、STLのcomplexクラス(#include <complex>)で簡単に扱うことができます。 Pointクラスの定義 complexをpointとして扱うために、complex<double>に「point」という別名(typedef)を付けます。さらに、complexクラスのreal()をx、imag()をyとしてマクロ定義することで、Pointクラスと同様の操作が可能になります。 #include <comple

  2. C++で点を別の点を中心として回転させる方法

    原点を中心とした点の回転 点Xを原点を中心として角度θだけ反時計回りに回転させるには、以下の式を使用します。 原点を中心にθだけ反時計回りにXを回転する式: X * polar(1.0, θ) ここで使われている polar 関数は、<complex> ヘッダーファイルで定義されている複素数用の関数で、大きさ(絶対値)と位相角から複素数を生成するために使用されます。polar(mag, angle) を呼び出すと、対応する複素数が返されます。複素数を平面上の点として扱うことで、回転のような幾何学的な操作を簡潔に記述できるのがポイントです。 点Yを中心とした点Xの回転 ある点を別の