Forum: Mikrocontroller und Digitale Elektronik Logische Inverse in C


von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe eine Wertetabelle wie im Bild im Anhang anhand derer ich einen 
Wert [a...e] bestimmen will. Mit "X" markierte Werte sind egal/"don't 
care". Oben steht der Eingang, links der Ausgang.

Die "einfachste" direkte Implementierung sieht dann so aus:
1
enum id_e
2
{
3
    val_a,
4
    val_b,
5
    val_c,
6
    val_d,
7
    val_e,
8
    val_error,
9
};
10
11
12
enum
13
{
14
    mask_l  = 0x10,
15
    mask_d1 = 0x08,
16
    mask_d2 = 0x04,
17
    mask_t  = 0x02,
18
    mask_e  = 0x01,
19
    mask_all = 0x1F,
20
};
21
22
23
enum id_e ident_v1(uint16_t in)
24
{
25
    enum id_e id;
26
    if( in & mask_e ) /* a */
27
    {
28
        id = val_a;
29
    }
30
    else if( !(in & mask_l) ) /* c */
31
    {
32
        id = val_c;
33
    }
34
    else if( !(in & mask_d1) && !(in&mask_d2) ) /* b */
35
    {
36
        id = val_b;
37
    }
38
    else if( (in & mask_d1) && !(in&mask_d2) ) /* d */
39
    {
40
        id = val_d;
41
    }
42
    else if( !(in & mask_d1) && (in&mask_d2) ) /* e */
43
    {
44
        id = val_e;
45
    }
46
    else
47
    {
48
        id = val_error;
49
    }
50
    return id;
51
};
Das Problem: Schon bei 5x5 Ein- und Ausgängen ist das Ganze ganz schön 
unübersichtlich und damit fehlerträchtig.

Also wird versucht, eine Tabelle auch wieder im Quelltext auf eine 
Tabelle abzubilden:
1
const uint16_t pos[] =
2
{
3
    [val_a] = mask_e,
4
    [val_b] = mask_l,
5
    [val_c] = 0,
6
    [val_d] = mask_l | mask_d1,
7
    [val_e] = mask_l | mask_d2,
8
};
9
10
const uint16_t dontcare[] =
11
{
12
    [val_a] = ~mask_e,
13
    [val_b] = mask_t,
14
    [val_c] = mask_t | mask_d2 | mask_d1,
15
    [val_d] = mask_t,
16
    [val_e] = mask_t,
17
};
18
19
20
enum id_e ident_v2(uint16_t in)
21
{
22
    enum id_e id;
23
    in &= mask_all;
24
    for( int ii = 0; ii<val_error; ii++ )
25
    {
26
        uint16_t m = dontcare[ii];
27
        uint16_t p = pos[ii];
28
        if( (in & ~m) == p )
29
        {
30
            return ii;
31
        }
32
    }
33
    return val_error;
34
};
Das ist schon etwas übersichtlicher. Aber vielleicht mache ich mir das 
alles unnötig kompliziert und es geht besser und einfacher.

Gefühlt würde ich die Problemstellung "logische Inverse" benennen - 
deswegen die Threadüberschrift.

von nicht"Gast" (Gast)


Lesenswert?

Hallo,

1. Du hast dein Problem nicht richtig beschrieben. Weder aus dem Text, 
noch aus dem Quellcode werde ich schlau, was du jetzt genau willst.

2. (wichtig) Was ist deine Frage?

Grüße,

von Peter D. (peda)


Lesenswert?

1
  a = E;
2
  b = L && !D1 && !D2 && !E;
3
  c = !L && !E;
4
// usw.

von quotendepp (Gast)


Lesenswert?

da steh ich nun ich armer tor, bin so klug als wie zuvor...

was hast du vor?

so wie ich das interpretiere möchtest du die schaltung aus der tabelle 
in code umsetzen?

dann nimm dir einfach die wahrheitstabelle, stell dir für jeden ausgang 
einen passenden (minimalen) boolschen term auf und fertig.

tipp: "T" ist sinnlos...

von quotendepp (Gast)


Lesenswert?

edith sagt: so wie von peda vorgeschlagen ;-)

von Günter N. (turtle64)


Lesenswert?

Die Tabelle ist unvollständig, es fehlen noch die Fälle
1, 1, 1, 0, 0
und
1, 1, 1, 1, 0

von Michael D. (sirs)


Angehängte Dateien:

Lesenswert?

Schneller und kürzer als von peda geht nicht. Außer die fehlendne von 
Günter müssen noch berücksichtigt werden.
Herleitung: unnötigen Eingang weglassen, einfach zusammenfassen wie im 
Bild

von Dieter H. (kyblord)


Lesenswert?

Michael D. schrieb:
> Schneller und kürzer als von peda geht nicht. Außer die fehlendne
> von
> Günter müssen noch berücksichtigt werden.
> Herleitung: unnötigen Eingang weglassen, einfach zusammenfassen wie im
> Bild

