Gleichungssystem:
-
Hier mal ein Beispiel für ein anderes Problem.
Problemstellung:
Löse die Gleichungax+b=0.Berechne selber allgemeine Lösung:
x=-b/aSetze dies in einem Programm um:
#include <iostream> using std::cout; using std::cin; using std::endl; double solution(double a, double b) { return -b/a; } int main() { cout << "Dieses Programm löst ax+b=0 nach x auf.\nGeben Sie a an: "; double a; cin >> a; cout << "Geben Sie b an: "; double b; cin >> b; cout << "Daraus folgt x = " << solution(a,b) << endl; }
-
Tipp:
struct punkt { double x, y; }; struct gerade { punkt p; // Ein Punkt der Geraden punkt r; // Richtungsvektor }; gerade mittelsenkrechte(punkt const& a, punkt const& b) { ... } punkt schnittpunkt(gerade const& g1, gerade const& g2) { ... } punkt umkreismittelp(punkt const& p1, punkt const& p2, punkt const& p3) { gerade ms12 = mittelsenkrechte(p1,p2); gerade ms23 = mittelsenkrechte(p2,p3); gerade ms31 = mittelsenkrechte(p3,p1); gerade *g1, *g2; ... Lass g1 und g2 auf zwei der drei Mittelsenkrechten zeigen, die möglichst senkrecht aufeinander stehen, damit die Schnittpunkt-Berechnung schön genau wird. ... punkt ergebnis = schnittpunkt(*g1,*g2); return ergebnis; }Jetzt bist Du dran.
-
Mit struct oder class kann der Fragesteller noch nicht umgehen. Zum Verständnis scheint mir eine einfache Funktion double RechneMirDasAus(double x, double y, double z) zunächst oder überhaupt sinnvoll. Noch ein Hinweis: Der Begriff Gleichungssystem ist anders belegt. Aber das ist Mathematik.
-
Doch ich kann mit struct und class usw. umgehen, das ist kein problem. hab mich auch schon viel mit qt beschäftigt...
das problem ist wohl doch eher mathematisch.
ich dachte es gibt in c++ z.B eine möglichkeit durch eine funktion die senkrechte einer geraden zu berechnen oder den mittelpunkt einer linie, oder eine möglichkeit einen virtuellen graphen zu erstellen. ich wollte eher was in der richtung dass ich z.b 2 geradenfunktionenen (mathematisch) initialisieren kann und anschließen über irgendeine methoden den schnittpunkt ausrechnen lasse, sowas in der richtung habe ich gesucht.
mir ist aber klar geworden, dass ich komplezere rechnungen nur durch viele einfache einzelschritte durch meine klasse durchführen kann. ich glaube ich sollte mich nochmal mit vektoren beschäftigen, das ist nur leider sehr lange her!
gtrotzdem VIELEN DANK an alle
-
Die genannten Probleme lassen sich relativ leicht mit Vektoren lösen.
- Der Mittelpunkt zwischen zwei Punkten mit Ortsvektoren a und b befindet sich an der Position 1/2 * (a + b).
- Einen senkrechten Richtungsvektor von (x,y) erhältst du durch (-y,x). Senkrechten zu einer Geraden gibt es allerdings unendlich viele, von daher sind zusätzliche Einschränkungen notwendig.
C++ bietet keine Funktionalität für solche spezifischen Probleme. Am besten schreibst du dir eine Vektorklasse, falls du häufig mit solchen Rechnungen konfrontiert bist.
-
Flipstar5 schrieb:
das problem ist wohl doch eher mathematisch.
ich dachte es gibt in c++ z.B eine möglichkeit durch eine funktion die senkrechte einer geraden zu berechnen oder den mittelpunkt einer linie, oder eine möglichkeit einen virtuellen graphen zu erstellen. ich wollte eher was in der richtung dass ich z.b 2 geradenfunktionenen (mathematisch) initialisieren kann und anschließen über irgendeine methoden den schnittpunkt ausrechnen lasse, sowas in der richtung habe ich gesucht.
so direkt gibt es das nicht, aber so ähnlich.
Flipstar5 schrieb:
mir ist aber klar geworden, dass ich komplezere rechnungen nur durch viele einfache einzelschritte durch meine klasse durchführen kann.
Nein, nicht unbedingt.
Flipstar5 schrieb:
ich glaube ich sollte mich nochmal mit vektoren beschäftigen, das ist nur leider sehr lange her!
.. das wäre allerdings Voraussetzung! Wenn Du Dir z.B. diesen Beitrag über homogene Koordinaten durchliest und diese Vektor-Klasse benutzt, dann weiter verstanden hast, wie man in homogenen Koordinaten die Gerade einer Mittelsenkrechten zweier Punkte bestimmt, dann kann man es im Grunde so hinschreiben, wie Du es Dir oben gewünscht hast (auf die Gefahr hin, Dich zu überfordern
):#include <iostream> #include <cmath> #include "Vector.h" // s. http://www.c-plusplus.net/forum/viewtopic-var-p-is-1108802.html#1108802 // -- bestimmt den Vektor zu v bei dem der homogene Anteil ==1 ist template< typename T > basic_vector< T > homogen( const basic_vector< T >& v ) { return v / Z( v ); } // -- berechnet die Orthogonale zu v - mit dem homogenen Anteil ==0 template< typename T > basic_vector< T > orthogonale( const basic_vector< T >& v ) { return basic_vector< T >( -Y(v), X(v), 0 ); } // -- berechnet die Mittelsenkrechte template< typename T > basic_vector< T > mittelsenkrechte( const basic_vector< T >& a, const basic_vector< T >& b ) { return ( a + b ) % orthogonale( a - b ); } int main() { using namespace std; Vector a( 3.0, 4.0, 1 ); Vector b( 6.0, 9.0, 1 ); Vector c( 13.0, 6.0, 1 ); cout << homogen( mittelsenkrechte( a, b ) % mittelsenkrechte( b, c ) ) << endl; return 0; }Gruß
WernerEdit: auf krümelkackers Hinweis hin (s.u.) Berechnung der Mittelsenkrechten (Zeile 23) vereinfacht
-
Werner Salomon schrieb:
// -- berechnet die Mittelsenkrechte template< typename T > basic_vector< T > mittelsenkrechte( const basic_vector< T >& a, const basic_vector< T >& b ) { return (( a + b ) / T(2)) % orthogonale( b - a ); }Hier setzt Du aber voraus, dass a und b die gleiche homogene Komponente besitzen. Das müsste streng genommen vorher "normalsiert" werden -- sozusagen auf den gleichen Nenner gebracht werden.
Aber sonst ist das ja extrem elegant.

-
Nachtrag: Das Teilen durch T(2) ist ja eigentlich überflüssig, nicht? Die Sklalierung der Vektoren spielt ja keine Rolle.
-
krümelkacker schrieb:
Werner Salomon schrieb:
// -- berechnet die Mittelsenkrechte ...Hier setzt Du aber voraus, dass a und b die gleiche homogene Komponente besitzen. Das müsste streng genommen vorher "normalsiert" werden -- sozusagen auf den gleichen Nenner gebracht werden.
das ist korrekt.
krümelkacker schrieb:
Aber sonst ist das ja extrem elegant.

Danke

krümelkacker schrieb:
Nachtrag: Das Teilen durch T(2) ist ja eigentlich überflüssig, nicht? Die Sklalierung der Vektoren spielt ja keine Rolle.
Ja tatsächlich - gut erkannt. Da habe ich gar nicht dran gedacht.
Gruß
Werner
-
.. ich setz' da noch einen drauf. Dazu muss ich aber die basic_vector-Klasse noch etwas aufrüsten.
Ich führe einen Einheitsvektor eZ vom Typ eZ_type ein und definiere das Skalarprodukt und das Kreuzprodukt mit einem Vektor.// Klasse für einen mathematischen Vektor in 3D // siehe: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1108802.html#1108802 struct eZ_type {}; // Einheitsvektor in Z namespace { eZ_type eZ; } template< typename T > class basic_vector : boost::additive< basic_vector< T >, boost::multiplicative< basic_vector< T >, T, boost::modable< basic_vector< T >, // % -> Kreuzprodukt boost::modable< basic_vector< T >, eZ_type // % -> Kreuzprodukt eZ > > > > { public: typedef T value_type; // ... wie gehabt basic_vector& operator%=( eZ_type ) { const value_type tmp = m_x; m_x = -m_y; m_y = tmp; m_z = T(0); return *this; } friend basic_vector operator%( eZ_type, basic_vector v ) { return -v %= eZ_type(); } basic_vector operator-() const // das fehlte wohl noch im Original { return basic_vector( -m_x, -m_y, -m_z ); } friend T operator*( const basic_vector& v, eZ_type ) { return v.m_z; } friend T operator*( eZ_type, const basic_vector& v ) { return v.m_z; } // .. usw.und dann vereinfacht sich die Berechnung des Umkreismittelpunktes zu
#include <iostream> #include <cmath> #include "Vector.h" // s. http://www.c-plusplus.net/forum/viewtopic-var-p-is-1108802.html#1108802 + Erweiterung oben // -- bestimmt den Vektor zu v bei dem der homogene Anteil ==1 ist template< typename T > basic_vector< T > homogen( const basic_vector< T >& v ) { return v / (v * eZ); } // -- berechnet die Mittelsenkrechte // Bem.: die Klammerung von ez % (a - b) ist notwendig, da das Kreuzprodukt nicht assoziativ ist template< typename T > basic_vector< T > mittelsenkrechte( const basic_vector< T >& a, const basic_vector< T >& b ) { return ( a + b ) % (eZ % ( a - b )); } int main() { using namespace std; Vector a( 3.0, 4.0, 1 ); Vector b( 6.0, 9.0, 1 ); Vector c( 13.0, 6.0, 1 ); cout << "Umkreismittelpunkt von a,b,c: " << homogen( mittelsenkrechte( a, b ) % mittelsenkrechte( b, c ) ) << endl; return 0; }Gruß
Werner
-
Bei allem Respekt, ich finde, Du hast es mit der Überladung der Operatoren übertrieben. Dass Du % für ein Kreuzprodukt nimmst, habe ich mir denken können, aber auch nur, weil ich den Rechenweg kenne. Über das * als Skalarprodukt bin ich aber trotzdem wieder gestolpert. In 'nem Code Review hätte ich das angemeckert und dot(x,y) und cross(x,y) als Alternativen vorgeschlagen.
-
...und die Funktion
mittelsenkrechtehätte ich auch wieder angemeckert, weil nirgends ersichtlich ist, dass man ihr nur Punkte a/b geben darf, die die gleiche homogene Komponente haben. Das müsste entweder dokumentiert werden oder durcha = homogen(a); b = homogen(b);korrekt behandelt werden.
-
krümelkacker schrieb:
Bei allem Respekt, ich finde, Du hast es mit der Überladung der Operatoren übertrieben. Dass Du % für ein Kreuzprodukt nimmst, habe ich mir denken können, aber auch nur, weil ich den Rechenweg kenne. Über das * als Skalarprodukt bin ich aber trotzdem wieder gestolpert. In 'nem Code Review hätte ich das angemeckert und dot(x,y) und cross(x,y) als Alternativen vorgeschlagen.
Ich meine, dass es letztlich Geschmackssache oder Gewohnheit ist, ob man jetzt einen Operator überlädt oder eine Funktion benutzt. Das % für das Kreuzprodukt ist natürlich nicht optimal, aber in Ermangelung von Alternativen sozusagen der am besten passende Operator, der noch 'frei' war. Sebastian fand das % auch unpassend, hatte aber andererseits keine Hemmung den operator/ für den Vektor im Nenner zu überladen.
Ich mag eben nicht so etwas in dieser Form hinschreiben: dot( cross( a, b ), c ); da ist mir die mehr mathematische Schreibweise (a%b)*c; lieber - aber wie gesagt, das ist Geschmackssache.Übrigens wäre auch der Komma-Operator für das Skalarprodukt bzw. das innere Vektorprodukt geeignet, wie der von Dir angegebene Link zeigt, aber das wolltest Du mit sicher nicht mit dem Hinweis zeigen
.krümelkacker schrieb:
...und die Funktion
mittelsenkrechtehätte ich auch wieder angemeckert, weil nirgends ersichtlich ist, dass man ihr nur Punkte a/b geben darf, die die gleiche homogene Komponente haben. Das müsste entweder dokumentiert werden oder durcha = homogen(a); b = homogen(b);korrekt behandelt werden.
Ja ein bisschen ein kniffliges Problem. Deine vorgeschlagene Lösung ist zwar korrekt, aber irgendwie unschön, da man ja korrekterweise davon ausgehen könnte, dass a und b den selben homogenen Anteil haben. Und dann wäre das a = homogen(a); einfach überflüssig. Mir persönlich würde so etwas in der Form
// -- berechnet die Mittelsenkrechte // Bem.: die Klammerung von ez % (a - b) ist notwendig, da das Kreuzprodukt nicht assoziativ ist template< typename T > basic_vector< T > mittelsenkrechte( const basic_vector< T >& a, const basic_vector< T >& b ) { assert( abs( eZ*a - eZ*b ) <= EPS ); // die Konstante EPS wäre in Abhängig der Anwendung zu bestimmen. return ( a + b ) % (eZ % ( a - b )); }besser gefallen.
Eine andere (vielleicht saubere) Lösung bestünde darin, einen zweiten Vektortyp einzuführen, deren homogener Anteil per Definition immer ==1 ist. D.h. die Funktion 'homogen()' würde so einen Typ als Returntyp haben und die beiden Parameter der Funktion mittelsenkrechte wären eben von diesem Typ.
Gruß
Werner