【MQL5】CompareByDigits関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク

CompareByDigits関数の働き・役割

CompareByDigits関数は、2つのベクトルまたは行列を比較するための関数です。
数値の有効数字を指定し、その精度で各要素を比較します。これにより、非常に大きな数値や小さな数値を含むデータを、丸め誤差や微小な差異を考慮した上で判定できます。

例えば、行列同士を比較した場合、指定した有効数字の範囲内で一致しているかどうかを調べ、異なる要素の数を返します。戻り値が0の場合は、全ての要素が指定した精度内で一致していることを意味します。

この関数を使用することで、厳密な浮動小数点比較が困難なケースでも、適切な精度を維持しつつ、データの一致判定が可能です。

有効数字とは?

有効数字とは、数値の中で意味を持つ桁数のことです。例えば、123.456という数値で有効数字を3桁にすると、「123」となります。この場合、小数点以下は考慮せず、上位3桁だけで比較を行います。


CompareByDigits関数の引数について

ベクトル用引数

ulong vector::CompareByDigits(
  const vector& vec,         // 比較するベクトル
  const int    digits        // 有効数字の数
  );
  1. vec
    比較対象となるもう一つのベクトルです。このベクトルと現在のベクトルを比較します。
  2. digits
    有効数字の桁数を指定します。例えば、digitsに10を指定すると、10桁まで一致しているかどうかで判定します。

行列用引数

ulong matrix::CompareByDigits(
  const matrix& mat,         // 比較する行列
  const int    digits        // 有効数字の数
  );
  1. mat
    比較対象となるもう一つの行列です。この行列と現在の行列を比較します。
  2. digits
    有効数字の桁数を指定します。ベクトルの場合と同様に、この桁数を基準に一致を判定します。

CompareByDigits関数の戻り値について

CompareByDigits関数戻り値は、比較結果として「一致しなかった要素の数」を返します。

戻り値の意味

  • 0: 全ての要素が指定した有効数字の範囲内で一致していることを意味します。
  • 0より大きい値: 不一致だった要素の数を示します。

例えば、戻り値が128の場合、128個の要素が一致しなかったことを表しています。


CompareByDigits関数を使ったサンプルコード

以下は、CompareByDigits関数を用いて行列を比較する具体的なサンプルコードです。

void OnStart()
{
    // 行列のサイズを設定
    int size_m = 128;  // 行の数を128に設定
    int size_k = 256;  // 列の数を256に設定

    // 行列matrix_aを初期化
    matrix matrix_a(size_m, size_k);

    // 行列にデータを書き込むための変数
    double value = 0.0;

    // matrix_aにデータを格納するループ処理
    for (int i = 0; i < size_m; i++)  // 行数分ループ
    {
        for (int j = 0; j < size_k; j++)  // 列数分ループ
        {
            if (i == j)  // 対角要素の場合
            {
                // 対角要素には1.0 + 行インデックスを代入
                matrix_a[i][j] = 1.0 + i;
            }
            else  // 非対角要素の場合
            {
                // 非対角要素にはvalueを1e+20(非常に大きな値)で割った値を代入
                value += 1.0;  // valueを1ずつ増加
                matrix_a[i][j] = value / 1e+20;
            }
        }
    }

    // matrix_aをもとに、新しい行列matrix_cを作成(matrix_aを-1倍したもの)
    matrix matrix_c = matrix_a * -1;

    // 比較結果を格納するための変数を定義
    ulong errors_epsilon;  // イプシロン比較での不一致要素数
    ulong errors_digits;   // 有効数字比較での不一致要素数

    // Compare関数を使用して、精度を指定して比較(イプシロン比較)
    errors_epsilon = matrix_a.Compare(matrix_c, 1e-15);

    // CompareByDigits関数を使用して、有効数字15桁で比較
    errors_digits = matrix_a.CompareByDigits(matrix_c, 15);

    // 比較結果をエキスパートログに出力
    printf("行列サイズ: %d x %d, イプシロン比較の不一致要素数: %I64u, 有効数字比較の不一致要素数: %I64u",
           size_m, size_k, errors_epsilon, errors_digits);
}

サンプルコードの解説

行列のサイズ設定と初期化

int size_m = 128;  // 行数を設定
int size_k = 256;  // 列数を設定
matrix matrix_a(size_m, size_k);  // 行列を初期化

最初に行列の行数と列数を指定し、それを基に行列を初期化します。ここでは128行×256列の行列matrix_aを作成しています。

matrix_aの構築

行列matrix_aの各要素に値を設定しています。

対角要素

  • 行番号と列番号が一致する要素には「1.0 + i」の値を代入します。
  • 具体例:
    • matrix_a[0][0] = 1.0
    • matrix_a[1][1] = 2.0
    • matrix_a[2][2] = 3.0

非対角要素

  • 行番号と列番号が異なる要素には、valueを10の20乗(1e+20)で割った値を設定します。valueはループごとに1ずつ増加します。
  • 具体例:
    • value = 1.01.0 / 1e+20 = 0.00000000000000000001
    • value = 2.02.0 / 1e+20 = 0.00000000000000000002

matrix_aのデータ例(3行3列の場合)

1.0,        0.00000000000000000001,    0.00000000000000000002
0.00000000000000000003,    2.0,        0.00000000000000000004
0.00000000000000000005,    0.00000000000000000006,    3.0

matrix_cの生成

行列matrix_aのすべての要素を-1倍して、新しい行列matrix_cを作成します。

matrix_cのデータ例

-1.0,       -0.00000000000000000001,   -0.00000000000000000002
-0.00000000000000000003,   -2.0,       -0.00000000000000000004
-0.00000000000000000005,   -0.00000000000000000006,   -3.0

比較の仕組み

精度1e-15の比較

  • 2つの要素の差が0.000000000000001(1e-15)以下であれば一致とみなします。
  • 対角要素の差(1.0-1.0)は2.0なので不一致。非対角要素の差は非常に小さいため一致。

1e-15という表記は、科学記法と呼ばれるものです。

科学記法についての詳細は下記の記事をご参照ください。

有効数字15桁の比較


比較結果の出力

出力例

行列サイズ: 128 x 256, イプシロン比較の不一致要素数: 128, 有効数字比較の不一致要素数: 32768

CompareByDigits関数を使ってEAを作る際のアイディア

  • 数値データの一致判定: 金融データの分析において、異なるソースから取得したデータが一致するかを確認する用途に使えます。
  • バックテスト結果の検証: 異なる手法や設定で生成された結果が、誤差の範囲内で一致しているかを判定するのに役立ちます。
  • モデル間の一致度チェック: 機械学習や統計モデルで出力された予測値を比較し、精度を評価することができます。

タイトルとURLをコピーしました