Forum: Mikrocontroller und Digitale Elektronik Wert aus Tabelle finden


von Bane (Gast)


Lesenswert?

Hallo,

ich habe eine Tabelle die folgendermaßen aussieht:

1        0
2        710
5  1648
10  2358
256  5678
1024  7098
1224  7281
1424  7435
1624  7570
1824  7689
2024  7796
2224  7892
2424  7980
2624  8061
2824  8137
3024  8207
3224  8272
3424  8334
...      ...

Der linke Tabellenwert hat einen Maximalwert von 16834.
Ich habe nun einen vorgegebenen Wert von z.B. 2400, und brauche
um die passende Zahl dafür zu interpolieren den nächstgrößeren und
nächstkleineren Tabellenwert.
Kann mir jemand sagen, wie ich diese Werte mit kleinstmöglichem
Rechenaufwand bekommen kann, da durch die Benutzung eines C166
die Leistung relativ eingeschränkt ist, und diese Rechenoperation
zyklisch alle 300ms ausgeführt wird.
Die Programmierung erfolgt in C, und es können keine Fließkommaoperation
verwendet werden. Die linken Tabellenwerte können frei verändert werden,
müßen nur den Raum zwischen 0 und 16384 abdecken.

Danke schonmal für eure Hilfe

von Karl H. (kbuchegg)


Lesenswert?

> Kann mir jemand sagen, wie ich diese Werte mit kleinstmöglichem
> Rechenaufwand bekommen kann

Da deine Tabelle nach der linken Spalte sortiert ist, kannst
du 'binäres Suchen' benutzen.

Google bringt dich mit diesem Stichwort sicher weiter.

von Karl H. (kbuchegg)


Lesenswert?

Aber ich seh grade, dass deine Index-Spalte ja
schöne Zahlenwerte aufweist.

Du hast 6 'Bereiche'

 * 1
 * 2
 * 5
 * 10
 * 256
 * 1024 und alles darüber.

Der springende Punkt ist, dass der 6. Bereich (1024 und alles
darüber) in 200-er Schritten geht. Also kann man aus dem Wert
die Arrayposition ausrechnen.
1
  if( SuchWert < 2 ) {
2
    Kleiner = Tabelle[0];
3
    Groesser = Tabelle[1];
4
5
  else if( SuchWert < 5 ) {
6
    Kleiner = Tabelle[1];
7
    Groesser = Tabelle[2];
8
  }
9
10
  else if( SuchWert < 10 ) {
11
    Kleiner = Tabelle[2];
12
    Groesser = Tabelle[3];
13
  }
14
15
  else if( SuchWert < 256 ) {
16
    Kleiner = Tabelle[3];
17
    Groesser = Tabelle[4];
18
  }
19
20
  else if( SuchWert < 1024 ) {
21
    Kleiner = Tabelle[4];
22
    Groesser = Tabelle[5];
23
  }
24
25
  else {
26
    Index = 5 + ( SuchWert - 1024 ) / 200;
27
    Kleiner = Tabelle[Index];
28
    Groesser = Tabelle[Index+1];
29
  }

Geht natürlich nur, wenn sich die linke Spalte in deiner
Tabelle nicht ändert. Wenn die variabel ist -> binäres Suchen

von Kai S. (Firma: ZeuSWarE GmbH) (zeusosc)


Lesenswert?

Hi,
Ich denke mal das die beiden assoziativ miteinander sind, d.h.
der linke ist eine art Index,..

Dann währe es in drei schritten machbar:

erstens:

packe in ein array alle werte die Kleiner als dein Referenzwert sind, 
und die die größer sind in ein seperates array,..

zweitens:
Suche den größten wert aus array1
drittens:
Suche den kleinsten wert aus array2

grüüße

von Bane (Gast)


Lesenswert?

Nur noch als zusätzliche Info:

rechte Spalte = ln(linke Spalte)*1024

Kann daher die Werte der rechten Spalte frei variieren,  falls dies die 
Sache vereinfachen würde. Muss damit nur den Wertebereich zwischen 0 und 
16384 abdecken können.

von Karl H. (kbuchegg)


Lesenswert?

Beim erneuten Lesen der Fragestellung
habe ich das hier gefunden

> Die linken Tabellenwerte können frei verändert werden,
> müßen nur den Raum zwischen 0 und 16384 abdecken.

Dann mach die linken Tabellenwerte in einem fixen Raster
und du kannst dir ganz einfach ausrchnen, wo denn der
nächst kleinere Wert in der Tabelle zu finden ist.
Wenn du dann noch die Schrittweite als 2-er Potenz
ansiedelt, dann brauchst das noch nicht mal eine
Division sondern der Compiler kann die Division durch
eine Schiebeoperation wegoptimieren.


von Bane (Gast)


Lesenswert?

Ist es dann besser, das ganze auf 2 Tabelle aufzuteilen?
Eine Tabelle für die Werte von 0 - 1024, und eine zweite von 1024 - 
16384?
Da es sich ja um inen logarithmus handelt ändern sich die Werte im 
unteren Zahlenbereich noch sehr schnell, hier muss dann also auch eine 
kleinere Schrittweite gewählt werden.

von Kai S. (Firma: ZeuSWarE GmbH) (zeusosc)


Lesenswert?

Also du möchtest irgendetwas interpolieren,..
Ausgangspunkt ist die linke spalte, die rechte ist eindeutig bestimmt 
durch:

Da der Log.nat. monoton steigend ist, und die zuordnung bijektiv ist, 
folgt das du also NUR die epsilon-Umgebung eines deiner linken werte 
brauchst, (delta umgebung folgt ja, durch folgenstetigkeit, mit folge 
aus gerundeten ln werten).

Also sortiere wie oben erwähnt deine linke spalte, dann hast du den 
nächst größeren und den nächst kleineren wert,..
aus den drei berechnest du dann die rechten spaltenwerte und wenn du 
darauffolgend magst interpolierst du das ganze,..


grüüüße

von Karl H. (kbuchegg)


Lesenswert?

Bane wrote:
> Ist es dann besser, das ganze auf 2 Tabelle aufzuteilen?
> Eine Tabelle für die Werte von 0 - 1024, und eine zweite von 1024 -
> 16384?
> Da es sich ja um inen logarithmus handelt ändern sich die Werte im
> unteren Zahlenbereich noch sehr schnell, hier muss dann also auch eine
> kleinere Schrittweite gewählt werden.

Könnte man machen.
Muss man aber nicht. Wenn man weiss dass ab 1024 eine
andere Schrittweite gewählt wurde, kann man das ja
berücksichtigen. Das 'if' ist schon erfunden.


von Bane (Gast)


Lesenswert?

Danke Karl Heinz,

die erste methode mit den if und den elsif war die beste, welche am 
schnellsten zum Ergebnis kam......also nochmal danke!!

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.