Bits bestrafen

Gast #2186122
Lesenswert?
• ▲
▼
Hallo,
ich habe ein Byte (hier Var) und möchte aufgrund der gesetzten Bits eine 
Zahl (hier Zahl) "bestrafen".

Hier z.B. ein Byte
1
unsigned char Var=0b101000;
2
//      Var=10|10|00


Und hier nun die Logik:

Zahl=0;

1. Paket (Bits 1&2 ):
Wenn die ersten beiden Bits 00, dann Zahl=Zahl+1;
Wenn die ersten beiden Bits 10, dann Zahl=Zahl+2;

2. Paket (Bits 3&4):
Wenn die zweiten beiden Bits 00, dann Zahl=Zahl+1;
Wenn die zweiten beiden Bits 10, dann Zahl=Zahl+2;

usw.

Bei dem Beispiel müsste die "Zahl" dann den Wert 5 aufweisen.
Wie kann man so etwas auf einem uController am effektivsten realisieren, 
ohne große If abfragen?


Grüße
#2186138
Lesenswert?
• ▲
▼
Unwissender69 schrieb:
> Wenn die ersten beiden Bits 00, dann Zahl=Zahl+1;
> Wenn die ersten beiden Bits 10, dann Zahl=Zahl+2;

uint8_t result = 0;
if(var & (1 << 6))
  result |= ((var >> 1) + (1 << 6)) & ((1 << 6) | (1 << 7));

Unwissender69 schrieb:
> Wenn die zweiten beiden Bits 00, dann Zahl=Zahl+1;
> Wenn die zweiten beiden Bits 10, dann Zahl=Zahl+2;

if(var & (1 << 4))
  result |= ((var >> 1) + (1 << 4)) & ((1 << 4) | (1 << 5));

Unwissender69 schrieb:
> Bei dem Beispiel müsste die "Zahl" dann den Wert 5 aufweisen.
> Wie kann man so etwas auf einem uController am effektivsten realisieren,
> ohne große If abfragen?

Ganz ohne würde ich es nicht machen. Aber eine pro Paket ist ja nicht so 
schlimm.
#2186158
Lesenswert?
• ▲
▼
Unwissender69 schrieb:
> Dankeschön Samuel,
> das dauert mir zu lange bei 20 Variablen. Der uC ist ja nur mit schieben
> beschäftigt.
Warum denn? Nur einmal pro Rechnung. Und wenn man diese Var >> 1 
temporär speichert ist es nur einmal schieben.
Die (1 << 4) werden vom Compiler ersetzt.

> Werde es in den Speicher legen und geeignet darauf zugreifen.
Oder meinst du das damit?
Moderator #2186165
Lesenswert?
• ▲
▼
Sollen wie im Beispiel immer nur 3 Bitpaare (also die Bits 0 bis 5)
betrachtet werden?

Oder was soll bspw. mit Var=0b10101000 passieren?

Nur aus Neugier: Warum bezeichnest du das Addieren von 1 oder 2 als
"bestrafen"?

Was meinst du mit am "effektivsten"?

Unabhängig davon: Eine sehr schnelle Methode wäre eine Tabelle (Array)
mit 256 Einträgen, von denen jeder das gesamte "Strafmaß" für das
entsprechende Byte enthält.
#2186168
Lesenswert?
• ▲
▼
Ich merke gerade, dass man die if-Abfrage negieren muss.

Und wenn ich schon dabei bin. Ein bisschen optimierter:

uint8_t result = 0, x = (1 << 6), y = (1 << 6) | (1 << 7);
uint8_t varl1 = var >> 1;

do
{

  if(!(var & x))
    result |= (varl1 + x) & y;
  x = x >> 2;
  y = y >> 2;
}
while(x);


Oder in einer Anweisung:

#define mask 0b01010101
var = !(var & mask) * ((var >> 1) & mask + 1);

Ich gebe aber keine Garantie, dass das funktioniert.



Mir fällt gerade auf: Deine Idee funktioniert gar nicht: 0b10 + 2 ergibt 
einen überlauf.
Gast #2186401
Lesenswert?
• ▲
▼
Stefan schrieb:
> Hat dein Byte nur 6 Bit?

