Hallo,
wie verhält sich eigentlich ein EXOR das so aussieht:
IF ($IN[1] EXOR $IN[2] EXOR $IN[3] EXOR $IN[4])
$CYCFLAG
Hallo,
wie verhält sich eigentlich ein EXOR das so aussieht:
IF ($IN[1] EXOR $IN[2] EXOR $IN[3] EXOR $IN[4])
$CYCFLAG
würde mal behaupten, daß das ein klassiches "nimmer" ist.
Hi,
wie für viele andere Fragen im Forum gilt auch hier: Doku lesen hilft meistens weiter !
Dort steht nämlich (unter "Prioritäten von Operatoren") :
Grundsätzlich gilt:
- Geklammerte Ausdrücke werden zuerst bearbeitet.
- Bei ungeklammerten Ausdrücken wird in der Reihenfolge der Priorität ausgewertet.
- Verknüpfungen mit Operatoren gleicher Priorität werden von links nach rechts ausgeführt.
Bei deiner Fragestellung ($IN[1] EXOR $IN[2] EXOR $IN[3] EXOR $IN[4])
kommt also der dritte Grundsatz zum tragen, d.h. der Ausdruck entspricht:
((($IN[1] EXOR $IN[2]) EXOR $IN[3]) EXOR $IN[4])
Ein einfacher (aber mühsamer) Weg herauszubekommen was da nun wirklich passiert,
ist das Aufstellen einer entsprechenden Tabelle:
$IN[1] $IN[2] $IN[3] $IN[4] Ergebnis 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1 0 1 0 0 1 0 1 1 1 1 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0
(bitte mal nachrechnen !)
In Worten: Das Ergebnis ist 1 (=True) wenn
- genau ein einzelner Eingang 1 ist, oder
- drei (beliebige) Eingänge 1 sind
Es gibt bestimmt auch eine einfachere algebraische Methode um das zu bestimmen,
ist bei mir aber schon ein paar Jahrzehnte her...
gruß
rmac
Da sieht man, wo es hinführt, aus dem Bauch raus zu antworten.
rmac hat natürlich Recht.
Hallo,
wie erreiche ich dann, dass in dieses IF gesprungen wird,wenn nur ein einziger Eingang dieser 4 da ist!
$CYCFLAG
bzw. mehr als einer wird abgewiesen!
Hallo,
wie erreiche ich dann, dass in dieses IF gesprungen wird,wenn nur ein einziger Eingang dieser 4 da ist!
$CYCFLAG
Kannst Du die Eingänge als Gruppeneingang definieren?
If ((Variable = 1) OR (Variable = 2) OR (Variable = 4) OR (Variable = 8)) Then MachWas
Alles anzeigen
Hallo,
wie verhält sich eigentlich ein EXOR das so aussieht:
IF ($IN[1] EXOR $IN[2] EXOR $IN[3] EXOR $IN[4])
$CYCFLAG
Eine Verknüfung von mehreren Variablen mit XOR verhält sich so, dass sie genau dann wahr ist, wenn eine ungerade Anzahl der Eingänge wahr ist (in dem Fall wie schon erwähnt einer oder drei)
Hallo,
wie erreiche ich dann, dass in dieses IF gesprungen wird,wenn nur ein einziger Eingang dieser 4 da ist!
$CYCFLAG
Hmm...
Mir fällt ad-hoc nichts eleganteres ein als:
(A and not B and not C and not D) or (not A and B and not C and not D) or (not A and not B and C and not D) or (not A and not B and not C and D)
Oder typumgewandelt, ist einfacher zu handlen, wenn mal ein Eingang dazukommt:
if ((b2i($IN[1]) + b2i($IN[2]) + b2i($IN[3]) +b2i($IN[4])) == 1) then ....
endif
...
DEFFCT INT b2i(b:in)
bool b
if b then
return 1
ELSE
return 0
ENDIF
ENDFCT
Oder so:
;.==========================================================
;. EXOR_MORE(Par1,Par2,Par2)
;. Par1 ... :OUT BOOL Array[]
;. Par2 ... :IN INT StartElement
;. Par3 ... :IN INT Anzahl Elemente
;. Result ... BOOL True wenn nur ein Eingang 1 ist.
;.==========================================================
DEFFCT BOOL EXOR_MORE(bArray[] :OUT,nStart :IN,nLen :IN)
BOOL bArray[],bOk
INT nStart,nEnd,nLen,K,L
nEnd = nStart + nLen-1
For K = nStart To nEnd
If bArray[K] Then
bOk = bArray[K]
For L = K To nEnd
bOk = (K<>L) AND bOk AND NOT bArray[L] OR (K==L) AND bOk
Endfor
Return bOk
Endif
Endfor
Return False
ENDFCT
Alles anzeigen
Beispiel der EXOR_MORE-Funktion:
BOOL bOk, bMyArray[5]
bOk = EXOR_MORE($IN[],20,4)
=> True wenn nur einer der Eingaenge 20 bis 23 High ist.
oder...
bMyArray[1] = $IN[7]
bMyArray[2] = $IN[13]
bMyArray[3] = $IN[24]
bMyArray[4] = $IN[29]
bMyArray[5] = $IN[33]
bOk = EXOR_MORE(bMyArray[],1,5)
Alles anzeigen
PS: Das Programm wurde noch nicht getestet, sollte aber so funktionieren.
Gruß
Robotnik
Hallo,
kannst Du mir die Funktion bitte im Details ein wenig erklären?
Danke $CYCFLAG
Hallo,
wie erreiche ich dann, dass in dieses IF gesprungen wird,wenn nur ein einziger Eingang dieser 4 da ist!
$CYCFLAG
Ohne viel Hirnschmalz zu verwenden würde ich das so machen:
$CONFIG.dat
und dann im code:
SWITCH meineInputGruppe
CASE 1, 2, 4, 8
;Nur einer der vier Eingänge steht an
DEFAULT
;Mehrere oder kein Eingang steht an
ENDSWITCH
lg drudge
Hallo,
folgende Zeile verursacht bei mir:
-----> Satzende oder Kommentar erwartet
bOk = K<>L AND bOk AND NOT bArray[L] OR K==L AND bOk
wo liegt denn da der Fehler
$CYCFLAG
Und hier noch Robotniks Version ein klein wenig schlanker:
DEFFCT bool checkBit(bArray[]:OUT, startBit:IN, bitLength:IN)
DECL int startBit, bitLength
DECL bool bCompare, bArray[]
bCompare = FALSE
FOR startBit=startBit TO (startBit+bitLength-1) STEP 1
bCompare = bArray[startBit] EXOR bCompare
IF (NOT bCompare) AND bArray[startBit] THEN
EXIT
ENDIF
ENDFOR
RETURN bCompare
ENDFCT
Alles anzeigen
Ich hab auch noch eine relativ übersichtliche Einzeiler-Variante (für 4 Eingänge) :ylsuper:
...wenn man nämlich die unzulässigen 3 Bit-Kombinationen explizit aussperrt.
Sieht dann so aus :
IF ($IN[1] EXOR $IN[2] EXOR $IN[3] EXOR $IN[4]) and not($IN[1] and $IN[2]) and not($IN[3] and $IN[4]) THEN
...
ENDIF
gruß
rmac
Hab's heut auch mal probiert, in der DEF Zeile fehlt das BOOL....
DEFFCT BOOL EXOR_MORE(bArray[] :OUT,nStart :IN,nLen :IN)
und mit den klammern in der Zeile:
bOk = (K<>L) AND bOk AND NOT bArray[L] OR (K==L) AND bOk
funktionierts dann.
@CYCFLAG
Zur Funktion:
Das ForNext mit K benötigt mann um das erste Bit mit HighPegel zu finden.
Dieses wird dann in den Merker bOk geschrieben um dann mit den noch übrigen Elementen verglichen zu werden.
Damit kein Vergleich auf K==nEnd durchgeführt werden muß wird als nStart für L der Zählwert K geschrieben.
Die Zeile:
bOk = (K<>L) AND bOk AND NOT bArray[L] OR (K==L) AND bOk
ist eigentlich zweigeteilt.
bei K==L wird der vorhergehende bOk Zustand auf bOk geschrieben, sollte die Schleife schon jetzt am Ende Sein wird bOk (hier normalerweise True) Zurückgegeben.
Ist K<>L das ist im zweiten durchlauf werden alle weiteren Elemente auf NOT abgefragt und mit bOk UND-verknüpft.
Sollte kein Eingang High sein wird nach nLen Durchläufen False zurückgegeben.
Das ist schon alles.
Hallo,
kann ich dann wirklich:
WaiT for $IN[265] or EXOR_MORE($IN[],20,4)
im Programm verwenden?
$CYCFLAG
@CYCFLAG
Wait For geht schon, nur werden die Werte im EXOR_MORE nicht aktualisiert.
Besser ist
While NOT $IN[xy] OR EXEC_MORE(....)
SetWaitState(Integerwert)
Endwhile
SetWaitState(0) ; keine Meldung
SetWaitState(12) ist dann ein Unterprogramm das zum Beispiel der Visu mitteilt, das auf die Bedingung 12 gewartet wird.
Du musst ein Benutzerkonto haben um einen Kommentar hinterlassen zu können