Laden...

AND-Operator Beinhaltet Zahl

Erstellt von trib vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.467 Views
T
trib Themenstarter:in
708 Beiträge seit 2008
vor 6 Jahren
AND-Operator Beinhaltet Zahl

Hallo zusammen,

ich bin gerade etwas verwundert, dass eine Programmierung von mir fehlschlägt.
Es geht darum, dass ein Relais mir meldet, welche Eingänge gerade belegt sind.
Dies wird Hexadezimal gemacht. Z.B. mit 00 02
Das entspricht binär 0000 0000 0000 0010
Von rechts begonnen zu zählen und mit 0 gestartet, ist der Eingang 1 geschaltet.

Also habe ich folgende Funktion erstellt, die mir prüfen soll, ob ein spezieller Eingang nun An- oder Ausgeschaltet ist:

            var data = " ;0002";
            int number = 1;

            //Remove NewLine & Whitespace
            data = Regex.Replace(data, @"\s+", string.Empty);
           
             //port 0 is 1, 1 = 2, ect.
             number += 1;
             var hex = data.Replace(";", string.Empty);
             var i = Int32.Parse(hex, System.Globalization.NumberStyles.HexNumber);

             return (i & number) == number;

Liefert auch erfolgreich true zurück.

Nun übergebe ich Hex 0005 und das entspricht 0000 0000 0000 0101
Also 1 und 3 sind angeschaltet. Meine Funktion gibt aber, bei 1, 4 & 5 true zurück.

Habe ich einen Denkfehler? Befürchte ich verzettel mich mit dem number += 1 aber das geht nicht anders, da ich binär ja nicht den Anschluss "0" darstellen kann, sondern bei 1 zu zählen beginnen muss.

3.003 Beiträge seit 2006
vor 6 Jahren

Da fragt man sich schon, was du da eigentlich erreichen möchtest und wieso du jedes mal noch auf binär verweist...du machst da Handstände, wo nicht klar ist, wozu.


var data = " ;0002";

var dataAsNumber = Convert.ToInt32(data.Trim(' ',';'), 16);

for (int i = 0; i < 12; i++)
{
    if(((int)Math.Pow(2,i) | dataAsNumber) == dataAsNumber) Console.WriteLine($"Eingang {i+1} ist an.");
}

LaTino
EDIT: mal abgesehen von deiner umständlichen Weise, eine hex-Zahl auszulesen - beim zweiten Lesen scheint mir, als ob dir einfach nicht klar ist, wie der bitweise &-Operator funktioniert.

Binär 5: 101
Number in deinem Beispiel: 2 entspricht 010

&-Verknüpft: Ergebnis ist 000 (exp 2: 1 & 0 = 0, exp 1: 0 & 1 = 0, exp 0: 1 & 0 = 0, macht 000)
000 ist 0 (in jeder Zahlenbasis 😉 ) und das ist != number (s.o., ist 2).

Für eine Prüfung "ist bit i in Zahl n gesetzt?" lautet die bitweise Operation:
(n | 2^i) == n ("wenn ich an Stelle i das Bit auf 1 setze, bleibt der Wert dann gleich?")

Alternative Prüfung dazu (wie die funktioniert, ist Hausaufgabe :evil: ):
(n & (1 << i)) != 0

Aber das sind eigentlich wirklich Grundlagen.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

4.939 Beiträge seit 2008
vor 6 Jahren

Aber für Binärzahlen sollte man (statt Math.Pow) besser


1 << i // binäre Linksverschiebung

verwenden.

@LaTino: Und es muß selbstverständlich der AND-Operator & zum Ausmaskieren verwendet werden, also:


((1 << i) & dataAsNumber) != 0

Edit: Stimmt, die Abfrage war falsch (ich hatte den Code von LaTino kopiert)

3.003 Beiträge seit 2006
vor 6 Jahren

Siehe mein Edit. (Math.Pow ist an der Stelle leichter lesbar, daher. Normal nimmt man natürlich die bitverschiebung). Und nein, zum Ausmaskieren checkt man auf 0.

LaTino
EDIT: viel zu selten verlinkt: [Artikel] Bitoperationen in C#

EDIT (letzter Edit, ich schwör): @th69 jetzt weiss ich, was du machen möchtest...wenn du so vorgehen willst, checkst du, ob bit i als einziges bit gesetzt ist. ((1 << i) & dataAsNumber) == (1 << i)) würde sogar gehen dann. Wenn man wissen will, ob bit i gesetzt ist, checkt man auf != 0.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
trib Themenstarter:in
708 Beiträge seit 2008
vor 6 Jahren

Hallo zusammen,

vielen dank für Eure Antworten!

Habe einfach einen groben Denkfehler gehabt und die Stelle, mit der Wertigkeit der Zahl verwechselt. Bzw. schlicht und ergreifend nicht genau genug darüber nachgedacht.
Dann noch etwas Zeitdruck und das Chaos war komplett 😉

Es funktioniert nun wie es soll! Meine Methode prüft nun, ob ein bestimmter Eingang geschaltet ist oder nicht. Unabhängig, ob noch weitere Eingänge aktiv sind.
Bzw. kann man ein Event auf bestimmte Eingänge beschränken und nur auslösen, wenn ein Eingang einen bestimmten Wert hat:

private Dictionary<int, bool> _eventListenerDict;
private void reader_TagReadEvent(string tagValue)
        {
            if (_eventListenerDict.Any(entry => Helper.CheckRelaisState(tagValue, entry.Key) != entry.Value))
                return;
            if (TagReadEvent != null)
                if (_myControl.InvokeRequired)
                    _myControl.Invoke(new TagReadEventDelegate(TagReadEvent), tagValue);
                else
                    TagReadEvent(tagValue);
        }

Ihr habt natürlich Recht, ich hätte da selbst darauf kommen (können) müssen!