genau so, sehe ich das auch. Stelle die konjunktive Normalform oder 
disjunktive Normalform auf und vereinfache mit KV-Diagrammen.
Alternativ (hast du ja bereits getan). Ein 2D-Array basteln und dort 
0,1, oder dont care eintragen. Mit KV-Diagrammen spart du natürlich 
Platz.

von noiasca (Gast)


Lesenswert?

1
struct myStruct {
2
  byte mask;
3
  byte filter;
4
};
5
6
const myStruct data[]
7
{
8
  // mask    filter
9
  { 0b00001, 0b00001},
10
  { 0b11101, 0b10000},
11
  { 0b10001, 0b00000},
12
  { 0b11101, 0b11000},
13
  { 0b11101, 0b10100} 
14
};
15
16
17
int check(byte in)
18
{
19
  for (size_t i = 0; i < (sizeof(data) / sizeof(data[0])); i++)
20
  {
21
    if ((in & data[i].mask) == data[i].filter) return i;
22
  }
23
  return -1; // not found
24
}

von Egon D. (Gast)


Lesenswert?

Dieter H. schrieb:

> genau so, sehe ich das auch. Stelle die konjunktive
> Normalform oder disjunktive Normalform auf und
> vereinfache mit KV-Diagrammen.

Quine/McClusky genügt.
Sind ja nur fünf Zeilen.

von Egon D. (Gast)


Lesenswert?

noiasca schrieb:

>
1
> struct myStruct {
2
>   byte mask;
3
>   byte filter;
4
> };
5
> 
6
> const myStruct data[]
7
> {
8
>   // mask    filter
9
>   { 0b00001, 0b00001},
10
>   { 0b11101, 0b10000},
11
>   { 0b10001, 0b00000},
12
>   { 0b11101, 0b11000},
13
>   { 0b11101, 0b10100}
14
> };
15
> 
16
> 
17
> int check(byte in)
18
> {
19
>   for (size_t i = 0; i < (sizeof(data) / sizeof(data[0])); i++)
20
>   {
21
>     if ((in & data[i].mask) == data[i].filter) return i;
22
>   }
23
>   return -1; // not found
24
> }
25
>

Was sind eigentlich Ternärvektoren?
Und was sind Ternärvektorlisten?

SCNR

von Walter T. (nicolas)


Lesenswert?

quotendepp schrieb:
> was hast du vor?

Ich dachte, das ginge aus dem Eingangsposting hervor. Ich will einen 
Decoder programmieren, der aus einer Bitmaske (in) den Schlüssel (return 
value) extrahiert. Ich benutze mal das Wort "Schlüssel", weil mir kein 
besseres Wort einfällt.

Günter N. schrieb:
> Die Tabelle ist unvollständig, es fehlen noch die Fälle
> 1, 1, 1, 0, 0
> und
> 1, 1, 1, 1, 0

Nicht alle Eingänge ergeben einen gültigen "Schlüssel", das stimmt.

quotendepp schrieb:
> tipp: "T" ist sinnlos...

Die Spalte "T" wird hier nicht benötigt, das stimmt. Sie ist aber da.

Dieter H. schrieb:
> Mit KV-Diagrammen spart du natürlich Platz.

Ist der Compiler nicht von sich aus gut darin, logische Wertetabellen 
auszuwerten? Ich weiß es nicht, deswegen frage ich.

quotendepp schrieb:
> so wie von peda vorgeschlage

Ich verstehe den Vorschlag leider nicht. Kann man logische Ausdrücke 
auch als Variablen speichern (so wie Lambda-Ausdrücke in anderen 
Programmiersprachen)? Und wie heisst das Konstrukt?

noiasca schrieb:
> struct myStruct {
>   byte mask;
>   byte filter;
> };

Du packst Positiv-Maske und Filter-Maske zusammen. Keine üble Idee, das 
macht die Sache etwas übersichlicher. Und "mask" und "filter" sind gute 
Namen.

Wahrscheinlich ist es sinnlos zu versuchen, die "inverse" Tabelle zu 
speichern. Sie wäre riesig. Ein schlechter Speed-Memory-Tradeoff.

Egon D. schrieb:
> Sind ja nur fünf Zeilen.

Es werden mehr. Ich fange immer mit den einfachen Sachen an.

Beitrag #6799439 wurde von einem Moderator gelöscht.
von Egon D. (Gast)


Lesenswert?

Walter T. schrieb:

> Egon D. schrieb:
>> Sind ja nur fünf Zeilen.
>
> Es werden mehr. Ich fange immer mit den einfachen
> Sachen an.

Seltsam.
Die nebensächlichen Bemerkungen von mir werden
beantwortet, aber die wichtigen werden ignoriert.
Nun ja.


Und übrigens ist das Beispiel nicht einfach -- es
ist klein.

von Walter T. (nicolas)


Lesenswert?

Egon D. schrieb:
> Die nebensächlichen Bemerkungen von mir werden
> beantwortet, aber die wichtigen werden ignoriert.
> Nun ja.

WTF? Ich habe nicht die geringste Ahnung, worauf Du mit Deinen 
Ternärvektoren hinauswillst und ich habe auch keine Lust auf lange 
Recherchen desbezüglich. Bislang haben Deine "Tipps" immer*) vom Thema 
weggeführt anstelle es weiterzubringen.

