Булевы операторы && и ||

204

Согласно определению R-языка различие между & и && (соответственно | и ||) состоит в том, что первое векторизовано, а второе - нет.

Согласно тексту справки, я читаю разницу, близкую к разнице между "И" и "AndAlso" (соответственно "Or" и "OrElse")... Значение: Это не все оценки, если они не должны быть (т.е. A или B или C всегда истинны, если A истинно, поэтому прекратите оценку, если A истинно)

Может ли кто-то пролить свет здесь? Кроме того, есть AndAlso и OrElse в R?

  • 0
    Также смотрите похожие вопросы по адресу stackoverflow.com/q/6933598/210673 и stackoverflow.com/q/7953833/210673 (теперь закрыт как дубликат).
  • 2
    Я думаю && и || плохо реализованы в R. На других языках они являются условными операторами И и ИЛИ, они выполняют логические логические операции И или ИЛИ, но оценивают только свой второй операнд, если это необходимо. В R не делай ничего полезного.
Теги:
boolean-operations
logical-operators
or-operator
and-operator

3 ответа

289
Лучший ответ

Более короткие векторы вектора, то есть они могут возвращать вектор, например:

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

Более длинная форма оценивает слева направо, исследуя только первый элемент каждого вектора, поэтому приведенное выше дает

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

Как говорится в справочной странице, это делает более длинную форму "подходящей для программирования управления потоком и [обычно] предпочтительнее в разделах". "

Итак, вы хотите использовать длинные формы только тогда, когда вы уверены, что векторы имеют длину один.

Вы должны быть абсолютно уверены, что ваши векторы имеют длину 1, например, в тех случаях, когда они являются функциями, которые возвращают только длину 1 булево. Вы хотите использовать короткие формы, если длина векторов возможно > 1. Поэтому, если вы не уверены, вам следует либо сначала проверить, либо использовать короткую форму, а затем использовать all и any, чтобы уменьшить ее до длины, определенной для операторов потока управления, например if.

Функции all и any часто используются для результата векторизованного сравнения, чтобы увидеть, соответствуют ли все или какие-либо сравнения соответственно. Результаты этих функций обязательно будут длиной 1, поэтому они подходят для использования в предложениях if, в то время как результаты векторизованного сравнения не являются. (Хотя эти результаты были бы подходящими для использования в ifelse.

Одно окончательное различие: && и || оценивают только столько терминов, сколько им нужно (что, по-видимому, означает короткое замыкание). Например, здесь сравнение с использованием значения undefined a; если он не закорочился, а & и | - нет, это даст ошибку.

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

Наконец, см. раздел 8.2.17 в The R Inferno, озаглавленный "and and and and".

  • 0
    Я сравниваю логику длины 1. В документации не ясно, почему она предпочтительна для потока управления. Это потому, что он использует «короткое замыкание» из ответов @ Theo и, следовательно, имеет лучшую производительность?
  • 0
    Нету. Просто используйте краткую форму '&' - ответы о коротком замыкании неверны.
Показать ещё 3 комментария
22

Ответ о "short-circuiting" потенциально вводит в заблуждение, но имеет некоторую правду (см. ниже). На языке R/S && и || оценивают только первый элемент в первом аргументе. Все остальные элементы в векторе или списке игнорируются независимо от первого значения. Эти операторы предназначены для работы с конструкцией if (cond) {} else{} и для прямого управления программой, а не для создания новых векторов. Операторы & и | предназначены для работы с векторами, поэтому они будут применяться "параллельно", так сказать, по длине самого длинного аргумента. Если векторы не имеют одинаковой длины, выполняется повторная обработка более короткого аргумента.

Когда оцениваются аргументы && или ||, существует "короткое замыкание" в том случае, если любое из последовательностей слева направо является определяющим, тогда оценки прекращаются и возвращается окончательное значение.

> 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
  • 0
    «короткое замыкание» - это новый термин для меня, но мне кажется, что ответ, описывающий его, согласуется с тем, что вы говорите о && и || ,
  • 0
    @DWin - в случае работы с логикой длины 1 они эквивалентны, верно? Я пытаюсь понять, почему они предпочтительны в потоке управления, как говорится в документации. Кроме того, R имеет конструкцию "короткого замыкания"?
Показать ещё 6 комментариев
17

&& и || - это то, что называется "короткое замыкание". Это означает, что они не будут оценивать второй операнд, если первого операнда достаточно, чтобы определить значение выражения.

Например, если первый операнд в && является ложным, тогда нет смысла оценивать второй операнд, так как он не может изменить значение выражения (false && true и false && false оба являются ложными). То же самое относится к ||, когда первый операнд истинен.

Подробнее об этом вы можете узнать здесь: http://en.wikipedia.org/wiki/Short-circuit_evaluation Из таблицы на этой странице вы можете видеть, что && эквивалентен AndAlso в VB. NET, который, как я полагаю, вы имеете в виду.

  • 3
    Это должно быть достаточным доказательством того, что это короткое замыкание: f <- function() { print('hello'); TRUE }; FALSE && f() . Измените на & и обратите внимание, что функция оценивается. QED.
  • 1
    Тео, да, ты прав, что && и || короткое замыкание. Но это действительно довольно незначительный момент в сравнении между короткой формой и длинной формой; гораздо важнее понять, что каждый из них делает, когда входные данные являются векторами.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню