布尔运算符&&和||

SFu*_*n28 232 r logical-operators or-operator boolean-operations and-operator

根据R输入语言定义,之间的差&&&(相应地|||)是,虽然后者不是前者被矢量.

根据帮助文本,我读到的差异类似于"And"和"AndAlso"(相应地"Or"和"OrElse")之间的区别......意思是:如果不是所有的评估都不是(即如果A为真,则A或B或C始终为真,因此请停止评估A是否为真)

有人会在这里光明吗?另外,R中是否有AndAlso和OrElse?

Aar*_*ica 321

较短的是矢量化的,这意味着它们可以返回一个向量,如下所示:

((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE  TRUE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)

较长的形式从左到右评估只检查每个向量的第一个元素,所以上面给出

((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)

正如帮助页面所说,这使得更长的形式"适合于编程控制流,并且在if子句中通常是首选的."

因此,只有在确定向量为长度为1时才要使用长格式.

绝对应该确定你的向量只有长度为1,例如在它们只返回长度为1的布尔值的情况下.如果向量的长度可能> 1,则要使用短格式.因此,如果您不完全确定,则应首先检查,或使用简短形式,然后使用allany将其缩短为长度1以用于控制流语句,例如if.

函数all和函数any通常用于矢量化比较的结果,以分别查看所有或任何比较是否为真.这些函数的结果肯定是长度为1,因此它们适用于if子句,而矢量化比较的结果则不适用.(虽然这些结果适合用于ifelse.

最后一个区别是:&&并且||只评估他们需要的多个术语(这似乎是短路的意思).例如,这是使用未定义值的比较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
Run Code Online (Sandbox Code Playgroud)

最后,参见The R Inferno中的 8.2.17节,标题为"and andandand".

  • @ SFun28:是的,短路是它首选流量控制的原因.除了更好的性能,您可能不想评估所有参数.规范示例在`?is.R`中给出,用于检查您是在运行R还是S-Plus.`if(exists("is.R")&& is.function(is.R)&& is.R())`.如果`is.R`不存在,那么你不想评估`is.function(is.R)`,因为它会抛出一个错误.同样,如果`is.R`不是函数,你不想像它那样调用它. (8认同)
  • 不,因为它保证只有一个 TRUE/FALSE 答案。较短的形式可能会导致“c(TRUE, FALSE)”,并且“if”语句不清楚。如果你确定所有东西的长度都是 1,那么是的,任何一种都可以,而且你认为“短路”是选择其中一种的原因是正确的。不过,请注意,请确保您 100% 确定它们的长度只能为一。否则你可能会遇到非常愚蠢的错误。 (2认同)
  • 在R inferno的当前版本中,相关部分现在是8.2.17"and andand" (2认同)

42-*_*42- 32

关于"短路"的答案可能具有误导性,但有一些道理(见下文).在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
Run Code Online (Sandbox Code Playgroud)

  • 确实如果`&&`的参数是函数而第一个是false,那么第二个参数将不会被评估.对于将评估两个参数的`&`或`ifelse`都不是这样. (2认同)

The*_*heo 23

&&||在所谓的"短路".这意味着如果第一个操作数足以确定表达式的值,它们将不会计算第二个操作数.

例如,如果第一个操作数&&为false,则评估第二个操作数没有意义,因为它不能更改表达式的值(false && true并且false && false都是false).第||一个操作数为真时也是如此.

你可以阅读更多关于此这里:http://en.wikipedia.org/wiki/Short-circuit_evaluation从该网页上表中可以看到,&&就相当于AndAlso在VB.NET,我假设你指的是.

  • 这应足以证明它是短路的:`f < - function(){print('hello'); TRUE}; FALSE && f()`.更改为"&"并注意该函数已被评估.QED. (3认同)
  • Theo,是的,您正确地认为`&amp;&amp;`和`||`短路。但这在短格式和长格式之间的比较中确实是一个次要的问题;了解输入为向量时每个函数的作用更为重要。 (2认同)
  • @MTibbits实际上这不是一个完整的答案,但关于短路**的说法是正确的**.试试`F&{message("Boo!"); T}`和`F && {message("Boo!"); T}`. (2认同)

Kon*_*lph 6

运算符/和/之间存在三个相关差异,官方文档中对此进行了解释。这里\xe2\x80\x99s是一个总结:&&||&|

\n

1.&|矢量化

\n

这意味着如果您想对向量执行按元素逻辑运算,您应该使用&and |

\n
a = c(TRUE, TRUE, FALSE, FALSE)\nb = c(TRUE, FALSE, TRUE, FALSE)\n\na | b\n# [1]  TRUE  TRUE  TRUE FALSE\n\na || b\n# Error in a || b : \'length = 4\' in coercion to \'logical(1)\'\n
Run Code Online (Sandbox Code Playgroud)\n

在以前版本的 R 中,a || b( 和a && b) 不会导致错误。相反,这些操作会默默地截断输出(仅返回第一个元素;在导致此错误之前,它会在 R 4.2 中短暂引发警告)。

\n

2.&&||短路

\n

短路意味着仅当左侧尚未确定结果时才计算表达式的右侧。几乎每种编程语言都对条件操作执行此操作,因为它在编写if条件时会产生方便的习惯用法,例如:

\n
if (length(x) > 0L && x[1L] == 42) \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

此代码依赖于短路:如果没有它,如果为x空,则代码将失败,因为右侧尝试访问不存在的元素。如果没有短路,我们将不得不使用嵌套if块,从而导致更冗长的代码:

\n
if (length(x) > 0L) {\n    if (x[1L] == 42) \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n

作为一般规则,在条件表达式 ( if, while) 中,您应该始终使用&&and ||,即使不需要短路:它更惯用,并导致更统一的代码。

\n

3.&可以|进行按位运算

\n

在许多(大多数?)编程语言中,&实际上|执行按位算术而不是布尔算术。即,对于两个整数aba & b计算按位与,并a | b计算按位或。对于布尔值,按位运算和逻辑运算之间没有区别;但对于任意整数,结果不同。例如,1 | 2 == 3在大多数编程语言中。

\n

然而,对于 R 来说情况并非&如此:R 将和 的数字参数强制转换|为逻辑值并执行布尔算术。

\n

\xe2\x80\xa6 除非两个参数都是类型raw

\n
c(1, 3) | c(2, 4)\n# [1] TRUE TRUE\n\nas.raw(c(1, 3)) | as.raw(c(2, 4))\n# [1] 03 07\n
Run Code Online (Sandbox Code Playgroud)\n

值得注意的是,当使用参数调用时,操作!(逻辑非)也会执行按位算术。xorraw

\n