Operatori booleani && e ||


252

Secondo la definizione del linguaggio R , la differenza tra &e &&(corrispondentemente |e ||) è che la prima è vettorializzata mentre la seconda no.

Secondo il testo di aiuto , ho letto la differenza simile alla differenza tra un "And" e "AndAlso" (corrispondentemente "Or" e "OrElse") ... Significato: che non tutte le valutazioni se non devono essere (ovvero A o B o C è sempre vero se A è vero, quindi smetti di valutare se A è vero)

Qualcuno potrebbe fare luce qui? Inoltre, c'è un AndAlso e OrElse in R?



3
Penso che && e || sono mal implementati in R. In altre lingue sono gli operatori AND e OR condizionali, eseguono operazioni booleane logiche AND o OR, ma valutano il suo secondo operando solo se necessario. In R non fare nulla di utile.
skan

Risposte:


340

Quelli più corti sono vettorizzati, nel senso che possono restituire un vettore, in questo modo:

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

La forma più lunga valuta da sinistra a destra esaminando solo il primo elemento di ciascun vettore, quindi dà quanto sopra

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

Come dice la pagina di aiuto, questo rende la forma più lunga "appropriata per la programmazione del flusso di controllo e [è] generalmente preferita nelle clausole if".

Quindi vuoi usare le forme lunghe solo quando sei sicuro che i vettori siano lunghi uno.

Dovresti essere assolutamente certo che i tuoi vettori siano solo di lunghezza 1, ad esempio nei casi in cui sono funzioni che restituiscono solo booleani di lunghezza 1. Si desidera utilizzare le forme brevi se i vettori hanno una lunghezza possibilmente> 1. Quindi, se non sei assolutamente sicuro, dovresti prima controllare, o usare la forma abbreviata e poi usare alle anyper ridurla a lunghezza per usarla nelle istruzioni del flusso di controllo, come if.

Le funzioni alle anyvengono spesso utilizzate sul risultato di un confronto vettoriale per vedere se tutti o alcuni dei confronti sono veri, rispettivamente. I risultati di queste funzioni saranno sicuramente di lunghezza 1, quindi sono appropriati per l'uso nelle clausole if, mentre i risultati del confronto vettoriale non lo sono. (Anche se questi risultati sarebbero appropriati per l'uso in ifelse.

Un'ultima differenza: l' unico &&e ||valutare tutti i termini di cui hanno bisogno (che sembra essere ciò che si intende per cortocircuito). Ad esempio, ecco un confronto usando un valore indefinito a; se non cortocircuita, come &e |no, darebbe un errore.

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

Infine, vedi la sezione 8.2.17 in The R Inferno , intitolata "and and andand".


Sto confrontando logici di lunghezza 1. La documentazione non è chiara sul perché sia ​​preferita per il flusso di controllo. È perché utilizza il "cortocircuito" dalle risposte di @ Theo e quindi ha prestazioni migliori?
SFun28,

no. Usa semplicemente la forma abbreviata "&": le risposte al corto circuito non sono corrette.
M. Tibbits,

1
No, perché garantisce di avere una sola risposta VERA / FALSA. Le forme più brevi potrebbero risultare c(TRUE, FALSE)e l' ifaffermazione non sarebbe chiara. Se sei certo che tutto ha lunghezza 1, allora sì, lo farebbe anche uno dei due, e hai ragione che il "cortocircuito" è la ragione per preferirne uno. Un avvertimento però, assicurati di essere sicuro al 100% che possono essere solo di lunghezza uno. Altrimenti puoi ottenere bug davvero sciocchi.
Aaron ha lasciato Stack Overflow il

9
@ SFun28: Sì, il cortocircuito è il motivo preferito per il controllo del flusso. Oltre a prestazioni migliori, potresti non voler valutare tutti gli argomenti. L'esempio canonico viene fornito ?is.Rper verificare se si sta eseguendo R o S-Plus. if(exists("is.R") && is.function(is.R) && is.R()). Se is.Rnon esiste, non si desidera valutare is.function(is.R)poiché genererà un errore. Allo stesso modo, se is.Rnon è una funzione, non si desidera chiamarla come se lo fosse.
Richie Cotton,