*) sobald ein Gegenbeispiel auftaucht, kann das Wort durch "meist" 
ersetzt werden.

Beitrag #6799448 wurde von einem Moderator gelöscht.
von Egon D. (Gast)


Lesenswert?

Walter T. schrieb:

> Egon D. schrieb:
>> Die nebensächlichen Bemerkungen von mir werden
>> beantwortet, aber die wichtigen werden ignoriert.
>> Nun ja.
>
> WTF? Ich habe nicht die geringste Ahnung, worauf Du
> mit Deinen Ternärvektoren hinauswillst

Ich meinte eigentlich meine Erwähnung von Quine/McClusky.


> und ich habe auch keine Lust auf lange Recherchen
> desbezüglich.

Ist mir klar.
Du willst können, ohne in der Tiefe zu verstehen.


> Bislang haben Deine "Tipps" immer*) vom Thema
> weggeführt anstelle es weiterzubringen.

Du bist der "ideale" Manager: Du verlangst Unmögliches
und scheisst jeden zusammen, der das nicht einfach
liefert, sondern darauf hinzuweisen versucht, DASS es
unmöglich ist.

Man dringt einfach nicht zu Dir durch.

Die Bitte: "Oh Moment. Wir haben offenbar unterschiedliche
Sichtweisen auf das Problem. Erkläre mir doch bitte Deine
Sicht." kommt in Deinem Verhaltensrepertoire nicht vor.


Leider sind Deine Fragen häufig recht interessant, so dass
ich mich doch immer wieder verführen lasse, etwas dazu zu
schreiben -- auch wenn ich eigentlich wissen müsste, dass
es zu nichts führt.

von Walter T. (nicolas)


Lesenswert?

Egon D. schrieb:
> Du bist der "ideale" Manager: Du verlangst Unmögliches

Tatsächlich verlange ich gar nichts (außer den normalen Regeln des 
Anstands). Wenn Dich das Thema oder meine Fragen nerven, steht es Dir 
völlig frei, pfeifend Deines Weges zu gehen. Du bist in keinerlei 
Lieferverpflichtung.

Egon D. schrieb:
> und scheisst jeden zusammen, der das nicht einfach
> liefert,

Auch das nicht. Hier bekommt niemand ein böses Wort, der nichts 
schreibt. Aber wer schreibt, sollte sich schon irgendwie daran messen 
lassen. Alles andere ist mimosenhaft.

Egon D. schrieb:
> sondern darauf hinzuweisen versucht, DASS es
> unmöglich ist.

Wenn schon im Eröffnungsbeitrag eine Lösung ist, kann das Problem schon 
einmal nicht unlösbar sein. Es kann höchstens nicht weiter vereinfachbar 
sein. Aber das trifft hier nicht zu. Ich habe ja schon brauchbaren Input 
erhalten.

Egon D. schrieb:
> Ist mir klar.
> Du willst können, ohne in der Tiefe zu verstehen.

Wenn die Frage zu einer konkreten Implementierung in C ist, ist jede Art 
mathematischer, philosophischer oder anthroposophischer Betrachtung eine 
nutzlose Abschweifung. Es gibt Gelegenheiten, wo diese sinnvoll sind - 
und die erkennt man daran, dass da handfeste Begründungen vorhanden 
sind.

Ansonsten ist der Wurf von irgendwelchen fremden aber wichtig klingenden 
Brocken in eine Diskussion eine bewährte Methode der Zersetzung.

Egon D. schrieb:
> Die Bitte: "Oh Moment. Wir haben offenbar unterschiedliche
> Sichtweisen auf das Problem. Erkläre mir doch bitte Deine
> Sicht." kommt in Deinem Verhaltensrepertoire nicht vor.

Das mag so wirken. Aber in den meisten Fällen sieht es für mich so aus, 
als hätten wir gar nicht unterschiedliche Sichtweisen auf das selbe 
Problem, sondern es würden komplett andere Problemstellungen 
hervorgezaubert, die dem Wortlaut nach irgendwie Ähnlichkeit habe, aber 
am Kern der Sache massiv vorbeigehen.

Gerne wird auch zu einem inversen Problem (kompliziert) das inverse 
Problem (einfach) konstruiert und dann umfangreich besprochen.

Egon D. schrieb:
> Ich meinte eigentlich meine Erwähnung von Quine/McClusky.

Was soll ich mit einer algebraischen Lösung von Logik in Normalform, 
wenn ich weder Normalform habe, noch überhaupt geklärt ist, ob der 
Compiler das Problem nicht viel besserer als ich lösen kann, wenn man es 
vernünftig hinschreibt?

von Egon D. (Gast)


Lesenswert?

Walter T. schrieb:

> Egon D. schrieb:
>> Ist mir klar.
>> Du willst können, ohne in der Tiefe zu verstehen.
>
> Wenn die Frage zu einer konkreten Implementierung
> in C ist, ist jede Art mathematischer,
> philosophischer oder anthroposophischer Betrachtung
> eine nutzlose Abschweifung.

