2015-03-26 11 views
8

MonoDevelop dies legt nahe, Drehen:MonoDevelop schlägt drehen, wenn Aussagen in bitweise Operationen

if (someBoolVar) 
    anotherBoolVar = true; 

in diese:

anotherBoolVar |= someBoolVar; 

Es tut es auch, wenn ich gesetzt anotherBoolVar zu false statt:

if (someBoolVar) 
    anotherBoolVar = false; 

wird:

anotherBoolVar &= !someBoolVar; 

Kann jemand erklären, wie diese Aussagen gleich sind?

+1

Ich bin mir ziemlich sicher, dass der letzte sein sollte '& = ~ someBoolVar;' Sie vermissen die '~' –

+14

Ihre IDE möchte, dass Sie weniger lesbaren Code schreiben. Ignoriere seinen Rat. –

+1

'|' (oder), '&' (und) und '~' (nicht) und sind bitweise Operatoren, in diesem Fall kann es zu diesen einzeiligen Zuweisungen gekürzt werden. Lassen Sie die IDE Ihren Code nicht "korrigieren", wenn er Sie verwirrt :) –

Antwort

12

Nun, funktional sie sind gleichwertig.

Im ersten Fall Sie anotherBoolVar zu true wenn someBoolVar ist true, unabhängig davon, welchen Wert anotherBoolVar zur Zeit einstellen möchten hat, hat der Ersatz dieser Ausdruck.

Es ist die Abkürzung für diese:

anotherBoolVar = anotherBoolVar | someBoolVar; 

Der zweite Ersatz tut auch der gleiche wie der Code es ersetzt, und ist für diese kurze:

anotherBoolVar = anotherBoolVar & (!someBoolVar); 

Die Lösung wird in die verborgene " bitweise "Natur der booleschen Variablen in diesem Fall. Um und mit einem invertierten Wert (~ invertiert die someBoolVar) wird effektiv sagen "alle Bits beibehalten, die in !someBoolVar gesetzt sind und den Rest löschen", was bedeutet, dass, wenn someBoolVar wahr ist, wird es falsch invertiert, und Sie ' ll effektiv löschen anotherBoolVar.


Jetzt sollten Sie tun, um diese?

Meiner Meinung nach, nein. Der Code ist besser lesbar. Bleiben Sie und suchen Sie möglicherweise nach einer Möglichkeit, MonoDevelop zu bitten, diese Dinge in Zukunft nicht zu empfehlen.

+1

Schwerpunkt auf SOLLTE du das tun. Nein. Genau wie andere Roboter hat auch die IDE keine emotionale Verbindung zum Code und diese IDE kümmert sich offensichtlich nicht um ihre menschlichen Benutzer. :) – kingdango

+2