2
Nell'attuale versione di R inferno, la sezione pertinente è ora 8.2.17 "e andand"
Silverfish

34

La risposta sul "cortocircuito" è potenzialmente fuorviante, ma ha un po 'di verità (vedi sotto). Nel linguaggio R / S, &&e ||valuta solo il primo elemento nel primo argomento. Tutti gli altri elementi in un vettore o elenco vengono ignorati indipendentemente dal valore dei primi. Gli operatori sono progettati per lavorare con la if (cond) {} else{}costruzione e il controllo del programma diretto piuttosto che costruire nuovi vettori .. L' &ei |operatori sono progettati per lavorare su vettori, in modo che saranno applicate "in parallelo", per così dire, lungo la lunghezza del l'argomento più lungo. Entrambi i vettori devono essere valutati prima di effettuare i confronti. Se i vettori non hanno la stessa lunghezza, viene eseguito il riciclaggio dell'argomento più breve.

Quando gli argomenti a &&o ||vengono valutati, c'è un "cortocircuito" in quanto se uno dei valori in successione da sinistra a destra è determinante, allora le valutazioni cessano e viene restituito il valore finale.

> 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

Il vantaggio del corto circuito apparirà solo quando la valutazione degli argomenti richiede molto tempo. Ciò si verifica in genere quando gli argomenti sono funzioni che elaborano oggetti più grandi o hanno operazioni matematiche più complesse.


"corto circuito" è un nuovo termine per me, ma mi sembra che la risposta che lo descrive sia in accordo con ciò che dici &&e ||.
Aaron ha lasciato Stack Overflow il

@DWin - nel caso di operare su logici di lunghezza 1, sono equivalenti, giusto? Sto cercando di capire perché sono preferiti nel flusso di controllo come afferma la documentazione. Inoltre, R ha un costrutto "cortocircuito"?
SFun28,

NON sono equivalenti per vettori di lunghezza> 1
M. Tibbits,

2
È vero che se gli argomenti &&sono funzioni e il primo è falso, il secondo non verrà valutato. Questo non è vero per nessuno dei due &o ifelseche valuterà entrambi gli argomenti.
IRTFM,

Non è anche quello che dice la risposta di Theo sul corto circuito?
Aaron ha lasciato Stack Overflow il

25

&&e ||sono ciò che viene chiamato "corto circuito". Ciò significa che non valuteranno il secondo operando se il primo operando è sufficiente per determinare il valore dell'espressione.

Ad esempio, se il primo operando su &&è falso, non ha senso valutare il secondo operando, poiché non può modificare il valore dell'espressione ( false && truee false && falsesono entrambi falsi). Lo stesso vale per ||quando il primo operando è vero.

Puoi leggere di più su questo qui: http://it.wikipedia.org/wiki/Short-circuit_evaluation Dalla tabella in quella pagina puoi vedere che &&è equivalente a AndAlsoin VB.NET, che presumo tu ti riferisca.


3
Questo dovrebbe essere sufficiente la prova che si tratta di corto circuito: f <- function() { print('hello'); TRUE }; FALSE && f(). Passare a &e notare che la funzione viene valutata. QED.
Theo,

2
Theo, sì, hai ragione &&e ||corto circuito. Ma questo è davvero un punto piuttosto secondario nei confronti tra la forma breve e la forma lunga; è molto più importante capire cosa ciascuno fa quando gli input sono vettori.
Aaron ha lasciato Stack Overflow il

2
@MTibbits In realtà questa non è una risposta completa, ma l'affermazione sul corto circuito è corretta . Prova F & {message("Boo!");T}e F && {message("Boo!");T}.
mbq,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.