muParser und eine Art max-Funktion für laufende Werte


  • Mod

    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. 😃


  • Mod

    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.


Anmelden zum Antworten