Formel oder Rechenweg gesucht.

OP #7397371
Lesenswert?

Hi

Ich stehe etwas auf dem Schlauch, vielleicht kann mir jemand den Weg weisen?

Ich habe eine Eingangszahl. Jedem Bit dieser Zahl ist ein bestimmter Wert zugeordnet.

Z.B: Bit0 -> 0,3 Bit1 -> 0,8 Bit2 -> 1,5 Bit3 -> 2,2

Alle Werte, deren Bits in der Eingangszahl gesetzt sind, sollen einfach zur Ausgangszahl zusammenaddiert werden.

Also Eingangszahl = 5 (Binär 0101) => Ausgangszahl 1,8 (1,5+0,3). Oder Eingangszahl = 14 (Binär 1110) => Ausgangszahl 4,5 (2,2+1,5+0,8).

Beitrag #7397401 wurde von einem Moderator gelöscht.
Moderator (Firma: Titel) Persönliche Seite #7397419
Lesenswert?

Ich würde es in "Zehntel" mit Integern rechnen:

1
int Summe=0;
2
if(Eingangszahl&1) Summe+= 3;
3
if(Eingangszahl&2) Summe+= 8;
4
if(Eingangszahl&4) Summe+=15;
5
if(Eingangszahl&8) Summe+=22;

Das ist schneller und wenns denn unbedingt sein muss, kann man das Ergebnis ja immer noch in den Floatwert umrechnen. Mit ein wenig Nachdenken kann man solche Floatrechnungen aber oft umgehen.

#7397571
Lesenswert?

Lothar M. schrieb:

Das ist schneller ...

Und am schnellsten so:

1
float fConvert (uint8_t uiEingangswert)
2
{
3
  static const float f0 =  .3,
4
                     f1 =  .8,
5
                     f2 = 1.5,
6
                     f3 = 2.2,
7
  afTable[] = {          0,
8
                        f0,
9
                     f1   ,
10
                     f1+f0,
11
                  f2      ,
12
                  f2   +f0,
13
                  f2+f1   ,
14
                  f2+f1+f0,
15
               f3         ,
16
               f3      +f0,
17
               f3      +f1,
18
               f3   +f1+f0,
19
               f3+f2      ,
20
               f3+f2   +f0,
21
               f3+f2+f1   ,
22
               f3+f2+f1+f0};
23

24
  return afTable[uiEingangswert & 0xf];
25
} // fConvert
Moderator (Firma: Titel) Persönliche Seite #7397674
Lesenswert?

Kay-Uwe R. schrieb:

Und am schnellsten so:

Eine LUT ist bei 16 Werten tatsächlich auch ein guter Ansatz. Den Index 10 hätte ich aber schöner formatiert... ;-)

Oder gleich richtig obfuscated:

1
    afTable[] = {0,f0,f1,f1+f0,f2,f2+f0,f2+f1,f2+f1+f0,f3,f3+f0,f3+f1,f3+f1+f0,
2
f3+f2,f3+f2+f0,f3+f2+f1,f3+f2+f1+f0};

Andreas B. schrieb:

