博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
R语言中的 & 和 &&
阅读量:7227 次
发布时间:2019-06-29

本文共 1465 字,大约阅读时间需要 4 分钟。

  hot3.png

R语言中的 & 和 &&

今天才发觉R中的& 和 && 不是一回事…

区别之一

当然,如果只计算两个标量(长度为1的向量),他俩似乎是差不多的:

TRUE & FALSE
## [1] FALSE
TRUE && FALSE
## [1] FALSE

如果计算的是两个向量的话,结果就明显不同:

c(TRUE, FALSE) & c(TRUE, TRUE)
## [1]  TRUE FALSE
c(TRUE, FALSE) && c(TRUE, TRUE)
## [1] TRUE

区别在于,& 依次比较两个向量中的对应元素,而&&只比较两个向量的首个元素。 &&的这种偷懒的做法确保了它的计算结果只为一个标量,TURE或FALSE。这就使他 可以与if等只接受一个标量为参数的函数完美搭配起来。

区别之二

说到偷懒,和&相比,&&偷懒的地方还不止这一处:

a #对象a不存在
## Error in eval(expr, envir, enclos): 找不到对象'a'
FALSE & a
## Error in eval(expr, envir, enclos): 找不到对象'a'
FALSE && a
## [1] FALSE

在进行比较时,&& 如果发现左边对象的值为FALSE,那么他就不会计算右边的对象了,(因为无论 右边对象的值为多少,逻辑与的结果总为FALSE)所以即使右边对象不存在时,也没有抛出错误。而 &就老实多了,计算完左边后他还会计算右边,而右边对象不存在,于是抛出错误。&&的这种计算方法 叫做短路计算

一点分析

好奇&&是怎么偷懒的,查看他的源代码:

`&&`
## .Primitive("&&")

不出所料,&&函数是调用编译好的c代码。要查看他的源代码就有点小麻烦,下载未编译的R源代码(也可以直接查看Github上的一个热心人维持的),在 src/main/names.c文件中找到这一行:

{"&&",      do_logic2,  1,  0,  2,  {PP_BINARY,  PREC_AND,    0}},

可知&&在c代码里面叫做do_logic2,接下来一番搜索最终在src/main/logic.c中 找到do_logic2的定义,看到其中一行:

x1 = asLogical(s1);

意思是取得左侧对象的值,怎么取?再看看asLogical这个函数的定义。又是一番搜索 在src/main/coerce.c中找到他的定义,其中几行:

switch (TYPEOF(x)) {case LGLSXP:      return LOGICAL(x)[0];

注意到[0]中的0,说明只提取数组的第一个元素(c语言中数组下标是从0开始的)。这也就是&&之所以只比较向量的第一个元素的原因。

回过头来再接着往下看看do_logic2的定义,看到其中几行:

case 1: /* && */      if (x1 == FALSE)          ans = FALSE;      else {          get_2nd;

意思很明白,如果&&左边对象(x1)的值为FALSE,那么结果(ans) 就为FALSE,不必再计算右边对象。否则的话(x1值为FALSE),还得计算右边对象(get_2nd)。 这就是&&短路计算的实现方式。分析至此告一段落。

参考:

转载于:https://my.oschina.net/tekie/blog/638023

你可能感兴趣的文章
Oracle——18用户、角色和权限信息的视图总结
查看>>
WordPress 中的 Debug 模式(调试模式)
查看>>
node下使用express框架,ejs模板引擎
查看>>
搜索:文本的匹配算法
查看>>
Fedora 17 LibreOffice 办公套件的安装与汉化
查看>>
scrollview不充满屏幕的原因
查看>>
PHP单例模式
查看>>
解密敏捷自动化测试
查看>>
DelphiMVC拦截器介绍
查看>>
Spring Cloud构建微服务架构:分布式配置中心【Dalston版】
查看>>
iOS 11正式版终于来了!强力助攻小程序
查看>>
开放平台API接口调用频率控制系统设计浅谈
查看>>
Lucene4.3进阶开发之潜龙勿用( 七)
查看>>
DTD和schema小总结
查看>>
去掉导航栏的黑线
查看>>
怎样让html加载完毕后加载js代码
查看>>
piwik 案例介绍
查看>>
敏感字过滤
查看>>
为什么我们要从 NodeJS 迁移到 Ruby on Rails
查看>>
Android 文件式数据库Realm
查看>>