Genau das ist eben falsch.

Die Programmiersprache C ist eine formale Sprache,
mit der bestimmte Sachverhalte so beschrieben werden
können, dass sie der maschinellen Bearbeitung
zugänglich werden.

Wenn schon der SACHVERHALT nicht komplett geistig
durchdrungen wurde, braucht man über dessen korrekte
BESCHREIBUNG gar nicht zu diskutieren.

Ich versuche Dich immer wieder darauf hinzuweisen,
dass es die SACHVERHALTE selbst sind, die noch Fragen
aufwerfen -- und Du weist mich immer wieder zurecht,
dass mich das nichts anginge, weil Du ja nur über die
korrekte und zweckmäßige BESCHREIBUNG diskutieren
willst.

Nu ja... mach halt. Nicht mein Problem.


> Ansonsten ist der Wurf von irgendwelchen fremden aber
> wichtig klingenden Brocken in eine Diskussion eine
> bewährte Methode der Zersetzung.

Bei allem Respekt: Das, was Du im Ursprungsbeitrag als
Anhang mitgeschickt hast, ist eine Wahrheitswerteliste
für boolesche Funktionen.
Für MICH springt da der Zusammenhang zu Quine/McClusky
ins Auge (auch wenn die Assoziation sachlich vielleicht
nicht vollkommen korrekt war).


> Egon D. schrieb:
>> Die Bitte: "Oh Moment. Wir haben offenbar unterschiedliche
>> Sichtweisen auf das Problem. Erkläre mir doch bitte Deine
>> Sicht." kommt in Deinem Verhaltensrepertoire nicht vor.
>
> Das mag so wirken. Aber in den meisten Fällen sieht es
> für mich so aus, als hätten wir gar nicht unterschiedliche
> Sichtweisen auf das selbe Problem, sondern es würden
> komplett andere Problemstellungen hervorgezaubert, die dem
> Wortlaut nach irgendwie Ähnlichkeit habe, aber am Kern der
> Sache massiv vorbeigehen.

Nun ja... DAS ist nicht mein Problem.

Ein Diskussionsforum dient -- Überraschung! -- der Diskussion.
Da prallen naturgemäß unterschiedliche Meinungen aufeinander;
es ist dann eine Frage der Diskussionskultur, ob man sich so
darüber austauschen kann, dass alle Seiten davon profitieren.

Du suchst offensichtlich einen unbezahlten Privatlehrer, der
Dir alle Frage sachkundig beantwortet und Dich ansonsten in
Ruhe lässt.


> Egon D. schrieb:
>> Ich meinte eigentlich meine Erwähnung von Quine/McClusky.
>
> Was soll ich mit einer algebraischen Lösung von Logik in
> Normalform, wenn ich weder Normalform habe, noch überhaupt
> geklärt ist, ob der Compiler das Problem nicht viel
> besserer als ich lösen kann, wenn man es vernünftig
> hinschreibt?

Naja, genau das sage ich ja seit gefühlt einem Dutzend
Threads: Der Compiler löst ÜBERHAUPT KEINE Probleme
für Dich! Der Compiler transformiert eine Beschreibung
der Lösung -- die Du zuvor gefunden haben musst -- in
eine andere! Mehr nicht!

von Peter D. (peda)


Lesenswert?

Walter T. schrieb:
> Kann man logische Ausdrücke
> auch als Variablen speichern

Natürlich. Jeder Ausdruck hat in C einen Wert. Für logische Werte gibt 
es extra den Typ bool. Er kann nur den Wert 0 oder 1 annehmen.
Manche MCs können auch Bitvariablen anlegen, z.B. der 8051. Die meisten 
MCs speichern aber bool als int.

von quotendepp (Gast)


Lesenswert?

Walter T. schrieb:
> quotendepp schrieb:
>> so wie von peda vorgeschlage
>
> Ich verstehe den Vorschlag leider nicht. Kann man logische Ausdrücke
> auch als Variablen speichern

evtl. könnte man sich da was zusammen basteln, aber ich wüsste nicht 
wozu.

was peter hier gemacht hat ist einfach die ersten drei zeilen deiner 
tabelle in code umzusetzen:

Peter D. schrieb:
1
 a = E; // a ist nur von E abhängig, alle anderen sind don't care, also a = E
Peter D. schrieb:
1
 b = L && !D1 && !D2 && !E; // b ist wahr/1/true/nicht null/... wenn L = 1, D1, D2 und E = 0/falsch/...

so kannst du das recht einfach der reihe nach runter schreiben. 
theoretisch sogar als tabelle formatiert, da whitespaces in c ja (zum 
glück) kein syntaxelement sind.

also z.b. sowas
1
//       |    L    |    D1    |    D2    |    T    |    E    |...
2
//===============================================================
3
    a    =                                              E;
4
//---------------------------------------------------------------
5
    b    =    L    &&   !D1   &&   !D2   &&            !E;
6
//---------------------------------------------------------------
7
    c    =   !L    &&                                  !E;

von c-hater (Gast)


