Berechnung einer riesigen Summe mit Multiplikation, Division usw.



  • Hallo liebe Community

    Ich steh gerade vor einem kuriosem Problem. Im Rahmen meiner Diplomarbeit muss ich ein Programm schreiben, das eine zweidimensionale Funktion integriert.
    Das Problem: Diese Funktion ist riesig und hat mehrere Parameter, die ich während der Laufzeit anpassen muss.

    Ich zeig euch mal einen winzigen Ausschnitt von dieser Funktion, damit ihr wisst wovon ich spreche:

    ...(Power(F5,2)*Power(m1,2)*(-4*Power(M(eps),2)*Power(m2,2) - 8*Power(m2,4) - 2*Power(Power(m1,2) + Power(m3,2) - s12 - s23,2) -
    (Power(m2,2)*Power(Power(m1,2) + Power(m3,2) - s12 - s23,2))/Power(M(eps),2) + 12*Power(m2,2)*(-Power(m1,2) - Power(m3,2) + s12 + s23)))/4...
    

    s12, s23 sind die Integrationsvariablen.
    F5, M(eps), m1, m2, m3 sind entweder selber Funktionen oder Parameter der Rechnung.

    Nun habe ich das Gefühl, dass der Compiler von dieser Funktion mit diesen 300 Zeilen nicht alles benutzt, sondern nur einen Teil und den Rest unter den Tisch fallen lässt. Ist so etwas möglich?

    Ich könnte natürlich die Funktion in mehrere Berechnungsschritte unterteilen, aber leider ist das konzeptionell nicht möglich, bzw. zu aufwendig, weil ich diese Funktion alle zwei Tage durch eine andere (die natürlich genau so groß ist) ersetzen muss. Ich möchte also flexibel bleiben und mich nicht alle zwei Tage hinsetzen müssen um die Funktion zu unterteilen. Die Funktion erzeuge ich mit Mathematica und kopiere sie anschließend in meinen C-Code um sie darin weiter zu verarbeiten.

    Der Grund warum ich denke, dass der Compiler irgendwelchen Mist baut, ist weil ich einzelne Funktionswerte aus meinem Programm mit Funktionswerten aus Mathematica verglichen habe und nicht das gleiche rauskam. Die sonstigen Parameter, die in dieser Funktion noch rumschwirren, habe ich mehrmals geprüft.

    Vielleicht wisst ihr eine Lösung oder habt eine Idee woran das liegen könnte.
    Ich zumindest bin gerade ziemlich ratlos.

    Viele Grüße
    Matthias


  • Mod

    Computer vergessen nichts und machen nichts falsch. Sie machen genau das, was du ihnen sagst. Wenn etwas anderes raus kommt, als du erwartest, dann sind entweder deine Erwartungen falsch oder du hast es ihnen falsch gesagt.

    Bei solch einem riesigen Ausdruck kann das natürlich zahlreiche Ursachen haben, von simplen Schreibfehlern, zu unbeachteten Nebeneffekten, zu handfesten Programmierfehlern.
    Zeig doch mal die Formel, wie sie in Mathematika steht und einmal die komplette Funktion in C. Vielleicht sehen wir einen offensichtlichen Fehler. Viele Anfänger fallen zum Beispiel auf die Nase, weil in C eine Division über den Integern wieder ein Integer ist, während ein CAS dann in der Regel einen Bruch daraus macht.



  • Kann Mathematica C-Code ausgeben? Oder gibt Mathematica nur irgendwas aus, was man auch als C interpretieren kann? Ich nehme an letzteres, sonst würde da pow und nicht Power stehen. Und vielleicht hast du irgendwo eine nicht beabsichtige Integer-Division oder sowas.

    Den Compiler kannst du verdächtigen, wenn du dir über die C-Semantik deines Ausdrucks im klaren bist, vorher nicht.



  • Hmm, gute Argumente.
    Dann werde ich wahrscheinlich irgendwo einen Fehler machen. Auf jeden Fall kann ich mir jetzt sich sein, dass von meiner Funktion nichts abgeschnitten wird?

    Was ich mir allerdings auch überlegt habe: Ich arbeite mit double Präzision. Es könnte sein, dass während der Rechnung in den Zwischenschritten große Werte entstehen, die die Präzision der Variablen überschreiten. Falls es zwei solcher großen Terme geben sollte, würde sie sich mit einem unterschiedlichen Vorzeichen gerade wegheben. Wird aber die Präzision überschritten, ist solch eine Cancelierung nicht mehr gegeben. Gleiches würde passieren, wenn eine extrem kleine mit einer extrem großen Zahl multipliziert wird. Vielleicht kommt Mathematica mit solchen Termen besser zurecht als C.

    Mathematica gibt C-Code aus, ja. Dafür gibt es den Befehl CForm[].
    Ich gehe stark davon aus, dass Mathematica mir meine Funktion richtig in C-Code übersetzt, da es bei kleineren Testfunktionen richtig ist.

    Die Funktion, die ich euch oben gezeigt habe, sieht in Mathematica so aus:

    (F5^2\*m1^2\*(-4\*M^2\*m2^2 - 8\*m2^4 - 2\*(m1^2 + m3^2 - s12 - s23)^2 - (m2^2*(m1^2 + m3^2 - s12 - s23)^2)/M^2 + 12\*m2^2\*(-m1^2 - m3^2 + s12 + s23)))/4

    M ist auch hier von eps abhängig.

    Zum Vergleich noch einmal die C Eingabe:

    (Power(F5,2)*Power(m1,2)*(-4*Power(M(eps),2)*Power(m2,2) - 8*Power(m2,4) - 2*Power(Power(m1,2) + Power(m3,2) - s12 - s23,2) - 
    (Power(m2,2)*Power(Power(m1,2) + Power(m3,2) - s12 - s23,2))/Power(M(eps),2) + 12*Power(m2,2)*(-Power(m1,2) - Power(m3,2) + s12 + s23)))/4
    

    Aber bedenkt, dass dies nur ein Ausschnitt meiner riesigen Funktion ist. Die ganze Funktion zu posten, würde den Rahmen sprengen.

    Ich kümmere mich mal um die Fehlersuche. Wenn nichts vom Code abgeschnitten wird, muss es ja an mir liegen...

    Vielen Dank euch zwei für die Antworten!

    P.S.: Übrigens bin ich kein Anfänger mehr 🙂 Ich programmiere wahrscheinlich schon zehn Jahre, aber mit solchen großen Ausdrücken habe ich noch nie zu tun gehabt und ich wollte daher auf Nummer sicher gehen 😉


  • Mod

    Wie sind denn Power, M und die ganzen sXX definiert?



  • Power ist so definiert:

    double Power(double base, double exponent) {
          return pow(base, exponent);
    }
    

    M(eps) so:

    double M(double eps) {
          return (mD+mDs-eps);
    }
    

    s12 und s23 sind die Integrationsvariablen. Diese kommen aus einer Integrationsroutine und durchlaufen einen bestimmten Wertebereich. Es sind double-Größen.

    Die vielen m's die noch in der Funktion rumeiern sind mit #defines definiert:
    Zum Beispiel

    #define m1 0.1396
    

    Ich bin grad auf einer heißen Spur und wahrscheinlich hattet ihr Recht, dass ich sonst irgendwo Mist gebaut habe. Ich muss es aber noch austesten.


Anmelden zum Antworten