Entwicklung einer einfachen Matrizenklasse
-
Hi, ich möchte gerne hier irgendwie weitermachen. Was mir noch fehlt, ist ein Konstruktor, der einen
std::vector
annimmt. Hatte gehofft, dieìnitializer_list
nimmt einen an, aber das ist wohl nicht so einfach.Deshalb habe ich noch folgenden:
Mat2D_T(const std::vector<std::vector<valType>>& elements) : Mat2D_T{ elements.size(), elements.front().size() } { for (size_t r = 0; r < rows(); ++r) { for (size_t c = 0; c < columns(); ++c) { if (c >= elements[r].size()) break; const auto v = elements[r][c]; setElement(r, c, v); //EDIT: geht natürlich auch (*this)(r, c) = v; ;-) } } }
Ich nehme den ersten Vector als Spaltenanzahl. Um unsinnige Eingaben abzufangen, müsste das doch genügen?
-
@zeropage sagte in Entwicklung einer einfachen Matrizenklasse:
Um unsinnige Eingaben abzufangen, müsste das doch genügen?
Eine Matrix als vector von vectoren ist an sich schon eine unsinnige Eingabe. ^^
-
Schon deshalb blöd, weil ich eigentlich zB dahin will:
std::vector<std::vector<float>> pArr = { {0., 0. }, {15., 0.}, {15., 9. }, {7.5, 13.}, {0., 9. } }; std::vector<Mat2D_T<float>> mVec; for (const auto& pVec : pArr) { Mat2D_T<float> mt{ pVec }; mVec.push_back(mt); }
-
@zeropage Ich kapiers nicht. Du willst Zeilen
vektorenmatrizen ausstd::vector<sonstwas>
basteln und dann eine Matrix daraus?
-
Vergiss es. Bin betrunken. Punkte sollen eine Matrix sein. Und dann gibt es Matrizen, die ich mit Punkten multiplizieren kann. Habe vorgegriffen. Natürlich erst Matrizen erstellen, dann Punkte, und dann nochmal multiplizieren.
Also vergiss alles. Erst Matrizen, dann Punkte.
-
-
Wieder nüchtern.
std::vector
hat sich erledigt, dieinitializer_list
reicht. Aber noch etwas zu print-Methoden. Ich habe zwar eine Ausgabe,template <typename T> std::ostream& operator<<(std::ostream& stream, const Mat2D_T<T>& mT) { stream << typeid(T).name() << " " << mT.rows() << "x" << mT.columns(); stream << " { "; for (std::size_t r = 0; r < mT.rows(); ++r) { if (r > 0) stream << ", "; stream << "{ "; for (std::size_t c = 0; c < mT.columns(); ++c) { if (c > 0) stream << ", "; stream << mT(r, c); } stream << " }"; } stream << " }\n"; return stream; }
möchte aber gerne mal eine formatierte. Da ich mir vorstellen kann, das die nicht in eine Template-Klasse gehören, habe ich sie in ein
namespace
gepackt.
Ich zeig das lieber jetzt, bevor es irgendwann auftaucht und dann extra korrigiert werden muss.namespace Mat2D { void print(const Mat2D_T<int>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<int>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); void print(const Mat2D_T<float>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<float>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); void print(const Mat2D_T<double>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<double>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); }
Die verschiedene Ausgabe von int und fließkomma ist nur wegen
setprecision()
.void Mat2D::printElement(const Mat2D_T<int>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream) { stream << "(" << row << "," << column << "):"; stream << std::setw(cwidth) << mT.element(row, column); } void Mat2D::printElement(const Mat2D_T<float>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream) { const int cp = 4; const int cpwidth = cwidth + cp; stream << "(" << row << "," << column << "): "; stream << std::setw(cpwidth) << std::fixed << std::setprecision(cp) << mT.element(row, column); }
-
Dieser Beitrag wurde gelöscht!
-
So, jetzt nochmal.
Gut, dann jetzt, wie man zB eine Einheitsmatrix erstellt. Da hätte ich zwei Vorschläge, der erste erscheint mir besser. Kann aber sein, das es besseres gibt, was mir nur nicht einfällt.
Ich lass das jetzt auch stehen, auch wenn mir in der Zwischenzeit was anderes einfällttemplate<typename T> class UnitMat_T : public Mat2D_T<T> { public: using size_t = std::size_t; UnitMat_T(const size_t size) : Mat2D_T<T>(size, size) { for (size_t n = 0; n < size; ++n) (*this)(n, n) = static_cast<T>(1); } };
template<typename T> Mat2D_T<T>getUnitMat(const std::size_t size) { Mat2D_T<T> ut(size, size); for (std::size_t n = 0; n < size; ++n) ut(n, n) = static_cast<T>(1); return ut; }
-
@zeropage sagte in Entwicklung einer einfachen Matrizenklasse:
So, jetzt nochmal.
Gut, dann jetzt, wie man zB eine Einheitsmatrix erstellt. Da hätte ich zwei Vorschläge, der erste erscheint mir besser. [...]template<typename T> class UnitMat_T : public Mat2D_T<T>
Also ich finde den zweiten besser.
UnitMat_T
ist wie einfloat_value_1_t
. Wenn du keinen extrem guten Grund hast, für einen speziellen Wert einen eigenen Typen zu haben, dann lass es. Es wird noch genug andere Gelegenheiten geben, sich das Leben selbst schwer zu machenEigener Typ für quadratische Matrizen könnte ich noch akzeptieren. Die haben ja durchaus etwas andere algebraische Eigenschaften, die einen zusätzlichen Typen rechtfertigen können.
-
Ok. Und die Funktion (dann auch ohne Template?)
getUnitMat()
oder gleichUnitMat()
kann ich dann in denMat2D
namespace schieben?
-
Dieser Beitrag wurde gelöscht!
-
Also so? (mit meinem haben wollen Point). Obwohl eigentlich Blödsinn, ich möchte ja einen Typ
Point
. Aber ich lösch das nicht schon wieder.namespace Mat2D { template<typename val_t> Mat2D_T<val_t> UnitMat(const std::size_t size) { Mat2D_T<val_t> ut(size, size); for (std::size_t n = 0; n < size; ++n) ut(n, n) = static_cast<val_t>(1); return ut; } template<typename val_t> Mat2D_T<val_t> Point2D(const val_t x, const val_t y) { Mat2D_T<val_t> p{ { x, y, static_cast<val_t>(1) } }; return p; } template<typename val_t> Mat2D_T<val_t> Point3D(const val_t x, const val_t y, const val_t z) { Mat2D_T<val_t> p{ { x, y, z } }; return p; } void print(const Mat2D_T<int>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<int>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); void print(const Mat2D_T<float>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<float>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); void print(const Mat2D_T<double>& mT, const int cwidth = 4, std::ostream& stream = std::cout); void printElement(const Mat2D_T<double>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout); }
-
-
Erst mal 'wth' nachschlagen. "what the hell" oder "heaven" plus Fragezeichen.
Öhm, was nimmt man denn da, wenn es eine1
sein soll?
-
Versuch es mal mit 1.
-
@SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:
Versuch es mal mit 1.
1 geht auch, aber ich finde es sogar gut, mit eigentlich überflüssigen
static_cast
die bewusste Absicht zu dokumentieren. Da weiss später jeder dass es so gewollt war.
-
Bewusste Absicht von was? 1 ist 1. noch dazu auf der rechten Seite einer Zuweisung. Soll man wirklich für den Fall programmieren, dass val_t einen überladenen Zuweisungsoperator hat? Der zudem eine sehr sonderbare (nicht-arithmetische) Semantik hätte.
-
@Finnegan sagte in Entwicklung einer einfachen Matrizenklasse:
mit eigentlich überflüssigen static_cast die bewusste Absicht zu dokumentieren.
val_t{ 1 }
^^
-
@SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:
Bewusste Absicht von was? 1 ist 1. noch dazu auf der rechten Seite einer Zuweisung. Soll man wirklich für den Fall programmieren, dass val_t einen überladenen Zuweisungsoperator hat? Der zudem eine sehr sonderbare (nicht-arithmetische) Semantik hätte.
Simple Dokumentation, dass man die Repräsentation der 1 als
float
,complex
oder sonstwas in dem Element speichern möchte und man sich bewusst ist, dass die Matrix nicht unbedingtint
s enthält. Da denke ich nichtmal an komische Typen, sondern dass jemand, der meinen Code liest, klar meine Intention herauslesen kann.Hier mag es trivial sein, woanders vielleicht nicht (und jemand stellt meinen Code um wo vielleicht eine Integer Promotion nicht mehr so läuft wie beabsichtigt). Es schadet jedenfalls nicht, klar in Code auszudrücken, was man will.
@Swordfish sagte in Entwicklung einer einfachen Matrizenklasse:
val_t{ 1 }
^^Ja, das wär auch okay