Lesenswert?

Walter T. schrieb:

> Das Problem: Schon bei 5x5 Ein- und Ausgängen ist das Ganze ganz schön
> unübersichtlich und damit fehlerträchtig.

Das ist so. Ein nur zu gut bekanntes, grundsätzliches und exponentiell 
wachsendes Problem der Informatik...

> Also wird versucht, eine Tabelle auch wieder im Quelltext auf eine
> Tabelle abzubilden:

Das hilft bei relativ kleinen Mengen an Eingängen ganz gut, der 
Lösungsansatz ist aber wegen des exponentiellen Charakters des Problems 
recht schnell am Ende.

> Das ist schon etwas übersichtlicher. Aber vielleicht mache ich mir das
> alles unnötig kompliziert und es geht besser und einfacher.

Nein. Die Sache ist einfach: es gibt KEINE grundsätzliche Lösung für 
das Problem. Das muss man nicht schön finden, ist aber leider ein 
Naturgesetz. Man hat nur die Möglichkeit, den Sachverhalt zu akzeptieren 
und die jeweils bestmögliche Näherung umzusetzen.

Bezüglich der Umsetzung bool'scher Logik gibt es übrigens optimierte und 
(hoffentlich) fehlerfreie generische Lösungen. Sprich: truthtable 
rein->C-Code fällt raus.

von A. S. (Gast)


Lesenswert?

Peter D. schrieb:
> Walter T. schrieb:
>> Kann man logische Ausdrücke
>> auch als Variablen speichern
>
> Natürlich. Jeder Ausdruck hat in C einen Wert. Für logische Werte gibt
> es extra den Typ bool.

Ich vermute, Walters Problem ist, dass er eine andere Schreibweise 
benötigt, weil er "die Reihe" zurückgeben will:
1
enum id_e
2
{
3
    val_a,
4
    val_b,
5
    val_c,
6
    val_d,
7
    val_e,
8
    val_error,
9
};
10
11
enum id_e get_id(bool L, bool D1, bool D2, bool T, bool E)
12
{
13
    if(E) return val_a;
14
    if(!L) return val_c;
15
    if(!D1 && !D2) return val_b;
16
    if(D1 == D2) return val_error;
17
    if(D1) return val_d;
18
    return val_e;
19
}
20
21
//oder in Ausführlich
22
enum id_e get_id(bool L, bool D1, bool D2, bool T, bool E)
23
{
24
    if( 1 &&   1 &&   1 &&  1 &&  E) return val_a;
25
    if( L && !D1 && !D2 &&  1 && !E) return val_b;
26
    if(!L &&   1 &&   1 &&  1 && !E) return val_c;
27
    if( L &&  D1 && !D2 &&  1 && !E) return val_d;
28
    if( L && !D1 &&  D2 &&  1 && !E) return val_e;
29
    return val_error;
30
}
31
32
//oder ohne X
33
enum id_e get_id(bool L, bool D1, bool D2, bool T, bool E)
34
{
35
    if(                        E) return val_a;
36
    if( L && !D1 && !D2 &&    !E) return val_b;
37
    if(!L &&                  !E) return val_c;
38
    if( L &&  D1 && !D2 &&    !E) return val_d;
39
    if( L && !D1 &&  D2 &&    !E) return val_e;
40
    return val_error;
41
}

von Der Opa aus der Muppet Show (Gast)


Lesenswert?

> es gibt KEINE grundsätzliche Lösung für das Problem

Unter dem Namen "Entscheidungstabelle" finden sich grundsätzliche 
Lösungen für Vollständigkeit und Widerspruchsfreiheit. Auch Programme, 
die Entscheidungstabellen überprüfen und Programmcode generieren.

Aber die Lösungen der Mathematiker benutzt niemand. In der Praxis 
klappen Vollständigkeit und Widerspruchsfreiheit sowieso nur bei kleinen 
Problemen, bei denen die hier vorgeschlagenen ad hoc Lösungen besser 
sind.

von A. S. (Gast)


Lesenswert?

Wenn er jedoch tabellen mag: (und defines für countof und binärzahlen 
hat und ggf. asserts)
1
struct LDDTE{uint8 mask; uint8 match;}
2
  
3
struct LDDTE table[]=
4
{{ b00001, b00001}
5
,{ b11101, b10000}
6
,{ b10001, b00000}
7
,{ b11101, b11000}
8
,{ b11101, b10100}};
9
  
10
enum id_e get_id(uint8 val)
11
{
12
enum id_e i;
13
  
14
    for(i=0; i < countof(table); i++)
15
    {
16
    uint8 match = val & table[i].mask;
17
  
18
        if(match==table[i].match) return i;    
19
    }
20
    return i;
21
}

von Walter T. (nicolas)


Lesenswert?

A. S. schrieb:
>> Natürlich. Jeder Ausdruck hat in C einen Wert. Für logische Werte gibt
>> es extra den Typ bool.
>
> Ich vermute, Walters Problem ist, dass er eine andere Schreibweise
> benötigt, weil er "die Reihe" zurückgeben will:

