0

これは初歩的な質問かもしれません。私は C++ を初めて使用し、メモリに収まらない可能性のある巨大なランダム マトリックスを実装したいと考えています。したがって、ファイルに書き込んで、ストリーム内の要素ごとに読み込む必要があると思います。

私が確認したいのは、要素がしきい値よりも小さいかどうかです。はいの場合、要素 (i,j) のインデックスを格納用の stl ベクトルにプッシュし、いいえの場合、次の要素に移動します。

基本的に、行列AJMを に書き込み、matrix.datその要素を次のように読み取る2 行が必要です。

for (int i = 0; i < ROWS; i++)
{
    for (int j = 0; j < COLS; j++)
    {
        currentElement = "read AJM[i][j] from matrix.txt";
    } 
}

したがって、「matrix.txt から AJM[i][j] を読み取る」は明確ではありません。ファイル ポインターを i と j で指定された特定の位置に反復し、読み取るバイト数を指定することによって行われると思います。

matrix.dat行列全体をメモリに保存しないように、インデックスを知っている要素を 1 つずつ読み書きする C++ コードを教えてください。

どうもありがとう!

4

3 に答える 3

4

ここで車輪を再発明しているかもしれません。行列が密な場合、基本的に 2 つの選択肢があります。列優先順 (Fortran 互換用) または行優先順 (C 多次元配列互換用) です。行列が疎行列の場合、いくつかの標準形式から最も適切なものを選択できます (つまり、「一般的な」疎行列とは異なる三重対角行列の選択)。CSR/CSC はおそらく最も普及している「非常に一般的な」疎行列表現。どのメモリ内表現を選択するかによって、ディスクベースの表現に多くの情報がもたらされます。私のアドバイス: やりたいことができるライブラリを見つけて使用し、車輪を再発明しないでください。

それ以来、あなたはマトリックスが密集していると答えました。私は、あなたが実際に尋ねた質問ではなく、あなたが尋ねるべきだったと思う質問に答えるつもりです。本当に巨大な行列 (たとえば、10 億の要素) をtextとして保存している場合は、本当にひどい時間を過ごすことになるので、生活を少し楽にするために、行列が double として保存されていると仮定します。 .

他にも可能性はありますが、基本的に、密行列のディスク上の単純な表現には、行優先順と列優先順の 2 つがあります。これらのいずれかを選択すると、インデックスi,jを取得してファイルからその値を取得し、行列の次元を知るための 2 つの選択肢があります。行列の次元がm(行) × n(列) であると仮定すると、要素に対応する行列の先頭からのオフセットは (行優先の場合i,j):

offset = i*n + j

または (列優先の場合):

offset = j*m + i

行列要素がすべて double であると仮定すると、行優先seek()の順序で次のようなことを行うために、このオフセットでファイルに入れることができます (mfsstd::ifstream行列ファイルに添付されています)。

double element;
mfs.seekg( (i*n+j)*sizeof(double) );
mfs.read( reinterpret_cast<char*>(&element), sizeof(double) );

あるいは、POSIX ライクなシステムでは、 を使用mmap()して行列ファイルをメモリにマップし、同じ根拠を使用して適切なオフセットを計算できます。

于 2013-09-18T21:54:43.063 に答える
0

行列の読み方は、行列の書き方によって異なります。個人的には、行列の幅と高さを指定して行列を書き始め、次に各行を線として書きます。簡単にするために、マトリックスをテキスト ファイルとして記述します。たとえば、次のようになります。

3 4
1 2 3 4
5 6 7 8
9 10 11 12

このような行列を読むのはとても簡単です:

int rows(0), columns(0);
if (in >> rows >> columns) {
    std::vector<std::vector<double>> matrix(rows);
    for (int r(0); in && r != rows; ++r) {
        std::copy_n(std::istream_iterator<double>(in), columns,
                    std::back_inserter(matrix[r]));
    }
}
if (!in) {
    std::cout << "ERROR: failed to read matrix\n";
}

明らかに、マトリックス構造が既にある場合は、マトリックスの個々の要素を直接埋める同様のアプローチを使用できます。std::copy_n()特定の要素またはその座標を保存するには、関数を、対応する座標で条件付きでメソッドを呼び出すものに置き換えるだけです。

template <typename InIt, typename Predicate, typename Fun>
void filter_n(InIt it, int n, Predicate pred, Fun fun) {
    for (int i = 0; i != n; ++i, ++it) {
        if (pred(*it)) {
            fun(*it, i);
        }
    }
}

...そして、std::copy_n()この関数への適切な呼び出しに置き換えます。たとえば、

    filter_n(std::istream_iterator<double>(in), columns,
             [threshold](double d){ return d < threshold; },
             [r](double, int c) { std::cout << "(" << r << ", " << c << ")\n"; });

これは、よりも小さい要素の座標を出力するだけですが、thresholdこれらの座標とその位置の値を適切なコンテナーに格納するのは簡単なはずです。

于 2013-09-18T21:33:38.410 に答える
0

ファイルを使用する場合は、保存するデータのエンコーディングを決定する必要があります。

単純な実装では、各要素を順番に格納し、各行 (または列) を次の行の前に順番に処理します。

使用しているエンコーディングに関係なく、メモリに収まらない場合は、位置を変更して正しい要素を見つけることができるファイル ハンドルを使用する必要があります。それが正確にどのように機能するかは、ファイルからの読み込みに何を使用するかによって異なります。

ほとんどの場合、操作が呼び出されるSeekか、いくつかの小さなバリエーションがあります。

于 2013-09-18T21:24:18.283 に答える