SCL Parität ermitteln

Matze001

Level-3
Beiträge
2.813
Reaktionspunkte
572
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Forum,

mal wieder ein kleines "Problem", welches ich gern geschickt lösen möchte, aber noch nicht so recht weiß wie.

Es ist folgendes: Ich habe ein Byte mit einer Nummer (0-254), und würde gern die Bitparität daraus ermitteln.

Also: Wenn die Anzahl der Bits gerade ist: Parität = 0, wenn die Anzahl der Bits ungerade ist: Parität = 1

Das ganze würde ich gern in SCL lösen.

Mein erster Gedanke war es zu berechnen, aber irgendwie fehlt mir eine Formel, um die Zahlen zu erreichen die eine Parität bilden.
Der zweite war alle Zahlenwerte die die Parität ergeben mit einem Vergleicher auszuwerten, sieht sehr beschissen aus,
und ist auch irgendwie nicht toll.

Sollte ich vielleicht die AT-Deklaration benutzen, und ein Array of Bool aus dem Byte machen, und dies in einer Schleife vergleichen?
Oder gibt es elegantere Lösungen?

Grüße

Marcel
 
Könnte Dir ne Schleife über die Bits und ein XOR darüber helfen?
Die Aussage dieses XOR-Beispiels ist:
Wenn genau EIN Eingang HI ist, ist auch der Ausgang HI.
Ein Kollege hier hat mal gefragt, ab man XOR kaskadieren kann.
Ja man kann. So kommt man zur Erkenntnis, dass der Ausgang immer dann HI ist, wenn eine ungerade Anzahl der Eingänge HI ist.
 
Auf die Schnelle:
Code:
FUNCTION CheckPari : BOOL
VAR_INPUT
    InByte : BYTE;
END_VAR


VAR_TEMP
    TmpByte : BYTE;
    TmpArray AT TmpByte : ARRAY[0..7] OF BOOL ;
    i : INT;
    count : INT;
END_VAR
   
    TmpByte := InByte;
    count := 0;
    FOR i := 0 TO 7 DO
        IF TmpArray[i] = True THEN 
            count := count + 1;
        END_IF;
    END_FOR;
    
            
    CheckPari := (count MOD 2) = 0;
END_FUNCTION
 
@Zotos,
ich vermute, daß es von der Syntax nicht richtig ist - aber für mich zum Üben - würde die Logik funktionieren?
Code:
[FONT=courier new]FUNCTION CheckPari : BOOL
[/FONT][FONT=courier new]
VAR_INPUT[/FONT]
[FONT=courier new]    InByte : BYTE;[/FONT]
[FONT=courier new]END_VAR[/FONT]

[FONT=courier new]VAR_TEMP[/FONT]
[FONT=courier new]    TmpByte : BYTE;[/FONT]
[FONT=courier new]    TmpArray AT TmpByte : ARRAY[0..7] OF BOOL ;[/FONT]
[FONT=courier new]    i : INT;[/FONT]
[FONT=courier new]END_VAR[/FONT]

[FONT=courier new]    TmpByte := InByte;[/FONT]
[FONT=courier new]    CheckPari := NOT TmpArray[0];[/FONT]
[FONT=courier new]    FOR i := 1 TO 7 DO[/FONT]
[FONT=courier new]        CheckPari := CheckPari XOR TmpArray[i];[/FONT]
[FONT=courier new]    END_FOR;[/FONT]
[FONT=courier new]
END_FUNCTION[/FONT]
 
Könnte man bei der Variablen-Deklaration das tmpByte weglassen und das ARRAY gleich aus dem InByte bilden und sich dadurch auch noch die erste Programmzeile sparen?
 
...
reicht es nicht das Bit xxx.0 abzufragen, ist es nicht gesetzt ist der Zahlenwert gerade.
...
Nein, denn er wollte nicht wissen, ob der Bytewert gerade ist, sondern ob die Anzahl der gesetzten Bits ungerade ist.
...
Es ist folgendes: Ich habe ein Byte mit einer Nummer (0-254), und würde gern die Bitparität daraus ermitteln.

Also: Wenn die Anzahl der Bits gerade ist: Parität = 0, wenn die Anzahl der Bits ungerade ist: Parität = 1
...
Beispiele:
10101010 = FALSE
11100000 = TRUE
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie wärs denn damit:
Code:
FUNCTION ParityCheck : BOOL
// Return: 
// false = Even (Gerade Anzahl Bits ist true)
// true  = Odd  (Ungerade Anzahl Bits ist true)
VAR_INPUT
    IN : BYTE;
END_VAR

VAR_TEMP
    val : BYTE;
END_VAR