Verstehe. Es gab da ein Mißverständnis über Ein- und Ausgang. Mal wieder 
das klassische "das Inverse Problem ist schwierig und das direkte ist 
einfach, aber ich gehe mal davon aus, dass das einfache Problem gemeint 
ist".

Ich bin erleichtert, dass ich nicht irgendein total praktisches 
Konstrukt ähnlich Lambda-Ausdrücken in C verpasst zu haben.

Die if()-Ausdrücke tabellarisch anzuordnen könnte auch brauchbar sein. 
Muss ich morgen mal ausprobieren.

Egon D. schrieb:
> Naja, genau das sage ich ja seit gefühlt einem Dutzend
> Threads: Der Compiler löst ÜBERHAUPT KEINE Probleme
> für Dich!

Dann gehe ich halt mit dem Compiler falsch um. Ich nutze ihn genau für 
den Zweck, Probleme zu lösen. Ich habe auch nicht vor, noch ein 
Informatik-Studium zu starten, um anschließend damit richtig umzugehen, 
dass er keine Probleme mehr löst.

Egon D. schrieb:
> Für MICH springt da der Zusammenhang zu Quine/McClusky
> ins Auge (auch wenn die Assoziation sachlich vielleicht
> nicht vollkommen korrekt war).

Und mir ist der Zusammenhang dazu völlig egal. Ich sehe nicht im 
geringsten ein, warum ich eine Wertetabelle von Hand optimieren sollte, 
deren Auswertung keinerlei Flaschenhals darstellt und die der Compiler 
wahrscheinlich besser als ich auswerten kann. Ich beschränke meine 
Optimierungen auf Stellen, wo das einen Nutzen hat.

quotendepp schrieb:
> so kannst du das recht einfach der reihe nach runter schreiben.
> theoretisch sogar als tabelle formatiert, da whitespaces in c ja (zum
> glück) kein syntaxelement sind.

Was mir da auffällt: Ihr habt immer so wunderbar kurze Bezeichner in 
euren Beispielen. Habt ihr die in der Realität auch, indem ihr lokale 
Kopien mit kurzen Namen anlegt, oder irgendwelche anderen alias oder 
sieht das bei euch auch in Wirklichkeit genauso übel aus wie bei mir?

c-hater schrieb:
> Die Sache ist einfach: es gibt KEINE grundsätzliche Lösung für
> das Problem.

Naja, es werden am Ende weniger als zwanzig "Schlüssel" und höchstens 12 
Bit Breite sein. Das Problem ist also zum Glück beschränkt und die 
Entscheidungstabelle (danke für das Stichwort!) hat mir netterweise 
schon ein Protokoll-Designer abgenommen.

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Ich bin erleichtert, dass ich nicht irgendein total praktisches
> Konstrukt ähnlich Lambda-Ausdrücken in C verpasst zu haben.

Die Tabelle

A. S. schrieb:
> struct LDDTE table[]=
> {{ b00001, b00001}
> ,{ b11101, b10000}
> ,{ b10001, b00000}
> ,{ b11101, b11000}
> ,{ b11101, b10100}};


ist doch minimal. Wie willst Du sowas noch kleiner machen? Und die paar 
Zeilen Auswertung sind gleich, egal ob Du 100 oder 1000 Einträge hast 
und egal ob Du 5 oder 32 Eingänge hast (abgesehen vom Datentyp)

von quotendepp (Gast)


Lesenswert?

Walter T. schrieb:
> Was mir da auffällt: Ihr habt immer so wunderbar kurze Bezeichner in
> euren Beispielen.

die bezeichner stammen aus deiner tabelle ;-)
wobei längere variablennamen ja auch kein problem darstellen würden, 
sind halt mehr tipparbeit. die länge der variablennamen ist dem compiler 
ja auch ziemlich wurscht...

Walter T. schrieb:
> Habt ihr die in der Realität auch

hmm, ähm, naja, manchmal, selten, immer, vielleicht, weiß nicht, hab 
angst, NEIN!

zumindest nicht immer, kommt auf die situation drauf an. bei einem 
beispiel wie der o.g. tabelle, als zählvariable, in einem "hello world" 
o.ä. schon. aber im allgemeinen sagt die variable aus wofür sie gut ist.

von Walter T. (nicolas)


Lesenswert?

A. S. schrieb:
> Die Tabelle
>
> A. S. schrieb:
>> struct LDDTE table[]=
>> {{ b00001, b00001}
>> ,{ b11101, b10000}
>> ,{ b10001, b00000}
>> ,{ b11101, b11000}
>> ,{ b11101, b10100}};
>
> ist doch minimal.

Die Tabelle ist gut. Schrieb ich ja schon oben. Ich muss mal schauen, 
wie sie aussieht, wenn die Bits sprechende Namen haben, aber auf den 
ersten Blick ist das der meistversprechende Ansatz.

quotendepp schrieb:
> die bezeichner stammen aus deiner tabelle ;-)

Die Bezeichner stammen aus PeDas Abkürzung.

quotendepp schrieb:
> wobei längere variablennamen ja auch kein problem darstellen würden,
> sind halt mehr tipparbeit.

