Hi, ich versuche gerade eine exponentielle Abnahme eines Wertes zu berechnen. Leider soll das ganze auf nem Tiny25 passieren. Da der zu wenig Speicher hat, ist die Berechnung mit der math.h nicht möglich. Das ganze soll ungefähr diese Form haben: wert = 150x(0.9)^t Nun habe ich keine Ahnung wie ich diese Formel anders umsetzen kann. Jemand ne Idee? Gruß Mink
wenn es nicht so genau sein soll, nimm eine wertetabelle und mach eine lineare approximation bei zwischenwerten (oder ist +-*/ erst in der math.h enthalten?)
Da gibt es eine Rekursionsformel: f(x+1) = t*f(x) = f(x) - (1-t)*f(x) Schrittweise kanns du variieren für Genauigkeit oder zeitliche Auflösung. Aber Vorsicht, Der Faktor ist auch exponentiell in der Schrittweite. Also Halbierung heißt von .9 auf sqrt(.9) und Verdoppelung der Schrittweite heißt von .9 auf .9*.9 = .81! Okay, diese Formel hilft nicht bei der Interpolation. Aber um die geht's doch hoffentlich nicht. (?) virtuPIC
Fragen zur Frage: - Was ist der Wertebereich von t (untere und obere Grenze)? - Ist t immer ganzahlig? - Wenn nicht, in welchem Format liegt t vor (Gleitkomma, Festkomma, ...)? - Welches Format und welche Genauigkeit soll das Eregbnis haben, reicht Runden auf die nächste ganze Zahl?
Guten Morgen, >wenn es nicht so genau sein soll, nimm eine wertetabelle und mach eine >lineare approximation bei zwischenwerten das hatte ich schon versucht, klappt auch bei größeren Werten von t da dort nicht so viel Genauigkeit verlangt wird. Bei kleineren Werten von t ist das aber ziemlich ungenau. Aber Danke für den Tip. >Da gibt es eine Rekursionsformel: >f(x+1) = t*f(x) = f(x) - (1-t)*f(x) Hab mal versucht darüber was zu finden und es nachzuvollziehen, aber irgendwie versteh ich es nicht ganz. Vielleicht kannst du mir das etwas genauer erklären? >Fragen zur Frage: >- Was ist der Wertebereich von t (untere und obere Grenze)? >- Ist t immer ganzahlig? >- Wenn nicht, in welchem Format liegt t vor (Gleitkomma, Festkomma, > ...)? >- Welches Format und welche Genauigkeit soll das Eregbnis haben, > reicht Runden auf die nächste ganze Zahl? Der Wertebereich von t liegt zwischen 1-3000, t ist immer ganzahlig. Das Ergebnis soll ganzzahlig zwischen 0-150 liegen. Runden ist kein Problem.
Bjoern B. wrote: > Der Wertebereich von t liegt zwischen 1-3000, t ist immer ganzahlig. Das > Ergebnis soll ganzzahlig zwischen 0-150 liegen. Runden ist kein Problem. Dann brauchst Du ja nur ne Tabelle mit 150 Werten (300 Byte) und dann einfach 8-mal vergleichen. Peter
>Dann brauchst Du ja nur ne Tabelle mit 150 Werten (300 Byte) und dann >einfach 8-mal vergleichen. Wie 8-mal vergleichen?
Hallo, x(t) = a * b^t x(tk+1) / x(tk) = a*b^tk+1/(a*b^tk) = b^tk+1 / b^tk = b^(tk+1-tk) = b^t_Abtast ergo: x(tk+1) = x(tk) * b^t_Abtast mit x(0) = a*b Gruß
>>Dann brauchst Du ja nur ne Tabelle mit 150 Werten (300 Byte) und dann >>einfach 8-mal vergleichen. >Wie 8-mal vergleichen? du schaust zuerst ob dein Wert in der oberen oder der unteren Hälfte der Tabelle liegt dann dann das gleiche in der gefundenen Hälfte usw. das ganze musst du 8x machen um zum Ziel zu kommen
Für t >= 55 wird das auf ganze Zahlen gerundete Ergebnis 0. Es genügt also, eine Tabelle tab mit 55 Elementen anzulegen, so dass tab[i] = 150 * 0.9**i (gerundet) ist. Da alle Tabellenwerte kleiner als 256 sind, benötigt man für jedes Element 1 Byte, für die ganze Tabelle also 55 Bytes. Die Auswerteroutine ist sehr einfach, ein Suchalgorithmus ist nicht erforderlich:
1 | unsigned char f(int t) { |
2 | static unsigned char tab[55] = { |
3 | 150, 135, 122, 109, 98, 89, 80, 72, 65, 58, |
4 | 52, 47, 42, 38, 34, 31, 28, 25, 23, 20, |
5 | 18, 16, 15, 13, 12, 11, 10, 9, 8, 7, |
6 | 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, |
7 | 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, |
8 | 1, 1, 1, 1, 1 |
9 | };
|
10 | |
11 | return t >= 55 ? 0 : tab[t]; |
12 | }
|
Kleiner Nachtrag: Da t nicht negativ wird, sollte man das Funktionsargument als unsigned int deklarieren. Für den gesamten Wertebereich von unsigned int liefert die Routine ein sinnvolles Ergebnis, für negative Werte hingegen nicht.
Eine exponentielle Abnahme bedeutet, dass pro Zeiteinheit ein konstanter Faktor subtrahiert wird. Dies laesst sich gut mit Fractionals erreichen x(n+1) := x(n) - const*(x(n) shr 8)
Ah, jetzt hab ich es kapiert. Werd es gleich mal ausprobieren und später mal Meldung geben. Vielen Dank und Gruß
xk+1 = xk * b^t_Abtast x0 = a*b Wenn a = 150; b = 0.9; und t_Abtast = 1.0s dann: x0 = 135 b^t_Abtast = 0,9 Annahme: x ist 16Bit Festkommazahl mit 256=1,0 und der Faktor ist 16Bit Festkommazahl mit 65536=1,0: x0 = 135*256 b^t_Abtast = 0,9 => Faktor = 58982 16Bit*16Bit Multiplikation liefert 2x16Bit Ergebnis mit xk+1 = obere 16Bit Man muss also nur eine (unsigned) 16Bit*16Bit Multiplikation machen und hat in den obersten 8Bit das Ergebnis ohne zu Interpolieren. Gruß
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.