Es scheint, MonoDevelop arbeitet an der Annahme eines _dumb_ Compilers. Jeder _decent_ Compiler wird die "if" -Anweisung in eine "OR" oder "AND" -Anweisung optimieren (sogar bei "-O0"), um einen "Vergleich und Sprung" zu vermeiden. Auf der anderen Seite, [MonoDevelop ist Open Source] (https://github.com/mono/monodevelop), wenn Sie also einen GitHub Account haben, können Sie eine Bug (Issue) Anfrage einreichen (@ LasseV.Karlsen sollten Sie das erwähnen in Ihrem letzten Absatz) –

+2

@kingdango [obligatorisch xkcd] (https://www.xkcd.com/810)? –

2

Für z.B.

if (someBoolVar) 
    anotherBoolVar = true; 

Also, wenn someBoolVar ist true es kommt auf

anotherBoolVar = (whatever boolean value of anotherBoolVar) | true; 

, die auf true immer bewerten wird.

0
if (someBoolVar) 
    anotherBoolVar = true; 

entspricht

if (someBoolVar) 
    anotherBoolVar = true; 
else 
    anotherBoolVar = anotherBoolVar //Nop 

was

if (someBoolVar) 
    anotherBoolVar = anotherBoolVar | someBoolVar; 
else 
    anotherBoolVar = anotherBoolVar | someBoolVar //Nop 

weil x entspricht | Wahr == Wahr und x | falsch == x

und ich nehme an, Sie wissen, dass

anotherBoolVar |= someBoolVar 

zu

anotherBoolVar = anotherBoolVar | someBoolVar 
2

Zum ersten Änderung entspricht, die if Konstruktion bedeutet:

someBoolVar is true ==> anotherBoolVar becomes true 
someBoolVar is false ==> anotherBoolVar is unchanged 

Die |= Konstruktion bedeutet:

Ähnliche Anmerkungen gelten für die zweite Änderung, obwohl als @Lasse V. Karlsen erwähnt, scheint die &= Konstruktion eine Tilde zu fehlen.

+0

_ "... scheint eine Tilde zu fehlen" _ FYI, es heißt (zumindest von mir) ein "_bitwise NOT_ operator". Andere mögen es etwas anderes nennen. –

+0

Ach komm schon. Es gibt einen Unterschied zwischen einer Tilde und einem bitweisen NOT-Operator, genau wie es einen Unterschied zwischen einem Summensymbol und dem griechischen Buchstaben Sigma gibt. Sie können mich nicht falsch nennen, wenn Sie den typografischen Namen anstelle des semantischen Namens verwenden. –

+0

Wenn Sie meinen Kommentar noch einmal gelesen haben, habe ich Sie nicht falsch genannt. Ich habe nur gesagt, dass "bitweiser NOT-Operator" sprachunabhängig ist, aber "Tilde" ist spezifisch für C-basierte Sprachen. –

3

IDE-Code-Empfehlungen sind oft ein Doppelkantenschwert. Ja, die Aussagen sind tERSE, ABER sie sind möglicherweise auch verwirrend (daher Ihr Nachdenken).

if (someBoolVar) 
    anotherBoolVar = someBoolVar; 

ist die gleiche wie

anotherBoolVar |= someBoolVar; 

weil |= Kurz circuts wenn someBoolVar falsch ist. Wenn someBoolVar true ist, wird es nicht kurzgeschlossen und weist daher den someBoolVar-Wert (true) einer anderenBoolVar zu.

Obwohl die knappere Aussage leicht optimiert werden kann, empfehle ich Ihnen, bei Ihrer if-Anweisung zu bleiben, weil sie aussagekräftiger und lesbarer ist.

Für diese Art von if-Anweisungen Ich versuche, sie Linie auf einer zu halten:

if (someBoolVar) anotherBoolVar = someBoolVar;

+1

+1 Aber Sie sollten eine boolesche Logiktabelle hinzufügen, ähnlich wie bei [Ross Pressner] (http://stackoverflow.com/a/29279979/1350209). Es erklärt, warum sie gleichwertig sind. Einfach zu sagen, dass sie gleichwertig sind, ist nicht viel hilfreich für jemanden (jetzt oder in der Zukunft), der Boolesche Logik nicht versteht (ähnlich einer Mathematikklasse, die nur sagt: sin (x)^2 + cos (x)^2 = 1 ', ohne _why_ zu erklären. –

1

Vielleicht hilft die Wikipedia article auf Boolesche Algebra.

Der Vorschlag ist eine Mikro-Optimierung, die Makro in Eile drehen kann. Der Just-in-Time-Compiler erzeugt eine bedingte Verzweigung für die if() -Anweisung, zumindest die von Microsoft erstellten sind nicht schlau genug, um den Code selbst zu optimieren. Sie müssen einen Blick darauf werfen, ob der Monojitter einen besseren Job machen kann, wenn Sie sich den generierten Maschinencode ansehen. Typische Codegenerierung wie folgt aussieht:

  if (someBoolVar) anotherBoolVar = true; 
00007FFD989F3BB1 movzx  eax,cl 
00007FFD989F3BB4 test  eax,eax 
00007FFD989F3BB6 je   00007FFD989F3BBA // <=== here 
00007FFD989F3BB8 mov   dl,1 
00007FFD989F3BBA etc... 

Bedingte Verzweigungen wie der JE-Befehl in dem obigen Maschinencode sind mühsam zu einem modernen Prozessor, es stark auf der Pipeline angewiesen, um Code auszuführen zu machen schnell. Befehlsdecodierung und Micro-Ops-Generierung wird im Voraus durchgeführt. Auch eine große Sache für den Prefetcher, es versucht zu erraten, welche Speicherorte in den Caches verfügbar sein müssen, damit die Ausführungs-Engine nicht zum Stillstand kommt, wenn der Speicherinhalt benötigt wird.Der Speicher ist sehr, sehr langsam im Vergleich zur rohen Ausführungsgeschwindigkeit der Ausführungs-Engine des Prozessors.

Ein Prozessor hat einen Verzweigung Prädiktor, es verfolgt, ob die Verzweigung genommen wurde, wenn der Code zuvor ausgeführt wurde. Und nimmt an, dass sich der Zweig wieder genauso verhält. Wenn es falsch rät, muss die Pipeline geleert werden. Eine Menge Arbeit wird weggeworfen und der Prozessor wird stehen bleiben, während er wieder hochfährt. Zusätzliche Long-Ställe können auftreten, wenn der Prefetcher falsch geraten hat, hohe Chancen, dass es getan hat. Es gibt eine good SO post, die die Folgen einer falschen Vorhersage erklärt.

Mit der Booleschen Algebra wird die Verzweigung vermieden, es wird eine OR- oder AND-Anweisung erzeugt, sie nehmen einen einzigen Zyklus und können die Pipeline niemals leeren. Sicherlich eine Mikro-Optimierung, macht es nur Makro, wenn dieser Code innerhalb der ~ 10% Ihres Codes befindet, die die Geschwindigkeit Ihres Programms bestimmt. Die IDE wird nicht schlau genug sein, Ihnen zu sagen, ob das der Fall ist, nur ein Profiler kann Ihnen das zeigen.

Fwiw, es gibt mehr Mikro-Optimierungen wie diese, Programmierer neigen dazu, die & & und || zu verwenden Betreiber unangemessen. Das Kurzschließverhalten dieser Operatoren erfordert immer eine Verzweigung im Maschinencode. Dieses Verhalten wird nicht immer benötigt, normalerweise ist es nicht und die & und | Operator kann viel schneller Code generieren. Wenn der Operand der linken Seite schlecht vorhergesagt wird, kann der Code 500% langsamer werden.