Ein echtes Problem sind sie nicht. Aber man bekommt damit bei Tabellen 
auch einen 38"-Monitor schneller voll, als einem lieb ist.
Aber ich meinte an dieser Stelle auch Bezeichner, nicht unbedingt 
Variablennamen. Hier sind es ja "enum-Konstanten".

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wenn es handoptimiert sein soll, finde ich deinen initialen 
Implementierungsansatz gar nicht so verkehrt. Allerdings würde ich statt 
der if / else if Orgie schlicht den Kurzschluss wählen:
1
enum id_e ident_v1(uint16_t in)
2
{
3
    enum id_e id;
4
5
    if( in & mask_e ) /* a */
6
       return val_a;
7
    if( !(in & mask_l) ) /* c */
8
       return val_c;
9
    if( !(in & mask_d1) && !(in & mask_d2) ) /* b */
10
       return val_b;
11
    if( (in & mask_d1) && !(in & mask_d2) ) /* d */
12
       return val_d;
13
    if( !(in & mask_d1) && (in & mask_d2) ) /* e */
14
       return val_e;
15
16
    return val_error;
17
};

Oder:
1
enum id_e ident_v1(uint16_t in)
2
{
3
    enum id_e id;
4
5
    if( in & mask_e ) /* a */
6
       return val_a;
7
    if( !(in & mask_l) ) /* c */
8
       return val_c;
9
    switch (in & (mask_d1 | mask_d2)) {
10
    case 0:
11
       return val_b;
12
    case mask_d1:
13
       return val_d;
14
    case mask_d2:
15
       return val_e;
16
    }
17
    return val_error;
18
};

von Egon D. (Gast)


Lesenswert?

A. S. schrieb:

> Die Tabelle
>
> A. S. schrieb:
>> struct LDDTE table[]=
>> {{ b00001, b00001}
>> ,{ b11101, b10000}
>> ,{ b10001, b00000}
>> ,{ b11101, b11000}
>> ,{ b11101, b10100}};
>
>
> ist doch minimal.

Das ist "zufällig" beim konkreten Beispiel so; im
allgemeinen muss das keineswegs gegeben sein -- ganz
besonders dann nicht, wenn man mehr als einen Ausgang
hat.

von Walter T. (nicolas)


Lesenswert?

Egon D. schrieb:
> Das ist "zufällig" beim konkreten Beispiel so

Von einem geistigen Nichtdurchdringer aufgestellte Wertetabellen 
funktionieren eben immer nur zufällig, und nicht, weil sie darauf 
angelegt sind, eindeutig zu sein.

Jörg W. schrieb:
> Wenn es handoptimiert sein soll, finde ich deinen initialen
> Implementierungsansatz gar nicht so verkehrt.

Ich bin hier echt kein Freund der Handoptimierung. Das ist eine typische 
Stelle, wo das Dilemma Geschwindigkeit|Lesbarkeit sehr stark in Richtung 
des Letzteren gelöst werden sollte.
 - Die Auswertung des Dekoders ist ganz gemütlich alle 10 Millisekunden.
 - Andererseits ist hier jede Falschauswertung fatal (und einige 
Kombinationen mitunter selten, dass es nicht sofort auffällt).
 - Und 100%ig fest ist die Wertetabelle auch noch nicht.

Eine Handminimierung würde bedeuten
 - bei jeder Fehlersuche in der Nähe die passende Doku zu suchen 
und/oder
 - sehr viele Testfälle zu schreiben und
 - Änderungen sind viel Arbeit.

Und selbst wenn die handoptimierte superschnelle Version ein Muss wäre, 
wäre eine wenig fehlerträchtige übersichtliche Version vorteilhaft. Dann 
kann man die beiden in den Modultests sich gegenseitig prüfen lassen.

von Egon D. (Gast)


Lesenswert?

Walter T. schrieb:

> Egon D. schrieb:
>> Das ist "zufällig" beim konkreten Beispiel so
>
> Von einem geistigen Nichtdurchdringer aufgestellte
> Wertetabellen funktionieren eben immer nur zufällig,
> und nicht, weil sie darauf angelegt sind, eindeutig
> zu sein.

Nicht ganz.

Der geistige Nicht-Durchdringer versteht den Unterschied
zwischen "zufällig" und zufällig nicht.

Macht aber nichts.
Du hast Recht, und ich habe meine Ruhe.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Ich habe es mal ausprobiert. Wenn man die Bezeichner auf fünf Zeichen 
beschränkt, ist es auch mit Bit-Namen noch ganz übersichtlich. Sieht 
dann wie im Anhang aus. (Das Forum wird aus einem so breiten Quelltext 
wohl Durcheinander machen, deswegen als Anhang.)

Wird das wegen zu großer Bitbreite zu breit, kann man das in zwei Zeilen 
teilen, ohne dass es zu unübersichtlich wird.

Die sehr kurze Präprozessor-Makro-Definition wird mir wohl nicht ins 
Genick fallen. So eine Tabelle mit ein paar 
Kurze-Bezeichner-Definitionen muss eh in eine eigene Quelltext-Datei.

