muParser und eine Art max-Funktion für laufende Werte
-
Hallo Sepp,
Werte in Feld speichern, std::max_element drauf aufrufen? edit: Anscheinend ist der verlinkte Parser nicht so flexibel, wie ich dachte. Man müsste dafür ein wenig tricksen.
Das könntest du auch in deinen Parser eingeben (sehe nichts, was dagegen spricht). Aber der ist dafür absolut nicht gedacht und es kommt mir sehr komisch vor, dass du diese Art von Frage zu einem Parser für mathematische Ausdrücke stellst.
ich habe halt laufend sich ändernde Eingangs-Werte, und würde die gerne durch den Parser jagen.
Wenn ich das richtig verstehe, meinst Du im Quellcode rumpfuschen, und das trau ich mich ehrlich gesagt nicht, da ich den komplexen Code noch net ansatzweise überschaue. Wäre aber mein letzter Notnagel.
Siehe dringend meinen letzten Beitrag in deinem anderen Thread.
Hab ich auch schon beantwortet.
lg
-
Verstehe ich das richtig, du willst so ein Verhalten?
myMax(0) speichert 0 myMax(5) speichert 5 myMax(4) behält 5 myMax() gibt 5 zurückOder willst du so etwas hier?
myMax(0,5,7,4,9,11,20,6,4,77,23,5) gibt 77 zurückDas würde nämlich mein Code oben machen.
Werte in Feld speichern, std::max_element drauf aufrufen?
Ich wusste, es gibt etwas in der Standardbibliothek

-
mcam77 schrieb:
Wenn ich das richtig verstehe, meinst Du im Quellcode rumpfuschen, und das trau ich mich ehrlich gesagt nicht, da ich den komplexen Code noch net ansatzweise überschaue. Wäre aber mein letzter Notnagel.
Nein, so meinte ich das nicht. Aber bevor ich das vor mache, will ich wirklich sicher sein, was du überhaupt möchtest. Derzeit kommt mir das nicht geheuer vor.
-
@patrick Lösung 1:
also rechnung speichern, z.B. SetExpr("myMax(X1)"); X1 0 = 5 -> speichern Eval() // =5 X1 1 = 3 -> nicht speichern Eval() // =5 X1 2 = 8 -> speichern Eval() // =8 X1 3 = 2 -> nicht speichern Eval() // =8 Result = Eval() // =8@Sepp, bitte les nochmal meine Beiträge, den 1. hab ich editiert und beim 3. hatte ich die Hoffnung, das er Deine Zweifel ausräumt.

