根据R语言的定义,&
和&&
(相应的|
和||
)之间的区别在于前者是矢量化的,而后者不是。
根据帮助文本,我读到的区别类似于"And"one_answers"AndAlso"之间的区别(对应的是"Or"和《OrElse》)。。。含义:如果不是所有的评估都必须是(即,如果A是真的,A、B或C总是真的,所以如果A是真实的,就停止评估)
有人能照亮这里吗?此外,R中是否存在AndAlso和OrElse?
较短的被矢量化,这意味着它们可以返回一个矢量,如下所示:
((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE TRUE FALSE FALSE
较长的形式不是,因此(从4.3.0开始)必须提供长度为1的输入。(万岁!需要的检查更少,见下文。)
直到R 4.3.0,给出&;长度>1没有抛出错误,而是从左到右评估,只检查每个向量的第一个元素,因此上面给出:
((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE
正如帮助页面所说;适用于编程控制流,并且在if子句中通常是首选"
因此,只有当你确定向量的长度为1时,你才想使用长形式,从4.3.0开始,R强制执行这一点。
如果你使用的是以前的版本,你应该绝对确定你的向量只有长度1,比如在它们是只返回长度1布尔值的函数的情况下。如果向量的长度可能>1.因此,如果您不能完全确定,您应该先检查,或者使用缩写形式,然后使用all
和any
将其缩短为长度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
最后,参见R Inferno中的第8.2.17节,标题为";和and and";。
关于";"短路";具有潜在的误导性,但有一定的真实性(见下文)。在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
只有当参数需要很长时间才能评估时,短路的优势才会显现出来。当参数是处理较大对象或具有更复杂数学运算的函数时,通常会发生这种情况。
更新:最新版本的news(“R”)
表示,向&&
或||
提供长度大于1的矢量是不推荐的,并发出警告,RCore的目的是使其成为R的后续版本中的错误。
&&
和||
是所谓的"短路"。这意味着,如果第一个操作数足以确定表达式的值,则它们不会计算第二个操作数。
例如,如果&&
的第一个操作数为false,那么计算第二个操作数就没有意义,因为它不能更改表达式的值(false && true
和false && false
都为false)。当第一个操作数为true时,||
也是如此。
您可以在此处阅读更多信息:http://en.wikipedia.org/wiki/Short-circuit_evaluation从该页的表中,您可以看到&&
等效于VB.NET中的AndAlso
,我想您指的是它。
操作员&&
/||
和&
/|
之间存在三个相关差异,官方文档对此进行了解释。总结如下:
1.&
和|
被矢量化
这意味着,如果要对向量执行元素逻辑运算,则应使用&
和|
:
a = c(TRUE, TRUE, FALSE, FALSE)
b = c(TRUE, FALSE, TRUE, FALSE)
a | b
# [1] TRUE TRUE TRUE FALSE
a || b
# [1] TRUE
对于&&
/||
,丢弃第一个之后的所有元素。当在长度超过1:的矢量上使用&&
/||
时,R的最新版本会生成有用的警告
In a || b : 'length(x) = 4 > 1' in coercion to 'logical(1)'
2.&&
与||
短路
短路意味着只有当表达式的右侧尚未确定结果时,才会对其进行求值。几乎每种编程语言都对条件运算这样做,因为在编写if
条件时,它会带来方便的习惯用法,例如:
if (length(x) > 0L && x[1L] == 42) …
此代码依赖于短路:如果没有短路,x
为空,则代码将失败,因为右侧试图访问不存在的元素。如果没有短路,我们将不得不使用嵌套的if
块,从而产生更详细的代码:
if (length(x) > 0L) {
if (x[1L] == 42) …
}
一般来说,在条件表达式(if
、while
)中,即使不需要短路,也应该始终使用&&
和||
:这更惯用,并导致更统一的代码。
3.&
和|
可以执行逐位运算
在许多(大多数)编程语言中,&
和|
实际上执行逐位算术,而不是布尔算术。也就是说,对于两个整数a
和b
,a & b
计算位和,而a | b
计算<em]位或>。对于布尔值,按位运算和逻辑运算之间没有区别;但对于任意整数,结果不同。例如,大多数编程语言中的1 | 2 == 3
。
然而,对于R:R,这不是真的:R将&
和|
的数字参数强制为逻辑值并执行布尔运算。
…除非两个参数都属于raw
:类型
c(1, 3) | c(2, 4)
# [1] TRUE TRUE
as.raw(c(1, 3)) | as.raw(c(2, 4))
# [1] 03 07
值得注意的是,运算!
(逻辑否定)和xor
在使用raw
自变量调用时也执行逐位算术。
从变更日志中,由于R 4.2.0调用长度大于1的&&
或||
是一个警告:
呼叫&;或者长度大于1的参数||现在会发出警告(这将成为一个错误)。
并且由于4.3.0是一个错误:
呼叫&;或||LHS或长度大于1的RHS(如果评估)现在总是一个错误,报告形式为
"长度=4"强制为"逻辑(1)"
环境变量R_CHECK_LENGTH_1_LOGIC2不再有任何影响。