Ja, die restlichen Bits werden nicht betrachtet.

Stefan schrieb:
> Können die Bitkombinationen 01 und 11 nicht auftreten?

01 kann auftreten, ist aber ein don't care und 11 tritt nicht auf.

Yalu X. schrieb:
> Sollen wie im Beispiel immer nur 3 Bitpaare (also die Bits 0 bis 5)
> betrachtet werden?

Ja, es sollen nur 3 Bit-Paare verglichen werden.

Yalu X. schrieb:
> soll bspw. mit Var=0b10101000 passieren?

don't care! Nur die ersten 6 bits, und auch da nur paarweise.

Yalu X. schrieb:
> Nur aus Neugier: Warum bezeichnest du das Addieren von 1 oder 2 als
> "bestrafen"?

Weil damit bestimmte Zustände in einem Algorithmus "bestraft" werden 
sollen. Dies bedeutet, je höher die Zahl ist umso unwahrscheinlicher 
wird dieser Zustand. Die Zustände sind einschrittig Kodiert.

Yalu X. schrieb:
> Eine sehr schnelle Methode wäre eine Tabelle (Array)
> mit 256 Einträgen, von denen jeder das gesamte "Strafmaß" für das
> entsprechende Byte enthält.

So hatte ich es vor. Da einige Berechnungen durchgeführt werden, möchte 
ich den Overhead, z.B. für Bitoperationen, so klein als möglich halten.

Yalu X. schrieb:
> Was meinst du mit am "effektivsten"?

Schnelle Abarbeitungszeit.
#2186573
Lesenswert?
• ▲
▼
Korrigiert:
1
#define mask 0b01010101
2
var = (~(var & mask)) * ((var >> 1) & mask + mask);

Ich lerne zwar noch Asm, aber ich komme auf 8 Takte für bis zu 4 Pakete 
in einem Byte (ldi nicht mitgerechnet, mul braucht 2 Takte):
1
.def var r16
2
.def var2 r17
3
.def mask r18
4

5
ldi mask, 0b01010101
6

7
mov var, var2
8
and var, mask
9
com var
10

11
lsr var2
12
and var2, mask
13
add var2, mask
14

15
mul var, var2

Das Ergebnis wäre dann in r0.

Würde der Asm funktionieren (ist mein erster Versuch asm zu schreiben)?
#2186877
Lesenswert?
• ▲
▼
Samuel K. schrieb:
>
1
> .def var r16
2
> .def var2 r17        ; var2 ist vermutlich Dein Eingangsregister
3
                       ; im Beispiel des TO wird dies auf 0b101000 = 40 gesetzt
4
> .def mask 0b01010101 ; = 85
5
> 
6

7
    ; Nach der Operation:   var    var2 (dezimal)
8
> mov var, var2        ;    40     40
9
> andi var, mask       ;    0      40
10
> com var              ;    255    40
11
>                      ; 
12
> lsr var2             ;    255    20
13
> addi var2, mask      ;    255    105
14
> subi var2, 255-mask  ;    255    191(-65)
15
>                      ; 
16
> mul var, var2        ;    R0:R1 = 48705 = High 190 ; Low 65
17
>

... und wo kommt da nun 5 heraus?


Wenn es wirklich schnell gehen soll, dann eine Tabelle mit 64 Einträgen.


Gruß

Jobst
#2187415
Lesenswert?
• ▲
▼
Jobst M. schrieb:
> ... und wo kommt da nun 5 heraus?

sry, ich habe es falsch verstanden. Ich dachte die Zahl soll dem PAket 
dazugerechnet werden.
Ok noch mal überlegen.
1
.def var r16
2
.def res r17
3

4
ldi res, 0
5

6
sbrc var, 6
7
rjmp next1
8
inc res
9
sbrc var, 7
10
inc res
11
next1:
12
sbrc var, 4
13
rjmp next2
14
inc res
15
sbrc var, 5
16
inc res
17
next2:
18
sbrc var, 2
19
rjmp next3
20
inc res
21
sbrc var, 3
22
inc res
23
next3:

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.