-
Wenn du dein Werkzeug vergewaltigen musst, dann ist das ein sehr starkes Anzeichen dafür, dass du das falsche Werkzeug gewählt hast. Daher frag nicht "Wie kann ich mit der Bohrmaschine Fische fangen?", sondern "Womit fange ich Fische?".
Was soll dein Programm machen?
-
value_type myMupMax(value_type val) { static value_type maxVal = val; if(val > maxVal) maxVal = val; return maxVal; }Der Max-Wert bleibt aber für den Rest der Programmausführung vorhanden, d.h. man kann nicht wieder von vorne anfangen.
Es wäre trotzdem interessant zu wissen, wofür du das brauchst. Vielleicht ist das hier der falsche Weg um das Problem anzugehen?
Edit: Funktion mit reset:
value_type myMupMax(value_type val, value_type reset) { static value_type maxVal = val; if(reset) maxVal = val; else if(val > maxVal) maxVal = val; return maxVal; }
-
Ich lese Messwerte ein, die sollen Anhand eines Ausdrucks ausgegeben werden.
Ausdruck Beispiel: ( MyMax(X1)+MyMax(X2) )/2
wenn jetzt für X1 und X2 jeweils Werte zwischen -5 und +5 (z.B. 1000x) durchgetickert sind sollen am Schluß +5 rauskommen, da ja die
( Max(X1)=5 + Max(X2)=5 ) /2 = 5
lg
-
Das schaut doch schon supi aus!
So hatte ich mir das auch vorgestellt! Jetzt wäre es noch nice, wenn ich wüsste wie ich die Funktion, die ja noch C ist in die Klasse rein bekomme(wenn das überhaupt geht) dann könnte mein Code das zurücksetzen übernehmen.
BTW, hab ich schon erfolglos probiert.
lg
-
Die Funktion ist so geschrieben, dass man sie einfach per
parser.DefineFun("myMax", myMupMax);einbinden kann.
Wenn du schreibst, du hättest etwas erfolglos probiert, schreibe doch bitte dazu, was du ausprobiert hast und welche Fehler/Probleme dabei aufgetreten sind. Glaskugeln verstauben sehr schnell und sind deshalb oft in der Reinigung.
Ich würde dein Problem anders lösen. X1 und X2 in einen Vector packen (vorher reserven, falls die Endgröße bekannt ist) und dann std::max_element aufrufen, addieren und durch 2 teilen.
-
#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; typedef double (TForm1::*MySqr)(double); // Hab ich iwo gelesen dass man das bei C++ machen muss * //Ansonsten meckert auch der Compiler p.DefineFun("MySqr", &MySqr); an __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } double TForm1::MySqr(double a_fVal) //Hier ein paar hilflose Versuche { return a_fVal*a_fVal; } void __fastcall TForm1::Button1Click(TObject *Sender) { using namespace mu; try { double fVal = 1; Parser p; p.DefineVar("a", &fVal); p.DefineFun("MySqr", &MySqr); p.SetExpr("MySqr(a)*_pi+min(10,a)"); for (std::size_t a=0; a<11; ++a) { fVal = a; // Change value of variable a Memo1->Lines->Add(p.Eval()); } } catch (Parser::exception_type &e) { std::cout << e.GetMsg() << std::endl; } }[BCC32 Fehler] muParserBase.h(134): E2285 Keine Übereinstimmung für 'ParserCallback::ParserCallback(double (* (_closure )(double))(double),bool)' gefunden
Vollständiger Parser-Kontext
muParserBase.h(133): Entscheidung zum Instantiieren: void void ParserBase::DefineFun<double (* (_closure )(double))(double)>(const std::string &,double (* (_closure )(double))(double),bool)
--- Zurücksetzen des Parser-Kontexts für die Instantiierung...
Unit1.cpp(6): #include Unit1.h
Unit1.h(10): #include muParser.h
muParser.h(32): #include muParserBase.h
muParserBase.h(45): namespace mu
muParserBase.h(62): class ParserBase
muParserBase.h(133): Analyse: void void ParserBase::DefineFun<double (* (_closure )(double))(double)>(const std::string &,double (* (_closure )(double))(double),bool)Implementierung von DefineFun:
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() ); }lg
-
Ich würde dein Problem anders lösen. X1 und X2 in einen Vector packen (vorher reserven, falls die Endgröße bekannt ist) und dann std::max_element aufrufen, addieren und durch 2 teilen.
Ja klar, wenn es nur 2 Eingänge wären. Das Prob ist, das ich das ich die Werte aus dem Ausdruck auslesen muss, und da kann ja alles mögliche drinstehen( z.B. MyMax(X1)+3 ).
Die Hardcore-Methode wäre nat. nach MyMax zu parsen(ohne den eig. Parser), die Werte einzutragen(als String) und das dann dem eig. Parser zu fressen geben. Aber iwie halte ich das nicht für die sauberste Methode
Mit Callback in der Klasse wäre das, denke ich, ne saubere Sache
lg
-
Die Funktion muss eine freie Funktion sein und sich an eine der folgenden Signaturen halten (in diesem Link als Funktionspointer angegeben): http://muparser.beltoforion.de/mup_interface_oprt.html#idDefFun
Das sähe zum Beispiel so aus:
value_type MySqr(value_type val) { return val*val; }Um die Funktion dem Parser hinzuzufügen:
parser.DefineFun("MySqr", MySqr);Das funktioniert ohne irgendwelche Typedefs, die musst du nicht mehr erstellen, da sie schon von der Bibliothek vorgegeben sind.
-
Ich würde mir an Deiner Stelle nochmal anschauen was Funktionszeiger und Methodenzeiger sind und worin die sich unterscheiden.
Dann würde ich mich etwas näher mit der VCL beschäftigen und wo die Unterschiede liegen zwischen "normalen" C++ Klassen und VCL-Klassen. Dann stößt Du auch darauf was dieses "_closure" bedeutet.
Und wenn Du schon am Nachdenken bist. Wieso hat deine Form eine Methode zum Quadratwurzel ziehen? Eine Form hat Methoden und Ereignisse um irgendwelche Eingabe- und Anzeigeelemente zu beeinflussen.