Boolesche Operatoren && und ||

252

Gemäß der R-Sprachdefinition besteht der Unterschied zwischen &und &&(entsprechend |und ||) darin, dass ersteres vektorisiert wird, während letzteres nicht.

Nach dem Hilfetext las ich den Unterschied verwandt mit dem Unterschied zwischen einem „Und“ und „AndAlso“ (entsprechend „Oder“ und „OrElse“) ... Bedeutung: Das nicht alle Auswertungen , wenn sie müssen nicht sein (dh A oder B oder C ist immer wahr, wenn A wahr ist, also hören Sie auf zu bewerten, ob A wahr ist)

Könnte hier jemand Licht ins Dunkel bringen? Gibt es auch ein AndAlso und OrElse in R?

SFun28
quelle
Siehe auch ähnliche Fragen unter stackoverflow.com/q/6933598/210673 und stackoverflow.com/q/7953833/210673 (jetzt als Duplikat geschlossen).
Aaron verließ Stack Overflow
3
Ich denke && und || sind in R schlecht implementiert. In anderen Sprachen führen sie die bedingten UND- und ODER-Operatoren aus, führen logische UND- oder ODER-Boolesche Operationen aus, werten jedoch nur den zweiten Operanden aus, wenn dies erforderlich ist. In R nichts Nützliches tun.
Skan

Antworten:

340

Die kürzeren sind vektorisiert, was bedeutet, dass sie einen Vektor wie folgt zurückgeben können:

((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE  TRUE FALSE FALSE

Die längere Form wertet von links nach rechts aus und untersucht nur das erste Element jedes Vektors

((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE

Wie auf der Hilfeseite angegeben, ist die längere Form "für die Programmierung des Kontrollflusses geeignet und wird in if-Klauseln normalerweise bevorzugt".

Sie möchten die langen Formen also nur verwenden, wenn Sie sicher sind, dass die Vektoren die Länge eins haben.

Sie sollten absolut sicher sein, dass Ihre Vektoren nur die Länge 1 haben, z. B. in Fällen, in denen es sich um Funktionen handelt, die nur Boolesche Werte der Länge 1 zurückgeben. Sie möchten die Kurzformen verwenden, wenn die Vektoren möglicherweise eine Länge von> 1 haben. Wenn Sie sich also nicht ganz sicher sind, sollten Sie entweder zuerst prüfen oder die Kurzform verwenden und sie dann verwenden allund anyauf Länge eins reduzieren, um sie in Kontrollflussanweisungen wie z if.

Die Funktionen allund anywerden häufig für das Ergebnis eines vektorisierten Vergleichs verwendet, um festzustellen, ob alle oder einige der Vergleiche wahr sind. Die Ergebnisse dieser Funktionen haben mit Sicherheit die Länge 1, sodass sie für die Verwendung in if-Klauseln geeignet sind, die Ergebnisse des vektorisierten Vergleichs jedoch nicht. (Obwohl diese Ergebnisse für die Verwendung in geeignet wären ifelse.

Ein letzter Unterschied: Die &&und ||bewerten nur so viele Begriffe, wie sie benötigen (was mit Kurzschluss gemeint zu sein scheint). Hier ist zum Beispiel ein Vergleich mit einem undefinierten Wert a. wenn es nicht Kurzschluss hat, wie &und |dies nicht tun, würde es einen Fehler geben.

a
# Error: object 'a' not found
TRUE || a
# [1] TRUE
FALSE && a
# [1] FALSE
TRUE | a
# Error: object 'a' not found
FALSE & a
# Error: object 'a' not found

Siehe schließlich Abschnitt 8.2.17 in The R Inferno mit dem Titel "and and andand".

Aaron verließ Stack Overflow
quelle
Ich vergleiche Logiken der Länge 1. In der Dokumentation ist nicht klar, warum sie für den Kontrollfluss bevorzugt werden. Liegt das daran, dass es den "Kurzschluss" aus @ Theos Antworten verwendet und somit eine bessere Leistung hat?
SFun28
Nee. Verwenden Sie einfach die Kurzform '&' - die Kurzschlussantworten sind falsch.
M. Tibbits
1
Nein, weil es garantiert nur eine einzige TRUE / FALSE-Antwort gibt. Die kürzeren Formen könnten dazu führen c(TRUE, FALSE), und die ifAussage wäre nicht klar. Wenn Sie sicher sind, dass alles die Länge 1 hat, dann reicht beides, und Sie haben Recht, dass der "Kurzschluss" der Grund ist, einen zu bevorzugen. Ein Wort der Warnung: Stellen Sie sicher, dass Sie zu 100% sicher sind, dass sie nur die Länge eins haben können. Sie können sonst wirklich doofe Fehler bekommen.
Aaron verließ Stack Overflow
9
@ SFun28: Ja, Kurzschluss ist der Grund, warum es für die Flusskontrolle bevorzugt wird. Neben einer besseren Leistung möchten Sie möglicherweise nicht alle Argumente bewerten. Das kanonische Beispiel zeigt ?is.R, ob Sie R oder S-Plus ausführen. if(exists("is.R") && is.function(is.R) && is.R()). Wenn is.Rnicht vorhanden, möchten Sie nicht auswerten, is.function(is.R)da dies einen Fehler auslöst. Wenn Sie is.Rkeine Funktion haben, möchten Sie sie auch nicht so aufrufen, als ob sie es wäre.
Richie Cotton
2
In der aktuellen Version des R-Infernos ist der relevante Abschnitt jetzt 8.2.17 "und und und und"
Silverfish
34

Die Antwort zum Thema "Kurzschluss" ist möglicherweise irreführend, hat aber eine gewisse Wahrheit (siehe unten). In der R / S-Sprache &&und ||nur das erste Element im ersten Argument auswerten. Alle anderen Elemente in einem Vektor oder einer Liste werden unabhängig vom ersten Wert ignoriert. Diese Operatoren sind so konzipiert, dass sie mit der if (cond) {} else{}Konstruktion arbeiten und die Programmsteuerung steuern, anstatt neue Vektoren zu erstellen . Die &und die |Operatoren sind so konzipiert, dass sie an Vektoren arbeiten, sodass sie sozusagen "parallel" entlang der Länge von angewendet werden das längste Argument. Beide Vektoren müssen ausgewertet werden, bevor die Vergleiche durchgeführt werden. Wenn die Vektoren nicht gleich lang sind, wird das kürzere Argument recycelt.

Wenn die Argumente zu &&oder ||ausgewertet werden, gibt es einen "Kurzschluss", da, wenn einer der Werte nacheinander von links nach rechts bestimmend ist, die Auswertungen aufhören und der Endwert zurückgegeben wird.

> if( print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(FALSE && print(1) ) {print(2)} else {print(3)} # `print(1)` not evaluated
[1] 3
> if(TRUE && print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 2
> if(TRUE && !print(1) ) {print(2)} else {print(3)}
[1] 1
[1] 3
> if(FALSE && !print(1) ) {print(2)} else {print(3)}
[1] 3

Der Vorteil des Kurzschlusses tritt nur auf, wenn die Bewertung der Argumente lange dauert. Dies tritt normalerweise auf, wenn die Argumente Funktionen sind, die entweder größere Objekte verarbeiten oder mathematische Operationen haben, die komplexer sind.

IRTFM
quelle
"Kurzschluss" ist für mich ein neuer Begriff, aber es scheint mir, dass die Antwort, die ihn beschreibt, mit dem übereinstimmt, was Sie über &&und sagen ||.
Aaron verließ Stack Overflow
@DWin - im Falle der Bedienung von Logiken über Länge 1 sind sie gleichwertig, oder? Ich versuche zu verstehen, warum sie im Kontrollfluss bevorzugt werden, wie in der Dokumentation angegeben. Hat R auch ein "Kurzschluss" -Konstrukt?
SFun28
Sie sind NICHT äquivalent für Vektoren mit einer Länge> 1
M. Tibbits
2
Es ist wahr, dass wenn die Argumente &&Funktionen sind und das erste falsch ist, das zweite nicht ausgewertet wird. Das ist nicht wahr für entweder &oder ifelsedie beiden Argumente bewerten.
IRTFM
Ist es nicht auch die Antwort von Theo auf Kurzschluss?
Aaron verließ Stack Overflow
25

&&und ||sind das, was man "Kurzschluss" nennt. Das bedeutet, dass sie den zweiten Operanden nicht auswerten, wenn der erste Operand ausreicht, um den Wert des Ausdrucks zu bestimmen.

Wenn beispielsweise der erste Operand to &&falsch ist, macht es keinen Sinn, den zweiten Operanden auszuwerten, da er den Wert des Ausdrucks nicht ändern kann ( false && trueund false && falsebeide falsch sind). Gleiches gilt, ||wenn der erste Operand wahr ist.

Weitere Informationen hierzu finden Sie hier: http://en.wikipedia.org/wiki/Short-circuit_evaluation Aus der Tabelle auf dieser Seite können Sie ersehen, dass &&dies AndAlsoVB.NET entspricht, auf das Sie sich vermutlich beziehen.

Das Ö
quelle
3
Dies sollte der Beweis sein, dass es sich um einen Kurzschluss handelt : f <- function() { print('hello'); TRUE }; FALSE && f(). Wechseln Sie zu &und beachten Sie, dass die Funktion ausgewertet wird. QED.
Theo
2
Theo, ja, das hast du richtig &&und ||kurzgeschlossen. Aber das ist wirklich ein ziemlich kleiner Punkt bei Vergleichen zwischen der Kurzform und der Langform; Es ist viel wichtiger zu verstehen, was jeder tut, wenn die Eingaben Vektoren sind.
Aaron verließ Stack Overflow
2
@MTibbits Tatsächlich ist dies keine vollständige Antwort, aber die Aussage zum Kurzschluss ist korrekt . Versuchen Sie F & {message("Boo!");T}und F && {message("Boo!");T}.
mbq