Forum: Mikrocontroller und Digitale Elektronik Berechnung einer exponentiellen Abnahme


von Bjoern B. (minkfeld)


Lesenswert?

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

von Kevin K. (nemon) Benutzerseite


Lesenswert?

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?)

von Thomas B. (Firma: Druckerei Beste) (virtupic)


Lesenswert?

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

von yalu (Gast)


Lesenswert?

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?

von Bjoern B. (minkfeld)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Bjoern B. (minkfeld)


Lesenswert?

>Dann brauchst Du ja nur ne Tabelle mit 150 Werten (300 Byte) und dann
>einfach 8-mal vergleichen.

Wie 8-mal vergleichen?

von Gast (Gast)


Lesenswert?

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ß

von Walter (Gast)


Lesenswert?

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

von yalu (Gast)


Lesenswert?

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
}

von yalu (Gast)


Lesenswert?

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.

von 6645 (Gast)


Lesenswert?

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)

von Bjoern B. (minkfeld)


Lesenswert?

Ah,

jetzt hab ich es kapiert. Werd es gleich mal ausprobieren und später mal 
Meldung geben.


Vielen Dank und Gruß

von Gast (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.