BEGIN
    val := IN;
    val := val XOR SHR(IN := val, N := 4);
    val := val XOR SHR(IN := val, N := 2);
    val := val XOR SHR(IN := val, N := 1);
    IF (val AND B#16#1) <> b#16#0  THEN
        ParityCheck := true;
    ELSE
        ParityCheck := false;
    END_IF;
END_FUNCTION
 
Hi,

das geht noch kürzer...

[h=3]Compute parity in parallel[/h]
unsigned int v; // word value to compute the parity of v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; return (0x6996 >> v) & 1; The method above takes around 9 operations, and works for 32-bit words. It may be optimized to work just on bytes in 5 operations by removing the two lines immediately following "unsigned int v;". The method first shifts and XORs the eight nibbles of the 32-bit value together, leaving the result in the lowest nibble of v. Next, the binary number 0110 1001 1001 0110 (0x6996 in hex) is shifted to the right by the value represented in the lowest nibble of v. This number is like a miniature 16-bit parity-table indexed by the low four bits in v. The result has the parity of v in bit 1, which is masked and returned.

Für Byte- Werte kann man die ersten beiden XORs weglassen.
 
Hi,

das geht noch kürzer...

Compute parity in parallel


unsigned int v; // word value to compute the parity of v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; v &= 0xf; return (0x6996 >> v) & 1; The method above takes around 9 operations, and works for 32-bit words. It may be optimized to work just on bytes in 5 operations by removing the two lines immediately following "unsigned int v;". The method first shifts and XORs the eight nibbles of the 32-bit value together, leaving the result in the lowest nibble of v. Next, the binary number 0110 1001 1001 0110 (0x6996 in hex) is shifted to the right by the value represented in the lowest nibble of v. This number is like a miniature 16-bit parity-table indexed by the low four bits in v. The result has the parity of v in bit 1, which is masked and returned.

Für Byte- Werte kann man die ersten beiden XORs weglassen.


Für meinen Geschmack hat Zotos die Aufgabenstellung am besten gelöst. Der Code ist auf den ersten Blick nachvollziehbar. Die Lösung von erdmann ist was für Spezialisten... ;)
 
Hallo,

das kommt von einer meiner liebsten Sammlung von solchen
"Sonderberechnungen", zusammengetragen von Sean Eron Andersen.
http://graphics.stanford.edu/~seander/bithacks.html
Davon gibt es noch eine:
http://aggregate.org/MAGIC/

Für ein Byte:
v ^= v >> 4;
v &= 0xf;
return (0x6996 >> v) & 1

Funktionieren tut das ganze so:
Die erste Zeile kombiniert die zwei Nibbles mittels XOR.
Anschliessend wird maskiert, sodass nur noch die unteren 4 bit übrigbleiben.
Die "magische Zahl" ist eine kleine Lookup- Table, die für die 16 Möglichkeiten
jeweils die Parität enthält.

Das funktioniert tatsächlich.

mfg Erdmann
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die Erklärung.
Leider hab' ich immer noch Probleme es ganz zu verstehen.
Die Kombination der Nibbles ist mir z.B. noch unklar:
Werden nur die beiden Halbbytes miteinander kombiniert, wenn ja - wie adressier ich die?
Oder werden die beiden Halbbytes miteinander vertauscht und dann das Ergebnisbyte mit dem Originalbyte kombiniert?

Wäre es Dir möglich, die Vorgehensweise in AWL oder SCL zu schreiben?


PS: Mein Englisch ist leider nur rudimentär vorhanden und auch mit dieser Schreibweise
...
Für ein Byte:
v ^= v >> 4;
v &= 0xf;
return (0x6996 >> v) & 1
...
hab' ich einige Schwierigkeiten (ist alles schon 'ne Weile her), so daß mir die Links nicht wirklich weiter helfen.
 
Zuletzt bearbeitet:
Hallo,

in AWL:
Code:
L     #V                          // Byte
      PUSH                              // Akku duplizieren
      SRW   4                           // Hohes Nibble nach unten
      XOW                               // beide Nibbles kombinieren
      UW    W#16#F                      // maskieren
      L     W#16#6996                   // "Magic Number"
      SRW                               // schieben
      UW    W#16#1                      // Bit 0 bleibt übrig
      L     0
      <>I                               // wenn <> 0
      =     #ODD                        // => Parity odd

mfg Erdmann
 
Ein letzte Frage, die sich mir nicht ganz erschließt:
...das geht noch kürzer...

...
Code:
[FONT=courier new]...[/FONT]
[FONT=courier new]   TmpByte := InByte;[/FONT]
[FONT=courier new]   CheckPari := NOT TmpArray[0];[/FONT]
[FONT=courier new]   FOR i := 1 TO 7 DO[/FONT]
[FONT=courier new]       CheckPari := CheckPari XOR TmpArray[i];[/FONT]
[FONT=courier new]   END_FOR;[/FONT]
[FONT=courier new]...[/FONT]
gegen (auch wenn's noch kein SCL ist, aber m.M.n. die Anzahl der nötigen Anweisungen - SRW, XOR, UW, SRW, UW, <>1):
...
Code:
L     #V                          // Byte
      PUSH                              // Akku duplizieren
      SRW   4                           // Hohes Nibble nach unten
      XOW                               // beide Nibbles kombinieren
      UW    W#16#F                      // maskieren
      L     W#16#6996                   // "Magic Number"
      SRW                               // schieben
      UW    W#16#1                      // Bit 0 bleibt übrig
      L     0
      <>I                               // wenn <> 0
      =     #ODD                        // => Parity odd
...
Und bei WORD oder DWORD wird's ja noch mehr, oder?
 
Zurück
Oben