Die Auswertung hat noiasca (Gast) oben ja schon passend geschrieben.

Danke für die Anregungen!

Der Opa aus der Muppet Show schrieb:
> Unter dem Namen "Entscheidungstabelle" finden sich grundsätzliche
> Lösungen für Vollständigkeit und Widerspruchsfreiheit.

Auch der Tipp ist sehr brauchbar. Danke dafür!

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Die Auswertung hat noiasca (Gast) oben ja schon passend geschrieben.

Ach du Schande! Das hatte ich überhaupt nicht gesehen. Auch wenn es bei 
mir (zwangsläufig) ziemlich ähnlich aussieht.

von noiasca (Gast)


Lesenswert?

Walter T. schrieb:
> Danke für die Anregungen!

fein.

zu deinem Code:
Dein Code, deine Regeln. Insofern wenns dir gefällt alles gut.

Aber ich kann mir nicht verkneifen

> uint16_t filter;    /**< Nicht-dontcare-Werte */

"Nicht-dontcare-Werte"

könnte man auch einfach

care Werte, Werte von Interesse,

nennen

Vieleicht noch zur Interpretation wie ich mask und filter verstehe

mask ..... das gibt an welche Bitposition von Interesse ist
filter ... das ist das was durch die mask durchkommen muss, vieleicht 
wäre "needle" angebracht, denn es ist ja eigentlich der "Suchbegriff" 
nach dem man sucht.

und nimm für den Struct Namen einen großen Anfangsbuchstaben.
1
struct DecisionTable

vom #define halte ich nichts. Aber wie gesagt, wenns dir gefällt...

von Walter T. (nicolas)


Lesenswert?

noiasca schrieb:
> "Nicht-dontcare-Werte" könnte man auch einfach care Werte, Werte
> von Interesse, nennen

Da ist etwas dran. War auch mein erster Gedanke. Aber "don't care" weckt 
sofort die richtigen Assoziationen (oder neudeutsch "rings a bell"), das 
war bei den anderen Kommentar-Varianten nicht der Fall.

noiasca schrieb:
> und nimm für den Struct Namen einen großen Anfangsbuchstaben.

und die erste Spalte nach dem Komma ist auch falsch ausgerichtet. Ich 
hatte die Datei nochmal korrigiert und es ist die falsche gelöscht 
worden.

noiasca schrieb:
> Vieleicht noch zur Interpretation wie ich mask und filter verstehe

Für mich ist "Maske" ja immer etwas, durch dass etwas durch muss, um 
einen Abdruck/Eindruck zu hinterlassen. Insofern ist für mich der 
"Filter" eher das, was meinem Verständnis einer Maske entspricht. Aber 
die Bezeichnungen "Positivmaske/Negativmaske" hätten eine Symmetrie an 
sich gehabt, die etwas Falsches suggeriert hätte. Insofern finde ich die 
beiden Begriffe nicht verkehrt, weil sie dazu zwingen, genauer 
hinzugucken.

A. S. schrieb:
> Ach du Schande! Das hatte ich überhaupt nicht gesehen. Auch wenn es bei
> mir (zwangsläufig) ziemlich ähnlich aussieht.

Besser zweimal etwas Brauchbares als gar nicht.

von TotoMitHarry (Gast)


Lesenswert?

Walter T. schrieb:
> Eine Handminimierung würde bedeuten

Da kann man doch eine Schleife hinterhängen die eben Mal 0-255 zählt und 
jeden Treffer ausgibt.. es dürfen dann halt nur 5 sein.

von EAF (Gast)


Lesenswert?

TotoMitHarry schrieb:
> Da kann man doch eine Schleife hinterhängen die eben Mal 0-255 zählt und
> jeden Treffer ausgibt.. es dürfen dann halt nur 5 sein.

Falsch!
Alleine Fall a betrachtet, dürfte dabei 127 mal auftreten

von EAF (Gast)


Lesenswert?

Walter T. schrieb:
> Da ist etwas dran. War auch mein erster Gedanke. Aber "don't care" weckt
> sofort die richtigen Assoziationen (oder neudeutsch "rings a bell"), das
> war bei den anderen Kommentar-Varianten nicht der Fall.

Ich mag doch auch eher die Positiv Betrachtung.
Also Fokussierung auf die care Bits.
Warum sollte ich meine Beachtung einem "do not care" Faktum schenken?
Widersinnig...
Beispiel(folgt dem Spickzettel im Eingangsposting):
1
char auswerter(byte value)// ' ' == error;
2
{
3
  if(  value & 0b00001 ) return 'a'; // E sonderfall
4
  if(!(value & 0b10000)) return 'c'; // L sonderfall
5
  
6
  value >>= 2;
7
  value &= 0b011; // restliche auszuwertende Bits
8
9
  const char out[4] = {'b','e','d',' ',};
10
  return out[value];
11
}

von TotoMitHarry (Gast)


Lesenswert?

EAF schrieb:
> Falsch!

Ja sorry, habe ich dann beim Abschicken auch gemerkt.

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.