Hallo allerseits!
Ich habe eine Frage bezüglich Lösung von Gleichungen in einem µC.
Und zwar habe ich folgende Gleichungen (Bruch) in meinem µC
implementiert:
Zähler:
Nenner:
Dann hab ich auch noch eine zweite ähnliche Gleichungen zu lösen. Ihr
könnt euch vorstellen, dass da ziemlich viel Speicher draufgeht
(ATMega168).
Gibt es vielleicht eine Möglichkeit solche Gleichungen einfacher zu
gestalten (generell) oder gibt es Tipps, wie man solche Sachen
platzsparend implementiert?
PS: Die Variablen sind alles als double definiert.
Vielen Dank!
Ist mir grad eingefallen:
Außer den beiden oben genannten Gleichungen habe ich noch eine
Polynomfunktion dritter Ordnung, die ich mit der Funktion pow() aus der
math.h löse.
Gibt es da vielleicht bessere Vorschläge dazu?
Thx...
OK, hast recht - sind Terme! Aber das ist nicht das Problem. Ich habe
den Zähler und denn Nenner und will das Ergebnis aus dem Bruch! Alle
Variablen sind bekannt! Mir gehts nur darum, ob man beim Lösen solcher
TERME etwas beachten soll...
Er meint die Umgekehrt Polnische Notation, wie sie in HP-Taschenrechnern
benutzt wurde. Die kommt ohne Klammern aus. Auch die Programmiersprache
Forth arbeitet mit dieser Schreibweise, die Zahlen kommen in ein
Stackregister, also FIFO-Speicherung.
UPN: Schon, aber das bringt ihn auch nicht weiter.
Wenn der Term so aussieht, dann sieht er so aus.
Zahlen einsetzen und ausrechnen lassen. Ob der Compiler
nun die Formel in Code umwandelt oder ob man das selbst
in UPN umwandelt und einen Interpreter dafür schreibt kommt
letztenlich auf dasselbe hinaus.
Zum OP:
Was ist denn konkret dein Problem?
Hast du Probleme mit der Rechengenauigkeit?
Dauert die Berechnung zu lange?
oder was stimmt damit nicht?
> PS: Die Variablen sind alles als double definiert.
Das hilft dir bei WinAvr auch nicht viel. Bei WinAvr
gilt: sizeof(double) == sizeof(float)
Und je nachdem in welchem Wertebereich deine Variablen liegen
kann eine 08/15 Implementierung dieser Terme alle möglichen
Ergebnisse liefern: Von ziemlich genau bis hoffnungslos falsch.
float mit seinem 4 Byte hat nun mal nicht mehr Genauigkeit als
5 bis 6 signifikante Ziffern. Die, je nach den konkreten Werten
der Variablen, ganz schnell auf 3 bis 4 signifikante Ziffern
herunter gehen.
@Janine Janine
Mir geht es darum, den Speicher zu optimieren und dachte, dass da
vielleicht was möglich ist! Und da hier viele Experten "rumlaufen",
wollte diese Problem hier mal reinstellen.
Aber dir gehts es wahrscheinlich nur darum, dumme und bissige Kommentare
reinzutippen...
Andy wrote:
> Ist mir grad eingefallen:>> Außer den beiden oben genannten Gleichungen habe ich noch eine> Polynomfunktion dritter Ordnung, die ich mit der Funktion pow() aus der> math.h löse.
Du löst gar nichts.
Eine Gleichung lösen bedeutet:
das x bestimmen, so dass die Gleichung wahr wird
Bsp.
x + 5 = 7
Die Gleichung wird gelöst, indem man bestimmt, dass x gleich 2 sein
muss.
Was du tust:
Du berechnest den Funktionswert eines Terms.
x + 7
für x gleich 10 berechnet sich der Funktionswert zu 17
>> Gibt es da vielleicht bessere Vorschläge dazu?
Möglicherweise. Kommt drauf an, welche Potenzen du hast.
Da du von 3. Potenz gesprochen hast, bietet sich natürlich
an:
x^3 <==> x x x
2 Multiplikationen dürften schneller ablaufen, als die
Potenzierung (die meist über Logarithmus und e-Funktion abläuft,
damit auch mit rationalen Zahlen potenziert werden kann)
Ausserdem gibt es da noch das Horner-Schema
a*x^3 + b*x^2 + c*x
da heben wir doch gleich mal 1 x heraus
(a*x^2 + b*x + c) * x
und schon ist die 3.te Potenz zu einer 2.ten Potenz geworden
Noch ein x herausgehoben
( ( a * x + b ) * x ) + c) * x
und es taucht keine einzige Potenz ausser der ersten mehr auf
(und die ist aber trivial).
:-) Kinder,Kinder, Kinder :-)))))))))
@Andy: Da es dir offensichtlich immer noch nicht aufgefallen ist:
Versuche doch mal deine Frage zu formulieren!!! Was ist denn so schwer
daran?? Wie willst du irgendwann deine Diplomarbeit schreiben, wenn du
nicht mal in der Lage bist ein einfaches Problem hinreichend genau zu
beschreiben?
Da heutzutage soetwas an der Uni wohl nicht gefordert ist, hier eine
kurze Anleitung:
-0. Schritt "Was genau habe ich vor? Ist es sinnvoll umgesetzt? Ist der
Aufwand nötig?"
-1 Schritt: "was habe ich bisher erreicht und WIE habe ich es erreicht?"
(code, Nassi-Schneidermann oder was auch immer)
-2. Schritt: "was funktioniert nicht / was ist schlecht"
-3. Schritt: "was genau sollen die lieben Leute, die sonst nichts zu tun
haben mir an Ideen zukommen lassen, damit mein Problem gelöst werden
kann?"
Das ganze ist formal schon eine Gleichung, die halt so weit umgeformt
ist, dass man sie schon ausrechnen kann. Kritik gibt es (nur) an der
Darstellung - ein Bruchstrich und das ganze in der Form f(x, y, z, ...)
= a / b dargestellt wäre sicherlich verständlicher.
Zur Berechnung selbst: man kann eine Konditionsanalyse und eine
Rundungsfehleranalyse (siehe auch Wikipedia: Kondition (Mathematik))
durchführen, um herauszubekommen, wie stark (Rundungs-)fehler das
Ergebnis der Berechnung verfälschen.
Habe gerade versucht die Gleichung zu vereinfachen - Maple hat aber
nichts gefunden.
vielleicht sollte man das forum weiter unterteilen in:+
lernen und fragen (janine -> =Müll)
und
fakten
es gibt ja gott sei dank schon eine codesammlung, aber wenn ich mir dann
das hier ansehe:
Beitrag "Webserver ATmega32/644DIP ENC28J60"
nur als beispiel, dann hat das nichts mehr mit fakten zu tun.
man müsste sich 400 postings durchlesen, was in wenigen zeilen kurz
erklärt werden könnte...
ist dort halt ein fortschreitender prozess der entwicklung, meiner
meinung nach müssten die ergebnisse dann kurz und bündig in die
codesammlung....
sodenn,
m.
nun gut, diese Aufgabenstellung war mit einigem Nachdenken (wenn
überhaupt nötig) schon noch verständlich, wenn auch fachlich schon etwas
leicht daneben. Da sind die meisten anderen Threads in diesem Forum aber
noch ein ganzes Stückchen schlimmer.
Aber generell muß man schon feststellen, daß fast kein Thread mal mit
einer ordentlichen Problembeschreibung beginnt - in der Regel kann man
da nur ganz pauschale Antworten geben, die dem Fragesteller ohnehin kaum
weiterhelfen, oder man muß ihm erstmal noch die ganzen Details aus der
Nase ziehen, um was Sinnvolles dazu sagen zu können. Ist halt irgendwie
wie eine Seuche.
Aber um mal zum Thema zu kommen: wenn man in Mathematik etwas aufgepaßt
hat, sollte die Umformung/Zusammenfassung einer Gleichung schon fast
kein Problem sein. Der Rest ist dann noch etwas Intuition, damit man ein
gewisses Gefühl hat, wie man am besten sowas anfängt, und ob es sich
überhaupt lohnt. Und mein Gefühl sagt mir jetzt so auf die Schnelle, daß
diese "Gleichung" sich wohl nicht sehr eindampfen läßt - sind einfach zu
viele Variablen, in zu unterschiedlicher Kombination.
Wenn es auf Performance ankommt, sollte man teure Operationen wie
Division/Multiplikation so weit wie möglich rausschmeißen bzw.
zusammenfassen. Wie man solche operationen durch billige Bitschiebereien
ersetzten kann in gewissen Situation, stand auch schon in diversen
Threads.
Wenn einige Variablen vom Kontext der Aufgabe her nur reine Konstanten
sind (die sich also im Programm später nie ändern), dann ersetze die
durch die Konstante und fasse die wenn möglich auch wieder zusammen.
Man muß sich einfach mal eins/zwei Stunden hinsetzen, und bißchen
Mathematik machen, dann sieht man schon, ob was besseres draus wird.
Zu Uli:
Ja , das ist der Weg auch aus meiner Sicht,
wenn es genau sein soll.
(Statistikpakete arbeiten intern so - die guten: "Wertanalyse",
sortieren,..)
Rundungsfehler sind aber auch abhängig von der Zahlendarstellung:
int float double ....
bekannt ist 1/2 = 0 statt 0.5 (bei int)
- ähnliches passiert halt auch bei
anderen Formaten.
Die Frage(-n) sollte(n) primär lauten:
wie genau soll es sein?
welche "worst-case Situationen" gibt es?
Dann erst:
RAM, CPU, ...
Was nutzt genug Speicher, wenn das Ergebnis NOK nicht (nicht OK)
Gruss
c.
> Dann hab ich auch noch eine zweite ähnliche Gleichungen zu lösen.> Ihr könnt euch vorstellen, dass da ziemlich viel Speicher draufgeht
Naja, Du kannst Rechenzeit gegen Speicherverbrauch tauschen, wie immer
bei allen Problemen.
Du willst (vermutlich) möglichst wenig RAM für die Zwischenergebnisse
verwenden. Dann bleibt Dir nix anderes übrig, als den Term teilweise
komplett ausmultiplizieren.
Für den ersten Term kannst Du evtl. folgendes machen:
Solche Teile wie -abx+ab kann man natürlich auch eleganter
programmieren, besonders wenn a und b Konstanten sind.
Es kommt eben immer auf den konkreten Fall an.
Du musst evtl. natürlich Seiteneffekte wie Rundungsfehler und
Auslöschung beachten. Aber vermutlich willst Du das gar nicht, da Dich
das noch gar nicht interessiert was bei Gleitkommazahlen so alles
passieren kann...