Ich finde den Fehler in meinem Programm nicht.
-
Hallo, ich weiß, nicht gerade aussagekräftiger Titel, aber ich wusste nicht was ich anderes nehmen sollte.
Ich möchte folgendes Problem lösen:
Diese Formel (in LaTeX-Code, kann man sich unter http://www.codecogs.com/components/equationeditor/equationeditor.php einfügen und ausgeben lassen, geht leider nicht anders, tut mir leid) berechnen:
C_{N,z} = C_{0,z-1} \cdot \left(\cfrac{V_v}{V_v+V_z}\right) \cdot \sum_{i=1}N\left[\left(\cfrac{V_{z-1}}{V_{z-1}+V_v}\right)i \cdot \left(\cfrac{V_z}{V_v+V_z}\right)^{N-i}\right]+C_{0,z} \cdot \left(\cfrac{V_z}{V_z+V_v}\right)^N
Alles aus V_v ist bekannt. Wie jeder sieht, lässt sich diese Formel nicht ohne weiteres nach V_v umstellen. Also wollte ich das iterativ lösen. Ich gebe im Programm einen Startwert für V_v vor und erhöhe ihn schrittweise, bis mein berechnetes C_{N,z} größer als das vorgebene ist.
Prinzipiell läuft das Programm, es beendet die Rechnung an der richtigen Stelle. Aber das Ergebnis stimmt nicht. Rauskommen müsse für die im Programm angebenen Werte V_v=0,148.
Interessanterweise passiert folgendes: wenn ich die Schrittweite von V_v z.B. verringere, müsste doch dasselbe rauskommen, nur dass mehr Rechenschritte durchgeführt werden müssen. Es kommt dann aber was anderes raus.
Ein Bsp:
V_v=0.0012 (Startwert V_v=0.0001, Schrittweite=0.00001)
V_v=0.000380 (Startwert V_v=0.00001, Schrittweite=0.000001)Ich bin ratlos. Habt ihr eine Idee? Habe ich vllt die Formel nicht richtig eingegeben o.ä.?
#include <stdlib.h> #include <math.h> #include <stdio.h> int main(void){ int i,N; double C_Nz,C_Nzb,C_0z,C_0z1,V_z,V_z1,V_v,a; FILE *fi; fi=fopen("Verschl.dat","w"); fprintf(fi,"C_Nzb \t C_N \t (C_Nzb-C_Nz) \t V_v \n"); C_Nz=5.87; C_0z=0; C_0z1=75; V_z=580; V_z1=1600; V_v=0.00001; N=325; a=0; do{ for(i=1;i<=N;i++){ a=a+pow(V_z1/(V_z1+V_v),i)*pow(V_z/(V_z+V_v),(N-i)); } C_Nzb=C_0z1*(V_v/(V_v+V_z))*a+C_0z*pow(V_z/(V_v+V_z),N); V_v=V_v+0.000001; fprintf(fi,"%6.2f %6.2f %8.3f %6.6f\n",C_Nzb,C_Nz,(C_Nzb-C_Nz),V_v); }while(C_Nzb<C_Nz); }
-
Bist du dir sicher, dass du Formel richtig interpretiert hast? C haengt ja von 2 Parametern, N und Z ab und es riecht quasi nach einer Rekursiven Vorschrift. Was ist denn C(0,0), C(0,1) .... . Wie rechtfertigst du die Abbruchbedingung (!)while(C_Nzb<C_Nz)?
Du kannst die Gleichung aber auch umformen nach 0 = .... und eine Nullstelle in V_v mittels http://de.wikipedia.org/wiki/Bisektion suchen. (oder Newton ...). Ansonsten habe ich die Umsetzung deiner Formel mir nicht genau angesehen, doch es ist problematisch eine kleine Zahl hoch N=325 zu nehmen und dann ueber alle N zu summieren. Fuer gewoehnlich sollte man bei der Summe bei der kleinsten Zahl anfangen, ist numerisch stabiler. Auch die Funktion pow solltest du zwecks numerischer Stabilitaet nicht verwenden, da sie ueber e und ln potenziert. Eine spezialisierte fuer N Element der Ganzen Zahlen sollte nicht das Problem sein. Die Formel innerhalb der summe sieht verdaechtig nach Binominalverteilung aus, vielleicht laesst sich da was ausnutzen.
Das sind meine Tips, loesen aber das Problem nicht.
-
Hallo, erstmal vielen Dank, irgendwie dachte ich mir schon sowas, wie du geschrieben hast. Ist also doch nicht so trivial zu lösen wie anfangsgedacht. OK, muss ich wohl durch.
N = 325 habe ich gewählt, weil ich aus der Literatur ein Beispiel mit deisen Zahlenwerten hab, und mein Programm damit überprüfen wollte.
Ich werde mir deine Anregungen mal zu Gemüte führen, danke!
EDIT: So während des Nachhausewegs habe ich über deine Antwort nachgedacht.
Nein, C_{Nzb} ist nicht von N und Z abhängig, sondern nur von V_v. Vllt habe ich das undeutlich benannt.Meine Abbruchbedingung rechtfertige ich so: ich habe einen Wert C_{N,z} gemessen. Nun will ich das zugehörige V_v wissen. Ich starte meine Rechnung mit einem Wert V_v der erwartungsgemäß kleiner als der reale ist und nähere mich dem realem immer weiter an. Damit ändert sich auch mein C_{Nzb}. Überschreitet er meinen gemessenen wert stoppt das Programm, und ich sollte mein V_v gefunden haben. Das funktioniert ja auch, aber das V_v stimmt nicht.
Was die von dir vorgeschlagenen Verfahren angeht, da muss ich nochmal schauen. Ich kann mir aber nicht vorstellen, dass eine vergleichsweise einfache Rechnung so problematisch sein soll.