1

マトリックスなどの大きなオブジェクトがあり、このオブジェクトを何らかの方法で変更する機能を提供したいと考えていました(マトリックスの場合、マトリックスを反転したい場合があります)。

反転機能を実装する最良の方法は何ですか?

次の 4 つのオプションが思い浮かびます。

  1. 自分自身を反転するメンバー関数 Matrix::invert() を持つことができます。
  2. メンバー関数は、新しい逆行列 (のようなものstd::string::substr)を構築できます。
  3. invert は、参照を取得して変更する非メンバー関数である可能性があります。void invert(matrix& m)
  4. invert は、行列を値で受け取り、反転してから返す非メンバー関数である可能性があります。matrix invert(matrix m)

ユーザーが元のマトリックスを保持したい場合、元のマトリックスは変更されないため、現在、4 番目のオプションが最善のように思えます。
auto m = matrix{};
auto m2 = invert(m);

また、逆行列のみが必要な場合は、次のことを行うことができます:
auto m = matrix{};
auto m2 = invert(move(m));
または
auto m = invert(matrix{})(新しく構築された行列が逆に移動され、変更され、rvo'd または m に移動されるため、これは効率的なはずです)

しかし、これは、クラスの表現に影響を与える操作はメンバー関数として実装する必要があるという考えに反します。matrix& matrix::invert()したがって、理想的には、親行列が右辺値で呼び出されている場合は親行列を変更しますが、左辺値で呼び出されている場合はそのままにして新しい行列を返すメンバー関数を実装する方法が必要です。これは正しいアプローチでしょうか?そして、それはどのように実装できますか?

別のオプションは、元のメンバーを変更するメンバーと、パラメーターが右辺値 (移動される場合) か左辺値 (この場合) に応じて「正しいことを行う」非メンバーを実装することです。コピーが作成されます)。これにはまだ 2 つの欠点があります。

  1. より多くのコード、今では 2 つの反転関数があるため
  2. m.invert() を言いたいかもしれませんが、元の行列を変更したくないので、連鎖は厄介です。

例: https://gist.github.com/mfaizan/6631482

ありがとう!

4

3 に答える 3

1

もちろん、それはすべて依存しますが、変更アクションと新しいオブジェクトを生成するアクションの両方を持つと便利なことがよくあります。元。m.invert() メソッドは、マトリックスをその場で変更できます。新しいマトリックスを作成するよりも効率的かもしれません (メモリを割り当てることなく既存の値を変更できます)。ただし、元のオブジェクトから切断された新しいオブジェクトを作成する方法があると便利です。

std::string で次のパターンが表示されます。

string orig("abcd");
orig += "efgh";

これにより、元の文字列が変更され、メモリの再割り当てを回避できる可能性があります。ただし、新しい文字列を作成することもできます。

string newStr = orig + anotherStr;
于 2013-09-20T01:38:29.427 に答える
1

考慮したい別の可能性があります。

bool invert (Matrix &);

行列は特異であると判断される場合があり、その場合false、行列を変更せずにそのままにします。この事件を報告する何らかの方法が必要です。

小さな行列に Cramer の規則などを使用するか、スケール (部分) ピボットを使用するか、または大きな行列に効率的な方法を使用するかにかかわらず、常に精度の制限があります。つまり、結果はマトリックスの条件付けの影響を受けます。ポイントは、行列が数学的に可逆であっても、浮動小数点演算で逆が得られない場合があることです。

「式」の最も用途Matrix invert (const Matrix &);の広い形式は次のとおりです。 - 移動コンストラクター/代入演算子がある場合。おそらくMatrix::Singular例外クラスがあります。

于 2013-09-20T02:23:17.630 に答える