CompareByDigits関数の働き・役割
CompareByDigits関数は、2つのベクトルまたは行列を比較するための関数です。
数値の有効数字を指定し、その精度で各要素を比較します。これにより、非常に大きな数値や小さな数値を含むデータを、丸め誤差や微小な差異を考慮した上で判定できます。
例えば、行列同士を比較した場合、指定した有効数字の範囲内で一致しているかどうかを調べ、異なる要素の数を返します。戻り値が0の場合は、全ての要素が指定した精度内で一致していることを意味します。
この関数を使用することで、厳密な浮動小数点比較が困難なケースでも、適切な精度を維持しつつ、データの一致判定が可能です。
有効数字とは?
有効数字とは、数値の中で意味を持つ桁数のことです。例えば、123.456という数値で有効数字を3桁にすると、「123」となります。この場合、小数点以下は考慮せず、上位3桁だけで比較を行います。
CompareByDigits関数の引数について
ベクトル用引数
ulong vector::CompareByDigits(
const vector& vec, // 比較するベクトル
const int digits // 有効数字の数
);
- vec
比較対象となるもう一つのベクトルです。このベクトルと現在のベクトルを比較します。 - digits
有効数字の桁数を指定します。例えば、digitsに10を指定すると、10桁まで一致しているかどうかで判定します。
行列用引数
ulong matrix::CompareByDigits(
const matrix& mat, // 比較する行列
const int digits // 有効数字の数
);
CompareByDigits関数の戻り値について
CompareByDigits関数の戻り値は、比較結果として「一致しなかった要素の数」を返します。
戻り値の意味
例えば、戻り値が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の構築
対角要素
- 行番号と列番号が一致する要素には「1.0 + i」の値を代入します。
- 具体例:
- matrix_a
[0][0] = 1.0
- matrix_a[1][1] = 2.0
- matrix_a[2][2] = 3.0
- matrix_a
非対角要素
- 行番号と列番号が異なる要素には、
value
を10の20乗(1e+20)で割った値を設定します。value
はループごとに1ずつ増加します。 - 具体例:
value = 1.0
→1.0 / 1e+20 = 0.00000000000000000001
value = 2.0
→2.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の比較
※1e-15
という表記は、科学記法と呼ばれるものです。
科学記法についての詳細は下記の記事をご参照ください。
有効数字15桁の比較
比較結果の出力
出力例
行列サイズ: 128 x 256, イプシロン比較の不一致要素数: 128, 有効数字比較の不一致要素数: 32768