<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Matrixklasse - kleiner Fehler]]></title><description><![CDATA[<p>Hallo.</p>
<p>Ich habe folgende Matrixklasse im Internet entdeckt. Sie läuft ohne Probleme durch, nur wie geschrieben, sind die Ergebnisse falsch. Beim zweiten Beitrag weiß ich nicht, wo ich das einbetten soll. Hier erstmal der Link:</p>
<p><a href="http://www.cplusplus.com/forum/general/17908/" rel="nofollow">http://www.cplusplus.com/forum/general/17908/</a></p>
<p>Ich habe es z.B. für die Summe mit folgendem versucht:</p>
<pre><code>//To compute the summation
matrix matrix::operator+(matrix&amp; a){
matrix sum(nrows, ncols);
for (int i=0; i&lt;nrows; i++)
for(int j=0; j&lt;ncols; j++) {
this-&gt;operator()(i,j); // Das habe ich hinzugefügt
sum(i,j) = (i,j) + a(i,j);
}
return sum;
}
</code></pre>
<p>Das gibt aber keine Veränderung. Ich hoffe, ihr könnt mir helfen. Die Klasse an sich find ich nämlich ganz gut und einfach aufgebaut.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/312342/matrixklasse-kleiner-fehler</link><generator>RSS for Node</generator><lastBuildDate>Sun, 02 Aug 2026 18:46:36 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/312342.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 02 Jan 2013 12:19:57 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 12:19:57 GMT]]></title><description><![CDATA[<p>Hallo.</p>
<p>Ich habe folgende Matrixklasse im Internet entdeckt. Sie läuft ohne Probleme durch, nur wie geschrieben, sind die Ergebnisse falsch. Beim zweiten Beitrag weiß ich nicht, wo ich das einbetten soll. Hier erstmal der Link:</p>
<p><a href="http://www.cplusplus.com/forum/general/17908/" rel="nofollow">http://www.cplusplus.com/forum/general/17908/</a></p>
<p>Ich habe es z.B. für die Summe mit folgendem versucht:</p>
<pre><code>//To compute the summation
matrix matrix::operator+(matrix&amp; a){
matrix sum(nrows, ncols);
for (int i=0; i&lt;nrows; i++)
for(int j=0; j&lt;ncols; j++) {
this-&gt;operator()(i,j); // Das habe ich hinzugefügt
sum(i,j) = (i,j) + a(i,j);
}
return sum;
}
</code></pre>
<p>Das gibt aber keine Veränderung. Ich hoffe, ihr könnt mir helfen. Die Klasse an sich find ich nämlich ganz gut und einfach aufgebaut.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285295</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285295</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 12:19:57 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 12:30:48 GMT]]></title><description><![CDATA[<p>wenn ich mir das so auf den ersten blick angucke, würde ich dir empfehlen die finger davon zu lassen</p>
<p>schreib dir selbst ne kleine klasse für matrizen rechnung, ist für dich ne gute übung. sollte mindestens genausoviel können wie die, die du uns gezeigt hast. und danach weist du, dass sie klappt.</p>
<p>wenn mehr willst oder besseres, dann google nach ner richtigen mathe bibliothek, die solche klassen anbietet...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285298</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285298</guid><dc:creator><![CDATA[Skym0sh0]]></dc:creator><pubDate>Wed, 02 Jan 2013 12:30:48 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 13:54:13 GMT]]></title><description><![CDATA[<p>Die Klasse ist schlecht. Die Hälfte der Member hier kann wahrscheinlich in 20 Minuten eine (viel, viel) bessere schreiben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> Wozu brauchst du diese Klasse btw? Spiele? Sehr große Matrizen? Ist Performance wichtig? Sicher, dass dir die naiven Algorithmen reichen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285330</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285330</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 13:54:13 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:06:53 GMT]]></title><description><![CDATA[<p>Aber warum ist die denn schlecht? Sehe doch da eig. nur das nötigste.<br />
Wichtig sind für mich große Matrizen und Performance.</p>
<p>Und weitere Algorithmen würde ich dann selbst dazuschreiben. Nur komm ich von Matlab, und da brauche ich ja das ganze nicht. Daher ist für mich das ganze Neuland und hätte gerne eine Vorlage gehabt.</p>
<p>Könnt ihr mir aber trotzdem nicht kurz sagen, wo man den Befehl einbetten müsste?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285336</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285336</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:06:53 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:50:56 GMT]]></title><description><![CDATA[<p>Wenn du wirklich Performance brauchst, dann nimm eine der großen Mathebibliotheken. (Eigen, MTL, <a href="http://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library" rel="nofollow">http://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library</a>)</p>
<p>Dass die Klasse schlecht ist sieht man schon daran, dass sie kein Template ist, int statt size_t und rohe Pointer statt std::vector benutzt werden. Das ist nur der erste kleine Blick.</p>
<p>Ansonsten hier eine Vorlage für eine ordentliche Klasse:</p>
<pre><code>template &lt;typename T&gt;
class matrix
{
  std::vector&lt;T&gt; data_;
  std::size_t y_size_;

public:
  matrix(std::size_t x_size, std::size_t y_size)
    : data_(x_size * y_size)
    , y_size_(y_size)
  {}

  const T&amp; operator () (std::size_t i, std::size_t j) const
  {
    return data_[i * y_size_ + j];
  }

  T&amp; operator () (std::size_t i, std::size_t j)
  {
    return data_[i * y_size_ + j];
  }
};
</code></pre>
<p>Tadaa.. Operatoren kannste selbst basteln. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285338</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285338</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:50:56 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:12:48 GMT]]></title><description><![CDATA[<p>Danke schonmal. Welches von den ganzen würdest Du denn nehmen? Du kennst Dich da ja besser aus als ich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285342</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285342</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:12:48 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:14:35 GMT]]></title><description><![CDATA[<p>Nä, ich hab keine Ahnung von Matrixlibs im wissenschaftlichen Umfeld, ich weiß nur wo ich suchen muss. Aber ich würde MTL wohl als erstes testen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285344</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:14:35 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:19:41 GMT]]></title><description><![CDATA[<p>Die gibs wohl nur als Testversion. Aber werde dann mal die anderen versuchen. Am liebsten würd ich das ja selbst programmieren. Nur, das wäre kein optimaler Code. Und ich leide leider unter etwas Zeitdruck. Ich habe zwar ein Grundlagenbuch durchgemacht und weiß meistens auch, von was die Rede ist. Aber alles selbst programmieren, ne, das kann ich noch nicht.</p>
<p>Ich habe dazu noch eine ganz andere Frage: Ist es eine gute Idee, Matrizen als einfache Vektoren zu übergeben? Ich meine damit, dass ich die einzelnen Zeilen der Matrix nacheinanderhäng, und z.B. mit</p>
<pre><code>#define A(Reihe, Spalte) = A[Reihe + irgendwas*Spalte]
</code></pre>
<p>dass dann definiere?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285347</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285347</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:19:41 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:23:15 GMT]]></title><description><![CDATA[<p>Keine Ahnung was du meinst, aber #define ist (fast) nie eine gute Idee. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> - Du stehst unter Zeitdruck? Was genau musst du denn eigentlichen machen? (Wie groß sind deine Matrizen?)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285349</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285349</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:23:15 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:27:51 GMT]]></title><description><![CDATA[<p>Muss viel mit Matrizen hantieren, die wiederrum Ein- und Ausgabe von Funktionen sind. Habe mir auch schon mal das mex-Interface angeschaut. Möchte Matlab und C++ koppeln.</p>
<p>Die Matrizen sind, mh... in Matlab benutze ich schon Sparematrizen, weil diese schon 240.000x240.000 groß sein können. Das ist aber eher schon das Maximale, was ich benötige.</p>
<p>Und wegen den Templates: wenn ich weiß, dass ich nur double-Zahlen habe, kann ich mir die ja sparen. Für mich sind Templates da nur logisch, wenn ich ab und zu auch Integer-Zahlen haben, und damit weniger Speicherplatz benötige.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285354</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285354</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:27:51 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:32:41 GMT]]></title><description><![CDATA[<p>Bei der Matrixgröße kannst du jede konventionelle Matrixklasse vergessen. Überleg doch mal, wie viel Speicher das ist. 460800000000 Byte = 429 Gigabyte. Hast du so viel RAM? Wohl nicht. Also das was du da aus dem Forum kopiert hast (und leider auch meine Variante), sind schon mal völlig aus dem Spiel. Die großen Bibliotheken sollten allerdings uU damit zurecht kommen, die müssten das komprimieren. Was genau du machen willst, und wozu du C++ brauchst wenn du Matlab hast, hast du uns allerdings noch nicht verraten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285355</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285355</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:32:41 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:37:33 GMT]]></title><description><![CDATA[<p>RobertB schrieb:</p>
<blockquote>
<p>Und wegen den Templates: wenn ich weiß, dass ich nur double-Zahlen habe, kann ich mir die ja sparen. Für mich sind Templates da nur logisch, wenn ich ab und zu auch Integer-Zahlen haben, und damit weniger Speicherplatz benötige.</p>
</blockquote>
<p>Vllt, möchtes du ja irgendwann ma was genaueres benutzen als double ... Dann fängst du wieder von vorne an?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285358</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285358</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:37:33 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:48:34 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Wenn du wirklich Performance brauchst, dann nimm eine der großen Mathebibliotheken. (Eigen, MTL, <a href="http://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library" rel="nofollow">http://scicomp.stackexchange.com/questions/351/recommendations-for-a-usable-fast-c-matrix-library</a>)</p>
<p>Dass die Klasse schlecht ist sieht man schon daran, dass sie kein Template ist, int statt size_t und rohe Pointer statt std::vector benutzt werden. Das ist nur der erste kleine Blick.</p>
<p>Ansonsten hier eine Vorlage für eine ordentliche Klasse:</p>
<pre><code>template &lt;typename T&gt;
class matrix
{
  std::vector&lt;T&gt; data_;
  std::size_t y_size_;

public:
  matrix(std::size_t x_size, std::size_t y_size)
    : data_(x_size * y_size)
    , y_size(y_size)
  {}
  
  const T&amp; operator () (std::size_t i, std::size_t j) const
  {
    return data_[i * y_size_ + j];
  }

  T&amp; operator () (std::size_t i, std::size_t j)
  {
    return data_[i * y_size_ + j];
  }
};
</code></pre>
<p>Tadaa.. Operatoren kannste selbst basteln. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Ich habe mal diese Klasse ausprobiert, aber es tritt ein Fehler auf. Folgendes habe ich gemacht:</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;

template &lt;typename T&gt;
class matrix
{
  vector&lt;T&gt; data_;
  size_t y_size_;

public:
  matrix(size_t x_size, size_t y_size)
    : data_(x_size * y_size)
    , y_size(y_size)
  {}

  const T&amp; operator () (size_t i, size_t j) const
  {
    return data_[i * y_size_ + j];
  }

  T&amp; operator () (size_t i, size_t j)
  {
    return data_[i * y_size_ + j];
  }
};

int main() {

	return 0;
};
</code></pre>
<p>Könnt ihr mir bitte sagen, was ich falsch gemacht habe?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285361</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285361</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:48:34 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:53:26 GMT]]></title><description><![CDATA[<p>&lt;vector&gt; nicht #included. <a href="https://ideone.com/p6RKY0" rel="nofollow">https://ideone.com/p6RKY0</a><br />
Und meinen Beitrag oben nicht gelesen. Bei der Matrixgröße kannst du diesen Ansatz sicher vergessen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285362</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285362</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:53:26 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 14:57:16 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>&lt;vector&gt; nicht #included. <a href="https://ideone.com/p6RKY0" rel="nofollow">https://ideone.com/p6RKY0</a><br />
Und meinen Beitrag oben nicht gelesen. Bei der Matrixgröße kannst du diesen Ansatz sicher vergessen.</p>
</blockquote>
<p>Deinen Beitrag habe ich gelesen. Der Ansatz war nur aus Interesse. Aber dieser ist dann allen Anschein nicht geeignet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285364</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285364</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Wed, 02 Jan 2013 14:57:16 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Wed, 02 Jan 2013 20:18:28 GMT]]></title><description><![CDATA[<p>Hallo RobertB,</p>
<p>bei der angestrebten Größe der Matrix kommst Du nur mit einer <a href="http://de.wikipedia.org/wiki/D%C3%BCnnbesetzte_Matrix" rel="nofollow">Sparse Matrix</a> weiter - vorausgesetzt natürlich, Dein Problem, welches Du lösen willst, erzeugt auch nur dünn besetzte Matrizen.<br />
<a href="http://www.boost.org/doc/libs/1_52_0/libs/numeric/ublas/doc/index.htm" rel="nofollow">boost.ublas</a> bietet <a href="http://www.boost.org/doc/libs/1_52_0/libs/numeric/ublas/doc/matrix_sparse.htm" rel="nofollow">sparse matrix</a> an. Ich selber habe aber keine Erfahrungen damit.</p>
<p>Wenn Du an einer einfach gestrickten Lösung interessiert bist, so kannst Du Dir auch selber was bauen. Im Prinzip lässt sich so eine Matrix mit einem <a href="http://www.cplusplus.com/reference/vector/vector/" rel="nofollow">vector</a> von <a href="http://www.cplusplus.com/reference/map/map/" rel="nofollow">map</a>s lösen. So wäre zumindest die Implementierung relativ straight forward.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;map&gt;
#include &lt;vector&gt;
#include &lt;cassert&gt;
#include &lt;iomanip&gt; // setw
#include &lt;numeric&gt; // accumulate

template&lt; typename T &gt;
class SparseMatrix
{
    typedef std::map&lt; std::size_t, T &gt; Row; // key -&gt; column
    typedef std::vector&lt; Row &gt; Field; // index -&gt; row

    struct Ref
    {
        Ref( Row&amp; row, std::size_t columnIdx )
            : row_( &amp;row )
            , column_( columnIdx )
        {}
        Ref&amp; operator=( const T&amp; element )
        {
            if( element == T() )
            {
                auto iElement = row_-&gt;find( column_ );
                if( iElement != end(*row_) )
                    row_-&gt;erase( iElement );
            }
            else
                (*row_)[column_] = element;
            return *this;
        }
        operator T() const
        {
            auto iElement = row_-&gt;find( column_ );
            return iElement == end(*row_)? T(): iElement-&gt;second;
        }
    private:
        Row* row_;
        std::size_t column_;
    };

public:
    SparseMatrix( std::size_t rows, std::size_t columns )
        : columns_( columns )
        , field_( rows )
    {}
    std::size_t Columns() const { return columns_; }
    std::size_t Rows() const { return field_.size(); }

    // --  Element Zugriff
    T operator()( std::size_t rowIdx, std::size_t columnIdx ) const
    {
        assert( rowIdx &lt; Rows() );
        assert( columnIdx &lt; Columns() );
        auto iElement = field_[rowIdx].find( columnIdx );
        return iElement == end(field_[rowIdx])? T(): iElement-&gt;second;
    }
    Ref operator()( std::size_t rowIdx, std::size_t columnIdx )
    {
        assert( rowIdx &lt; Rows() );
        assert( columnIdx &lt; Columns() );
        return Ref( field_[rowIdx], columnIdx );
    }

    // --  Arithmetik
    SparseMatrix&amp; operator+=( const SparseMatrix&amp; b );
    SparseMatrix&amp; operator-=( const SparseMatrix&amp; b );

    // --  Ausgabe
    template&lt; typename E, typename Traits &gt; friend
        std::basic_ostream&lt; E, Traits &gt;&amp; operator&lt;&lt;( std::basic_ostream&lt; E, Traits &gt;&amp; out, const SparseMatrix&amp; mx )
    {
        std::streamsize width = out.width();
        if( width == 0 )
            width = 4;
        for( auto iRow = begin(mx.field_); iRow != end(mx.field_); ++iRow )
        {
            auto iElement = begin(*iRow);
            for( std::size_t columnIdx = 0; columnIdx &lt; mx.columns_; ++columnIdx )
            {
                out &lt;&lt; &quot; &quot; &lt;&lt; std::setw( width );
                if( iElement != end(*iRow) &amp;&amp; iElement-&gt;first == columnIdx )
                {
                    out &lt;&lt; iElement-&gt;second;
                    ++iElement;
                }
                else
                    out &lt;&lt; T();
            }
            out &lt;&lt; &quot;\n&quot;;
        }
        return out &lt;&lt; std::flush;
    }

    std::size_t NoElements() const // Anzahl belegter Elemente; für Debugzwecke
    {
        return std::accumulate( begin(field_), end(field_), std::size_t(0),
            []( std::size_t sum, const Row&amp; row )-&gt; std::size_t { return sum + row.size(); } );
    }

private:
    std::size_t columns_;
    Field field_;
};
</code></pre>
<p>Was bei dieser Matrixgröße ein No-GO ist, wenn Du jetzt zwei Schleifen baust, die über alle Zeilen und Spalte laufen und dann irgendwelche Operationen ausführen. Bei einer Kantenlänge von 240.000 Elementen einer quadratischen Matrix schlägt jede NanoSekunde der Operation mit einer knappen Minute Laufzeit zu Buche.<br />
D.h. man muss sich auch bei der Operation die dünne Besetzung der Matrix zu Nutze machen.</p>
<p>Als Demonstration habe ich die Addition zweier Matrizen implementiert:</p>
<pre><code>template&lt; typename T &gt;
SparseMatrix&lt; T &gt;&amp; SparseMatrix&lt; T &gt;::operator+=( const SparseMatrix&lt; T &gt;&amp; b ) {
    assert( Rows() == b.Rows() );
    assert( Columns() == b.Columns() );
    auto iRowDst = begin(field_);
    for( auto iRow = begin(b.field_); iRow != end(b.field_); ++iRow, ++iRowDst )
    {
        auto iElementDst = begin(*iRowDst);
        for( auto iElement = begin(*iRow); iElement != end(*iRow); ++iElement )
        {
            for( ; iElementDst != end(*iRowDst) &amp;&amp; iElementDst-&gt;first &lt; iElement-&gt;first; ++iElementDst )
                ;
            if( iElementDst != end(*iRowDst) &amp;&amp; iElementDst-&gt;first == iElement-&gt;first )
            {
                if( (iElementDst-&gt;second += iElement-&gt;second) == T() ) // Auslöschung beachten
                    iElementDst = iRowDst-&gt;erase( iElementDst );
                else
                    ++iElementDst;
            }
            else
                iRowDst-&gt;insert( iElementDst, *iElement );
        }
    }
    return *this;
}
</code></pre>
<p>Die Subtraktion ist identisch - nur in Zeile 15 das += durch ein -= ersetzen.</p>
<p>Bei mir (VS10) benötigt eine leere map&lt;size_t,double&gt; 20 Bytes Speicher. Damit hat eine leere SparseMatrix mit 240.000 Zeilen einem Speicherbedarf von knapp 5MByte. Für jedes Element kommen dann in der Größenordnung 20Byte hinzu (ein Knoten in der Map).<br />
Wahrscheinlich ist es auch schlauer die Map durch eine sortierte Liste von pair<a href="std::size_t,T" rel="nofollow">std::size_t,T</a> (evt. <a href="http://www.cplusplus.com/reference/forward_list/forward_list/" rel="nofollow">forward_list</a>) zu ersetzen. Aber mit der Map war es einfacher zu codieren.</p>
<p>Abschließend eine Demo, die die Funktion zeigt.</p>
<pre><code>int main()
{
    using namespace std;
    SparseMatrix&lt; double &gt; mx( 8, 5 );
    mx( 0, 1 ) = 3.4;
    mx( 7, 4 ) = 99.;
    cout &lt;&lt; fixed &lt;&lt; setprecision( 1 );
    cout &lt;&lt; &quot;\n&quot; &lt;&lt; mx &lt;&lt; &quot;Anzahl Elemente !=0: &quot; &lt;&lt; mx.NoElements() &lt;&lt; endl;
    for( std::size_t c = 0; c &lt; mx.Columns(); ++c )
        mx( 6, c ) = (c+1)*1.1;
    cout &lt;&lt; &quot;\n&quot; &lt;&lt; mx &lt;&lt; &quot;Anzahl Elemente !=0: &quot; &lt;&lt; mx.NoElements() &lt;&lt; endl;
    mx( 6, 1 ) = 0.;
    cout &lt;&lt; &quot;\n&quot; &lt;&lt; mx &lt;&lt; &quot;Anzahl Elemente !=0: &quot; &lt;&lt; mx.NoElements() &lt;&lt; endl;
    cout &lt;&lt; &quot;Der Wert von mx(6,2) ist: &quot; &lt;&lt; mx(6,2) &lt;&lt; endl;

    SparseMatrix&lt; double &gt; m2( 8, 5 );
    m2(2,0) = 2.4;
    m2(6,2) = 3.3;
    m2(6,4) = -5.5;
    mx += m2;
    cout &lt;&lt; &quot;\n&quot; &lt;&lt; mx &lt;&lt; &quot;Anzahl Elemente !=0: &quot; &lt;&lt; mx.NoElements() &lt;&lt; endl;

    return 0;
}
</code></pre>
<p>Wie viele Elemente!=0 enthält Deine Matrix so in etwa? Und welche Operationen benötigst Du für die Matrix?</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285469</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285469</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Wed, 02 Jan 2013 20:18:28 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 08:10:56 GMT]]></title><description><![CDATA[<p>Wow, ich bin beeindruckt vom Code! Vielen Dank!</p>
<p>Dünn besetze Matrizen habe ich. Muss dann noch ein Gleichungssystem lösen. Aber dafür werde ich wahrscheinlich Matlab nutzen und das rüberziehen. Oder ich benutze mit dem Mex-Interface eine Build-in Funktion von Matlab in C++ für das Lösen.</p>
<p>Weitere Operationen brauche ich eig. nicht. Es geht dann doch hauptsächlich um das Füllen und Bearbeiten einzelner Einträge dieser großen Matrix. Das geht ja alles mit dem Code, vielen Dank. Ich muss diesen nur noch ganz verstehen :).</p>
<p>Und leider brauche ich eine ganz große Schleife. Die erste geht nämlich über die Dimension der Länge bzw. Breite (habe eine quadratische Matrix) der Matrix, die zweite dann von 1 bis 3. Also im schlimmsten Fall habe ich 240.000*3 Durchläufe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285535</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285535</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Thu, 03 Jan 2013 08:10:56 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 11:59:16 GMT]]></title><description><![CDATA[<p>Wenn du nen matlab interface hast bietet sich Werners Implementierung aus Performance Gründen nicht an. Soweit ich weiss brauchst du für Matlab alles in einem zusammenhängenden Speicher. D.h. ein haufen Kopieroperation werden fällig.<br />
(nanosekunden und so ... :D)</p>
<p>Google einfach mal nach &quot;Compressed row format&quot; bzw. &quot;Compressed column format&quot;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285651</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285651</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Thu, 03 Jan 2013 11:59:16 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 12:23:03 GMT]]></title><description><![CDATA[<p>Du hast uns immer noch nicht verraten warum du C++ benutzen willst wenn du doch matlab hast? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285667</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285667</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Thu, 03 Jan 2013 12:23:03 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 13:29:25 GMT]]></title><description><![CDATA[<p>cooky451 schrieb:</p>
<blockquote>
<p>Du hast uns immer noch nicht verraten warum du C++ benutzen willst wenn du doch matlab hast? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Aus Performancegründen soll ich C++ benutzen. Man sagte mir, dass wegen den Schleifen C++ schneller ist. Aber wegen den Kopiervorgängen habe ich mir auch schon &quot;Sorgen&quot; gemacht, wie das beim MEX-Interface abläuft.</p>
<p>Ich soll das Programm so schnell wie möglich machen, das ist das Ziel. Ich würde lieber bei Matlab bleiben :).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285703</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285703</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Thu, 03 Jan 2013 13:29:25 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 13:53:34 GMT]]></title><description><![CDATA[<p>Mein Tipp: Bleib einfach bei Matlab. Nicht, dass ich groß Ahnung davon hätte, aber ich weiß ein paar Dinge:<br />
- Die Leute die Matlab implementiert haben, wissen bestimmt was sie tun.<br />
- Du hast keine Ahnung von C++.<br />
-&gt; Es dauert wahrscheinlich mindestens einige Wochen bis du gut genug bist, um Matlab performancemäßig zu schlagen, auch mit Bibliotheken die für dich das Rechnen übernehmen.</p>
<p>Die zeit ist recht grob geschätzt, da ich weder dich noch Matlab gut genug kenne, aber das sollte man trotzdem mal erwähnen. Abgesehen davon: Wenn du wirklich, wirklich Performance brauchst, warum lädst du dann wieder Sachen nach Matlab? Das bringt doch nichts. Wenn, dann rechne gleiche alles in C++ aus. Nimm Eigen oder MTL und lass die möglichst alles rechnen, was die können. Denn deren Algorithmen und Implementierungen sind mit an Sicherheit grenzender Wahrscheinlichkeit deutlich schneller als alles was du oder wir hier mal eben zusammenbasteln könnten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285725</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285725</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Thu, 03 Jan 2013 13:53:34 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 15:22:31 GMT]]></title><description><![CDATA[<p>Das mit Matlab entscheide leider nicht ich allein, sondern meine &quot;Chefs&quot;. Aber Danke für Deinen Rat.</p>
<p>Denn, ich habe mir etwas überlegt: ich schmeiße ganz am Anfang in Matlab erstellte Daten in C++ (mit build-in Funktionen von Matlab), und am Ende hole ich mir das Ergebnis und lasse es in Matlab plotten. Dann habe ich nur die beiden Schnittstellen.</p>
<p>Und, was hälts Du davon, dass ich mein ganzes Matlabprogramm am Ende einfach mit einem Coder in C++-Code übersetze? Matlab bietet dafür eigens eine Lösung. Ob das dann schneller ist?</p>
<p>Auf jeden Fall ziehe ich den Hut vor euch C++-Programmieren! Das ist doch die wahre Kunst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285778</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285778</guid><dc:creator><![CDATA[RobertB]]></dc:creator><pubDate>Thu, 03 Jan 2013 15:22:31 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Thu, 03 Jan 2013 15:37:09 GMT]]></title><description><![CDATA[<p>Das wollt ich gerade vorschlagen. Das moderne Matlab kann C++ Code exportieren (vorausgesetzt ihr habt die entsprechenden Lizenzen).</p>
<p>Ich habe zwar nur seeehhr wenig ahnung vom mex-Interface. Aber könntest du nicht rauskriegen wie Matlab die Sparse-Matrizen implementiert (ich tippe auf eine von den von mir vorgeschlagenden Formaten) und einfach für diese Implementierung die entsprechend Funktionen schreiben die du brauchst (Addition , Multiplikation, Assemblierung und was sonst noch anfällt. Bei den ersten beiden würd ich ma vermuten das sind schon build-ins).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2285783</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2285783</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Thu, 03 Jan 2013 15:37:09 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Fri, 04 Jan 2013 19:44:39 GMT]]></title><description><![CDATA[<p>ScottZhang schrieb:</p>
<blockquote>
<p>Wenn du nen matlab interface hast bietet sich Werners Implementierung aus Performance Gründen nicht an. Soweit ich weiss brauchst du für Matlab alles in einem zusammenhängenden Speicher. D.h. ein haufen Kopieroperation werden fällig.<br />
(nanosekunden und so ... :D)</p>
<p>Google einfach mal nach &quot;Compressed row format&quot; bzw. &quot;Compressed column format&quot;.</p>
</blockquote>
<p>Dass es dafür auch Lösungen gibt, die nur mit Arrays und Indizes funktionieren war ja klar; die gute alte Fortran-Welt lässt grüßen. Aber dass es eine Datenstruktur als Quasi-Standard bis in die Wikipedia geschafft; damit hätte ich jetzt nicht gerechnet.<br />
Ich habe nicht herausbekommen, ob MatLab die Sparse matrix im <a href="http://de.wikipedia.org/wiki/Compressed_Row_Storage" rel="nofollow">CRS</a> abspeichert, aber ich habe mir mal die Mühe gemacht, meine <code>class SparseMatrix</code> auf dieses Format umzustellen.<br />
Es ist nicht wirklich mehr Code geworden, aber es war schwieriger zu implementieren. Ich habe bestimmt mehr als die doppelte Zeit gebraucht wie für die std::map-Lösung.</p>
<p>Keine Ahnung, ob das anderen auch so geht, aber mit den STL-Container kann man auf einem höheren Abstraktionsniveau codieren, und das geht bei mir wesentlich flüssiger.</p>
<p>Die class SparseMatrixc im CRS Datenformat:</p>
<pre><code>#include &lt;algorithm&gt; // for_each, find_if,..
#include &lt;cassert&gt;
#include &lt;iterator&gt; // distance
#include &lt;ostream&gt;
#include &lt;vector&gt;
#include &lt;utility&gt; // std::pair&lt;&gt;

template&lt; typename T &gt;
class SparseMatrix
{
    struct Ref
    {
        Ref( SparseMatrix&amp; mx, std::size_t rowIdx, std::size_t columnIdx )
            : mx_( &amp;mx )
            , rowIdx_( rowIdx )
            , columnIdx_( columnIdx )
        {}
        Ref&amp; operator=( const T&amp; val )
        {
            auto element = mx_-&gt;find_element( rowIdx_, columnIdx_ );
            if( element.second )
            {
                if( (mx_-&gt;val_[element.first] = val) == T() )
                    mx_-&gt;erase_( rowIdx_, element.first );
            }
            else if( val != T() )
                mx_-&gt;insert_( rowIdx_, columnIdx_, element.first, val );
            return *this;
        }
        operator T() const
        {
            auto element = mx_-&gt;find_element( rowIdx_, columnIdx_ );
            return element.second? mx_-&gt;val_[element.first]: T();
        }
    private:
        SparseMatrix* mx_;
        std::size_t rowIdx_;
        std::size_t columnIdx_;
    };
    friend struct Ref;

public:
    SparseMatrix( std::size_t rows, std::size_t columns )
        : columns_( columns )
        , val_()
        , colInd_()
        , rowPtr_( rows+1 )
    {}
    std::size_t Columns() const { return columns_; }
    std::size_t Rows() const { return rowPtr_.size()-1; }

    // --  Element Zugriff
    T operator()( std::size_t rowIdx, std::size_t columnIdx ) const
    {
        assert( rowIdx &lt; Rows() );
        assert( columnIdx &lt; Columns() );
        auto element = find_element( rowIdx, columnIdx );
        return element-&gt;second? val_[element-&gt;first]: T();
    }
    Ref operator()( std::size_t rowIdx, std::size_t columnIdx )
    {
        assert( rowIdx &lt; Rows() );
        assert( columnIdx &lt; Columns() );
        return Ref( *this, rowIdx, columnIdx );
    }

    // --  Ausgabe
    template&lt; typename E, typename Traits &gt; friend
        std::basic_ostream&lt; E, Traits &gt;&amp; operator&lt;&lt;( std::basic_ostream&lt; E, Traits &gt;&amp; out, const SparseMatrix&amp; mx )
    {
        std::streamsize width = out.width();
        if( width == 0 )
            width = 4;
        std::size_t i = 0; // Index in mx.colInd_[] &amp; mx.val_[]
        for( auto iRow = begin(mx.rowPtr_); iRow != end(mx.rowPtr_)-1; ++iRow )
        {
            for( std::size_t columnIdx = 0; columnIdx &lt; mx.columns_; ++columnIdx )
            {
                (out &lt;&lt; &quot; &quot;).width( width );
                if( i &lt; *(iRow+1) &amp;&amp; mx.colInd_[i] == columnIdx )
                    out &lt;&lt; mx.val_[i++];
                else
                    out &lt;&lt; T();
            }
            out &lt;&lt; &quot;\n&quot;;
        }
        return out &lt;&lt; std::flush;
    }

    std::size_t NoElements() const // Anzahl belegter Elemente; für Debugzwecke
    {
        return val_.size();
    }

private:
    void insert_( std::size_t rowIdx, std::size_t columnIdx, std::size_t i, const T&amp; val )
    {
        assert( rowPtr_[rowIdx] &lt;= i );
        assert( i &lt;= rowPtr_[rowIdx+1] );
        assert( std::none_of( begin(colInd_) + rowPtr_[rowIdx], begin(colInd_) + rowPtr_[rowIdx+1],
            [columnIdx]( std::size_t c )-&gt;bool { return c == columnIdx; } ) );
        if( val != T() )
        {
            val_.insert( begin(val_) + i, val );
            colInd_.insert( begin(colInd_) + i, columnIdx );
            std::for_each( begin(rowPtr_) + rowIdx+1, end(rowPtr_), []( std::size_t&amp; idx ) { ++idx; } );
        }
    }
    void erase_( std::size_t rowIdx, std::size_t i )
    {
        assert( i &lt; val_.size() );
        assert( rowPtr_[rowIdx] &lt;= i );
        assert( i &lt; rowPtr_[rowIdx+1] );
        val_.erase( begin(val_) + i );
        colInd_.erase( begin(colInd_) + i );
        std::for_each( begin(rowPtr_) + rowIdx+1, end(rowPtr_), []( std::size_t&amp; idx ) { --idx; } );
    }
    std::pair&lt; std::size_t, bool &gt; find_element( std::size_t rowIdx, std::size_t columnIdx ) const
    {
        auto iColumn = std::find_if( begin(colInd_) + rowPtr_[rowIdx], begin(colInd_) + rowPtr_[rowIdx+1],
            [columnIdx]( std::size_t c )-&gt;bool { return columnIdx &lt;= c; } );
        return std::make_pair( std::size_t( std::distance( begin(colInd_), iColumn ) )
            , iColumn != begin(colInd_) + rowPtr_[rowIdx+1] &amp;&amp; *iColumn == columnIdx );
    }

    // --   Members
    std::size_t columns_;
    // --   Datenstruktur der Sparse Matrix im CRS -&gt; &lt;http://de.wikipedia.org/wiki/Compressed_Row_Storage&gt;
    std::vector&lt; T &gt; val_;
    std::vector&lt; std::size_t &gt; colInd_;
    std::vector&lt; std::size_t &gt; rowPtr_;
};
</code></pre>
<p>Der Speicherbedarf dürfte niedriger sein (ca. bei 20%-30% der vorherigen Lösung) dafür ist das Einfügen neuer Elemente nicht mehr performant. Zumindest nicht wenn man sie einzeln zuweist.</p>
<p>.. es fehlt noch die Addition. Wenn ihr das Demo-main aus meinem vorherigen Posting benutzt, so lasst die Addition einfach weg, oder schreibt Euch eine - viel Spaß damit.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2286332</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2286332</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Fri, 04 Jan 2013 19:44:39 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Sat, 05 Jan 2013 10:08:44 GMT]]></title><description><![CDATA[<p>Sieht wohl so aus als würde Matlab die columns compressen: <a href="http://www.mathworks.de/de/help/matlab/apiref/mxcreatesparse.html" rel="nofollow">Matlab: mxCreateSparse</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2286437</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2286437</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Sat, 05 Jan 2013 10:08:44 GMT</pubDate></item><item><title><![CDATA[Reply to Matrixklasse - kleiner Fehler on Sat, 05 Jan 2013 20:31:12 GMT]]></title><description><![CDATA[<p>CSR ist auch in ublas implmentiert. das Problem an CSR ist wie gesagt das Einfügen bei matrix-vektor und matrix-matrix produkten.</p>
<p>Ein netter Trick dafür ist etwas mehr Speicher als benötigt zu reservieren und die Elemente bei der Berechnung des Produkts am Ende unsortiert einzufügen. Am Schluss wird dann gemerged.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2286626</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2286626</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sat, 05 Jan 2013 20:31:12 GMT</pubDate></item></channel></rss>