So? for (i=0; i<8, ... num[i];

Amoklaufender Pointer: num hat nur 4 Elemente, der Index selektiert 8. War aber auch schon recht spät...

#7397731
Lesenswert?

Man kann die LUT auch mit einer Initialisierungsroutine bestimmen und die Gewichtungen dort als Parametersatz mitgeben. So wären (niederfrequente) Änderungen zur Laufzeit möglich:

1
static float afTable[16] = {};
2

3
void vTableInit (float *pfWeights)
4
{
5
  for (int i = 0; i < 16; i++)
6
    afTable[i] = ((i & 1) ? pfWeights[0] : 0)
7
               + ((i & 2) ? pfWeights[1] : 0)
8
               + ((i & 4) ? pfWeights[2] : 0)
9
               + ((i & 8) ? pfWeights[3] : 0);
10
} // vTableInit
11

12
float fConvert (uint8_t uiEingangswert)
13
{
14
  return afTable[uiEingangswert & 0xf];
15
} // fConvert
#7397734
Lesenswert?

Martin S. schrieb:

Lothar M. schrieb:

Eine LUT ist bei 16 Werten tatsächlich auch ein guter Ansatz.

aber nicht als float, etwas oversized...

Was denn? 16 floats sind 64 Byte groß. Das ist ggf. kürzer als ein Programm. Und ints sind bei einer 32-Bit-Maschine gleichgroß. Ich würde hier bis mindestens zu einer 256er-LUT gehen. Für 16-Bit-Eingangswerte dann auf zwei 256er-LUTs splitten und Low- und High-Byte-Anteile addieren. Für 32 Bit analog 4 LUTs.

#7397818
Lesenswert?

Kay-Uwe R. schrieb:

Barrel-Shifter und Co-Prozessoren wurden aber schon erfunden ...

Was erfunden wurde, ist spätestens dann egal, wenn es um einen konkreten µC geht. Dann kommt es nämlich nur darauf an, wie dieser konkrete µC HW-mäßig ausgestattet ist und was per SW emuliert werden muss. Aber noch geht es ja nur darum, Peter vom Schlauch herunter zu helfen. Ob irgendwelcher Optimierungsaufwand lohnt, hängt sowieso von der konkreten Anwendung bzw. vom sportlichen Ehrgeiz ab.

#7398063
Lesenswert?

Martin S. schrieb:

Einfach 3,8,15 und 22 in Ihren Summen in die LUT und erst am ende einen schönen float draus machen, wenn überhaupt wirklich nötig...

Und dann wird statt 0.3 auf einmal 0.31841 und statt 0.8 0.79876 verlangt - und dann? Hier steht ausdrücklich "zum Beispiel": Peter N. schrieb im Beitrag #7397371:

Z.B: Bit0 -> 0,3 Bit1 -> 0,8 Bit2 -> 1,5 Bit3 -> 2,2

#7398293
Lesenswert?

Lothar M. schrieb:

Amoklaufender Pointer: num hat nur 4 Elemente, der Index selektiert 8. War aber auch schon recht spät...

Es ging ums Prinzip. Weder hat er die Groesse des Parameters angegeben (koennte ja auch int32 sein), noch die Laenge des float array festgelegt.

Apollo M. schrieb:

... variable shifting is ugly and time/code space consuming!

Wer sagt das? Unter welcher Platform soll das so sein?

(Firma: @home) #7398322
Lesenswert?

Andreas B. schrieb:

Jede CPU hat eine simple Shift operation.

Das ist klar und sicher, aber eine variable extra loop (mit shift) ist ungünstig, wenn das auch ohne geht. In den AVR/Tiny Cores von Spence Konde wurde die Arduino Standard shiftout/in() Funktion entspr. meinem Vorschlag ersetzt. Spence Konde hat zuvor umfangreich detailierte Tests durchgeführt und weitere Varianten erprobt. Ziel war maximal shift speed.

#7398375
Lesenswert?

Martin S. schrieb:

Wenn wir schon dabei sind, und was heißt das hier? Was sind "gültige Stellen im Speicher"?

Bei einem Float nach IEEE 754 mit 32 Bit stehen für die Ziffern 23 Bit zur Verfügung - der Rest geht für Vorzeichen und Exponent drauf. https://de.wikipedia.org/wiki/Gleitkommazahl#Speicherformate

Bei einer Ganzzahl von 32 Bit stehen für die Ziffern bis zu 31 Bit zur Verfügung (ein Bit von den 32 fürs Vorzeichen). Wenn man die Ganzzahl also optimal normiert, hat man 8 Bit mehr für gültige Stellen zur Verfügung, also ein Faktor 256 mehr in der Auflösung.

Martin S. schrieb:

Rainer W. schrieb:

geeignet normiert ist

?

https://de-academic.com/dic.nsf/dewiki/1029361

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren