Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

前端基础-05-JavaScript简介

$
0
0

JavaScript简介

1.JavaScript简介

  • JavaScript 是一种脚本语言,是一种动态类型、弱类型
  • JavaScript通常用来操作HTML页面的
  • html骨架,css是样式,js是行为

2.JavaScript如何调用

  • JS标签里面
<script>
     alert(5);
</script>
  • 写在外部.js后缀文件里面,通过script标签引入
#引用方法:
<script src="testJs.js"></script>
  • 写在标签里面
<div class="box1" onclick="alert(1)">
</div>

注意在引入js文件的script里面,一定不能再写js代码

标签里面写js代码一般情况下不推荐

script标签的位置:

head或者body里面,建议写在body里面
要注意是否需要加上window.onload

window.onload = function () {
//这里再写代码(意识是:当整个页面加载完成之后,再执行这里的代码)
//一个页面中只能出现一次window.onload
alert(5);
}

如果说没有什么特别的要求,一般script标签放在body结束之前

3.JavaScript注释

  • 单行注释
/*
多行注释
*/
  • 多行注释
//  单行注释

4.JavaScript代码规范

  • 严格区分大小写 alert才是js本身自带的,Alert不是自带的
  • 语句字符必须是半角符号
  • 某些完整的语句后面需要分号
  • 引号里面代表字符串,字符串是没有代码功能的,所以不需要满足上面的条件

5.常用的获取页面元素

那么JS如何操作页面:
要操作页面,就是操作标签,JS要操作标签,就要先获取标签

#JS如何获取独有标签
#document.title
document.title = "我要把标题改成666";

#document.head

#document.body
//修改别的标签的内容,得用innerHTML(会解析标签),innerText(不会解析标签)
document.body.innerHTML = "<em>我想给页面加点东西</em>";
document.body.innerText = "<em>我想给页面加点东西</em>";

#其他标签的获取,id前面必须是document,其他的前面可以是某个元素,但不能是集合
#通过id获取元素
document.getElementById()
//获取的是确切的某个元素,可以直接操作这个元素
document.getElementById("box").innerHTML += "吃惊";


#通过className获取元素(不支持IE8及以下)
.getElementsByClassName()
//获取的是一堆元素的集合,设置操作的时候要通过下标(索引、序号)拿到对应的某一个
document.getElementsByClassName("wrap")[0].innerHTML = "害怕";
document.getElementsByClassName("wrap")[1].innerHTML = "害怕+1";

#通过标签名获取元素
.getElementsByTagName()
document.getElementsByTagName("p")[0].innerHTML = "同学们好";
alert(document.getElementsByTagName("p").length);

#通过选择器的写法获取元素(不兼容IE7及以下)
.querySelector()
.querySelectorAll()
//获取第一个对应的元素
document.querySelector("#box1 .fly").innerHTML = "box1 kk fly";
//获取所有对应的元素
document.querySelectorAll("#box1 .fly")[1].innerHTML = "box1 fly";

#通过name值获取
document.getElementsByName()

#写入内容
#在页面加载完之前,给body部分新增内容
document.write()
document.write("我是新增的内容!");
#在文档流关闭之后,修改整个html的内容
window.onload = function () {
    document.write("我是新增的内容!");
};

6.JS常用的几个事件

#事件:用户的操作
    元素.事件 = 函数;
    鼠标事件:
        左键单击 oncclick
        左键双击 ondblclick
        鼠标移入 onmouseover/onmouseenter
        鼠标移出 onmouseout/onmouseleave
document.getElementById("box").onclick = function () {
            alert("hello world");
           document.getElementById("box").innerHTML = "哈哈";
            this.innerHTML = "哈哈";
};
document.getElementById("box").onmouseenter= function () {
            alert("hello world");
};
document.getElementById("box").onmouseleave= function () {
            alert("hello world");
};
作者:lianjiaokeji 发表于2017/11/16 15:46:32 原文链接
阅读:0 评论:0 查看评论

Nginx使用教程

$
0
0

什么是Nginx

Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件代理服务器,并在一个BSD-like协议下发行。由俄罗斯的程序设计师lgor Sysoev所开发,供俄国大型的入口网站及搜索引擎Rambler使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。

 

nginx的优点

Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率。能经受高负载的考验, 有报告表明能支持高达 50,000 个并发连接数。

Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理服务器对外进行服务。

Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。

Nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,就稳定性而言,nginx比lighthttpd更胜一筹。

Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。

Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比Perlbal 要好很多。

 

在windows上配置nginx实例详解

首先下载一个nginx,解压到本地,我这里解压位置:D:\lin\nginx

运行nginx(指令如下图)


以下是nginx默认的配置信息(路径:D:\lin\nginx\conf\nginx.conf)。

server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

配置信息介绍:

    listen:表示当前的代理服务器监听的端口,默认的是监听80端口。

    server_name:用于配置基于名称的虚拟主机 ,server_name在接到请求后的进行匹配。

顺序为完全匹配>*开始的域>*结束的域>正则表达式,因为匹配成功就会不再进行其他匹配,所以设置规则时要注意控制规则范围的顺序。

    location:表示匹配的路径,默认所有请求都被匹配

    root:如果配置了root,作用是当匹配到请求的路径时,将会在这个文件夹内寻找符合规则的文件。

    index:当没有指定主页时,默认会选择这个指定的文件,它可以有多个,并按顺序来加载,如果第一个不存在,则找第二个,依此类推。

 

nginx本质上就是一个负责转发的代理服务器,那么如何配置进行代理转发?

比如我们在本地开启了tomcat,他的默认端口是8080,此时访问tomcat的路径是localhost:8080,现在准备通过nginx使得访问localhost时转到tomcat请求下。

 

我们只需要在nginx.conf中稍微改动即可,如下:




这里解释一下proxy_pass    http://localhost:8080; 这里表示代理,相当于将上面的监控的请求路径转发到localhost:8080去了

配置信息修改完之后要重新加载文件,可以使用命令:nginx -s reload  ,来进行刷新

现在,我们刷新localhost界面,就会发现他显示了tomcat的主界面。

 

nginx擅长处理静态页面,也就是html、css、js等,但无法解析jsp,我们通常会配置nginx让他处理静态页面,让tomcat处理jsp,那么这样如何配置呢?





如上图,我们首先要去掉之前配的location /,否则请求全被它拦截了,后面的配置就没有意义。

接着,配置中使用了正则


location ~ \.jsp$ {  
        proxy_pass http://localhost:8080;  
}

表示后缀为jsp的请求被转发到http://localhost:8080,这里也就是tomcat的主页面。

此时,我们请求http://localhost/index.jsp,页面如下图:


location ~ \.(html|js|css|png|gif)$ {  
	root D:/lin/apache-tomcat-8.0.47-windows-x64/apache-tomcat-8.0.47/webapps;  
}

表示后缀为html|js|css|png|gif这些的页面,转发去本地的webapps下面去找资源(这里是我的本地路径),此时webapps下面没有页面,为了看个效果,去webapps下面的docs下面复制个index.html出来,此时输入http://localhost/,转发到了我们刚复制到webapps下面的index.html页面,如下图:

没有样式,因为随便复制出来的一个,可能css,js路径不匹配。


nginx最常用作负载均衡,将大量的并发访问或数据流量分担到多台节点设备服务器上分别处理,那么他是如何配置的呢?

我们在server外添加了一个upstream,然后就可以在proxy_pass里面直接用http://+upstream的名称来使用。

例如:

我们使用两台服务器分担数据流量,配置如下:

upstream up_name {
    ip_hash;
    server www1.ysblv.cn:8080;
    server www1.ysblv.cn:8080;
}

那么,proxy_pass配置的转发地址就应该是这样:

location /ysblv/ {
    proxy_pass  http://up_name/ysblv/;
}

这里需要注意的是:upstream配置在nginx.conf中,但在server{}之外,不能被server包围起来;upstream中配置的server元素和proxy_pass中的不同,不能加http://。

 

这里解释一下ip_hash

ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某个IP的用户在后端Web服务器www1上登录后,再访问该站点的其他URL,能够保证其访问的还是后端Web服务器www1而不是www2。如果不采用ip_hash指令,假设来自某个IP的用户在后端Web服务器www1上登录后,再访问该站点的其他URL,有可能被定向到后端Web服务器www2上,由于用户登录后session信息是记录在服务器www1上的,www2上没有,这时会提示用户还没有登陆。

 

以上简单的介绍了nginx的基本功能和配置,下面列一个nginx配置信息的详细清单,供参考,配置时可以查看,这份配置来自(脚本之家)


#定义Nginx运行的用户和用户组
user www www;

#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;

#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;

#进程文件
pid /var/run/nginx.pid;

#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;

#工作模式与连接数上限
events {

 #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
 use epoll;
 
 #单个进程最大连接数(最大连接数=连接数*进程数)
 worker_connections 65535;
}

#设定http服务器
http {
 include mime.types; #文件扩展名与文件类型映射表
 default_type application/octet-stream; #默认文件类型
 #charset utf-8; #默认编码
 server_names_hash_bucket_size 128; #服务器名字的hash表大小
 client_header_buffer_size 32k; #上传文件大小限制
 large_client_header_buffers 4 64k; #设定请求缓
 client_max_body_size 8m; #设定请求缓
 sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
 autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
 tcp_nopush on; #防止网络阻塞
 tcp_nodelay on; #防止网络阻塞
 keepalive_timeout 120; #长连接超时时间,单位是秒

 #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
 fastcgi_connect_timeout 300;
 fastcgi_send_timeout 300;
 fastcgi_read_timeout 300;
 fastcgi_buffer_size 64k;
 fastcgi_buffers 4 64k;
 fastcgi_busy_buffers_size 128k;
 fastcgi_temp_file_write_size 128k;

 #gzip模块设置
 gzip on; #开启gzip压缩输出
 gzip_min_length 1k; #最小压缩文件大小
 gzip_buffers 4 16k; #压缩缓冲区
 gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
 gzip_comp_level 2; #压缩等级
 gzip_types text/plain application/x-javascript text/css application/xml;
 
 #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
 gzip_vary on;
 #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用

 upstream qianyunlai.com {
  #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
  server 192.168.80.121:80 weight=3;
  server 192.168.80.122:80 weight=2;
  server 192.168.80.123:80 weight=3;
 }

 #虚拟主机的配置
 server {

  #监听端口
  listen 80;
  
  #域名可以有多个,用空格隔开
  server_name www.qianyunlai.com qianyunlai.com;
  index index.html index.htm index.php;
  root /data/www/qianyunlai;

  location ~ .*.(php|php5)?$ {
   fastcgi_pass 127.0.0.1:9000;
   fastcgi_index index.php;
   include fastcgi.conf;
  }

  #图片缓存时间设置
  location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
   expires 10d;
  }

  #JS和CSS缓存时间设置
  location ~ .*.(js|css)?$ {
   expires 1h;
  }

  #日志格式设定
  log_format access '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" $http_x_forwarded_for';
  
  #定义本虚拟主机的访问日志
  access_log /var/log/nginx/qianyunlai.log access;

  #对 "/" 启用反向代理
  location / {
   proxy_pass http://127.0.0.1:88;
   proxy_redirect off;
   proxy_set_header X-Real-IP $remote_addr;
   
   #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   
   #以下是一些反向代理的配置,可选。
   proxy_set_header Host $host;
   client_max_body_size 10m; #允许客户端请求的最大单文件字节数
   client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
   proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
   proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
   proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
   proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
   proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
   proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
   proxy_temp_file_write_size 64k;
   #设定缓存文件夹大小,大于这个值,将从upstream服务器传
  }

  #设定查看Nginx状态的地址
  location /NginxStatus {
   stub_status on;
   access_log on;
   auth_basic "NginxStatus";
   auth_basic_user_file conf/htpasswd;
   #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
  }

  #本地动静分离反向代理配置
  #所有jsp的页面均交由tomcat或resin处理
  location ~ .(jsp|jspx|do)?$ {
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_pass http://127.0.0.1:8080;
  }

  #所有静态文件由nginx直接读取不经过tomcat或resin
  location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ {
   expires 15d;
  }
  
  location ~ .*.(js|css)?$ {
   expires 1h;
  }
 }
}

作者:weixin_36380516 发表于2017/11/16 15:47:22 原文链接
阅读:4 评论:0 查看评论

Mycat之——日志报Unknown charsetIndex:224错误

$
0
0

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/78547554

Mycat启动后,不能进行任何数据库的操作,报Unknown charsetIndex:224错误
从错误看是因为字符集问题引起的  ,因为我MYSQL服务器默认使用的是utf8mb4,所以修改mycat字符集的配置文件
#vi index_to_charset.properties
在配置文件最后加入224=utf8mb4,重启服务即正常


作者:l1028386804 发表于2017/11/16 9:51:08 原文链接
阅读:99 评论:0 查看评论

Linux硬连接和软连接详解

$
0
0

Lnux也有类似于windows下的快捷方式,这种快捷方式在linux下称作硬连接(hard link)和软连接(symbolic link,又称作符号链接)。

创建链接文件
创建linkfile.txt文件

[root@localhost tmp]# touch linkfile.txt
[root@localhost tmp]# echo 'testlink' > linkfile.txt 

创建硬连接

[root@localhost tmp]# ln linkfile.txt hardlink

创建软连接

[root@localhost tmp]# ln -s linkfile.txt softlink

读取文件内容,可以看出三个文件的内容都是一样的

[root@localhost tmp]# cat hardlink 
testlink
[root@localhost tmp]# cat softlink 
testlink
[root@localhost tmp]# cat linkfile.txt 
testlink

通过链接文件修改文件内容

[root@localhost tmp]# echo 'testlink2' >> hardlink 
[root@localhost tmp]# cat linkfile.txt 
testlink
testlink2
[root@localhost tmp]# echo 'testlink3' >> softlink 
[root@localhost tmp]# cat linkfile.txt 
testlink
testlink2
testlink3

可以看出,通过修改链接文件内容,源文件的内容也发生了改变。这就是链接文件的作用,链接文件基本上代表了源文件,通过链接文件可以查看修改源文件内容,也可以通过链接文件修改源文件属性等等。

硬连接和软连接有什么不同?
实际上软连接更接近windows的快捷方式,可以看下面的操作。

这里写图片描述

我将源文件给删除了,通过硬连接依然可以读取文件内容,软连接则显示文件不存在(源文件被删除,软连接文件的颜色都发生了改变)。这就奇怪了,源文件都删除了,为啥还可以读取文件内容?这涉及到linux的文件系统原理,linux中一个文件是由inode和block来存储的,block中存放文件内容,inode存放文件属性和block的位置。当用户读取文件内容的时候,系统会先找到该文件对应的inode,从inode中获取该用户是否有权限读取文件内容,如果有权限,则通过inode中存放的block位置找到相应的block,获取文件的内容。我这里只是简单的介绍linux的文件系统,详细内容推荐去看下linux相关书籍。

我们再重复最开始的操作,创建源文件,创建链接文件。

[root@localhost tmp]# rm -rf testlink.txt 
[root@localhost tmp]# rm -rf hardlink 
[root@localhost tmp]# rm -rf softlink 
[root@localhost tmp]# touch testlink.txt
[root@localhost tmp]# ln testlink.txt hardlink
[root@localhost tmp]# ln -s testlink.txt softlink
[root@localhost tmp]# ll -i testlink.txt hardlink softlink 
50801629 -rw-r--r-- 2 root root  0 Nov 16 15:54 hardlink
50801663 lrwxrwxrwx 1 root root 12 Nov 16 15:54 softlink -> testlink.txt
50801629 -rw-r--r-- 2 root root  0 Nov 16 15:54 testlink.txt

其中ll -i 指令可以查看文件的inode(第一列为inode编号)。可以看到hardlink和testlink.txt对应的是同一个inode,而softlink则占用了另外一个inode。软连接是指向源文件的,所以当删除源文件后,由于无法找到源文件的inode,自然就无法读取源文件的内容。但是对于硬连接来说,硬连接和源文件共享同一个inode,删除了源文件,inode和对应的block并没有被删除,所以依然可以通过硬连接来读取源文件的内容。

这样看来,硬连接貌似更安全。删除了源文件,依然可以通过硬连接来查看源文件的内容。但是由于硬连接的限制比较多,比如不能给文件夹创建硬连接。所以实际上,软连接用得更多一些。

给文件夹创建软连接

[root@localhost tmp]# mkdir dirlinktest
[root@localhost tmp]# ln dirlinktest/ dirhardlink
ln: ‘dirlinktest/’: hard link not allowed for directory --不允许给文件夹创建硬连接
[root@localhost tmp]# ln -s dirlinktest/ dirsoftlink
作者:u012062455 发表于2017/11/16 17:02:55 原文链接
阅读:0 评论:0 查看评论

poj 2586 Y2K Accounting Bug【贪心】【刷题计划】

$
0
0
Y2K Accounting Bug
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16154   Accepted: 8111

Description

Accounting for Computer Machinists (ACM) has sufferred from the Y2K bug and lost some vital data for preparing annual report for MS Inc. 
All what they remember is that MS Inc. posted a surplus or a deficit each month of 1999 and each month when MS Inc. posted surplus, the amount of surplus was s and each month when MS Inc. posted deficit, the deficit was d. They do not remember which or how many months posted surplus or deficit. MS Inc., unlike other companies, posts their earnings for each consecutive 5 months during a year. ACM knows that each of these 8 postings reported a deficit but they do not know how much. The chief accountant is almost sure that MS Inc. was about to post surplus for the entire year of 1999. Almost but not quite. 

Write a program, which decides whether MS Inc. suffered a deficit during 1999, or if a surplus for 1999 was possible, what is the maximum amount of surplus that they can post.

Input

Input is a sequence of lines, each containing two positive integers s and d.

Output

For each line of input, output one line containing either a single integer giving the amount of surplus for the entire year, or output Deficit if it is impossible.

Sample Input

59 237
375 743
200000 849694
2500000 8000000

Sample Output

116
28
300612
Deficit

Source

题意:某公司每5个月公布一次财务报告,一年公布了8次,每一次都是亏损,但是不知道每一次亏损了多少,题目给定了每个月的盈利值s和亏损值d,问,这一年能否不亏损,如果能,最大盈利值是多少?

思路:一开始没有懂什么意思,后来师父解释如下:1~5,2~6,3~7,4~8,5~9,...8~12.共8个季度,每个季度都是亏钱,要求最大的盈利值,就要使全年亏钱的月份最少,盈利月份数最多,并且满足每个季度都是亏损的,我用的枚举方法有如下情况(从盈利最多的情况开始枚举,直到枚举到全年亏损的情况):

1:每个季度4个月盈利,1个月亏。ssssd

2: 每个季度3个月盈利,2个月亏。sssdd

3: 每个季度2个月盈利,3个月亏。ssddd

4:每个季度1个月盈利,4个月亏。sdddd

5: 每个季度都亏损。输出    :Deficit。

#include<stdio.h>
int main()
{
    int s,d;//s是赚的钱,d是亏的钱 
    while(scanf("%d%d",&s,&d)!=EOF)
    {
        if(4*s < d&&(10*s-2*d>=0))//每个季度里4个月赚,1个月亏。全年10个月赚,2个月亏。 
            printf("%d\n",10*s-2*d);
        else if(3*s < 2*d&&(8*s-4*d>=0))//每个季度3个月赚,2个月亏。之后以此类推。 
            printf("%d\n",8*s-4*d);
        else if(2*s < 3*d&&(6*s-6*d>=0))
            printf("%d\n",6*s-6*d);
        else if(s < 4*d&&(3*s-9*d>=0))
            printf("%d\n",3*s-9*d);
        else 
            printf("Deficit\n");//以上条件都不满足,说明全年只有亏损 
    }
    return 0;
}

思路2:在师父吐槽了我的方法的局限性后,他给我解释了一下他的方法,可以适用更大数据的情况,解释了半天,我都不知道怎么用代码去实现,最后师父亲自写出来我才懂了,泪目~~

全年每个月的盈利情况如下:  1:ssssdssssdss

               2:sssddsssddss

               3:ssdddssdddss

               4:sddddsddddsd

               5:dddddddddddd

#include<stdio.h>
int main()
{
    int s,d,i,n,sum;//s是赚的钱,d是亏的钱 
    while(scanf("%d%d",&s,&d)!=EOF)
    {
        n = 5;
        for(i = 4; i >= 0; i --)//每个季度盈利月份从4枚举到0 
        {
            if(i*s < (n-i)*d)
                break;
        }//找到满足每个季度亏损并且使全年盈利最多的月份数i 
        sum = (i*s-(n-i)*d)*2;//计算在前10个月总的盈利数 
        if(i > 2)
            sum += s*2;//当每个季度的盈利月份大于2时,全年剩余的两个月也是盈利 
        else
            sum += s*i - d*(2-i);//反之,有可能一个月亏或者最后的两个月都亏损 
        if(sum >= 0)
            printf("%d\n",sum);
        else
            printf("Deficit\n"); 
    }
    return 0;
}


作者:hello_sheep 发表于2017/11/16 17:08:08 原文链接
阅读:0 评论:0 查看评论

干货 |《深入理解Elasticsearch》读书笔记

$
0
0

题记

由于之前已经梳理过Elasticsearch基础概念且在项目中实战过Elasticsearch的增删改查、聚类、排序等相关操作,对ES算是有了一定的认知。

但是,仍然对于一些底层的原理认知模糊,特买来《深入理解Elasticsearch》过了一遍,将书中一些细节知识点结合官网文档梳理如下。

1——4章偏应用,跟着敲一遍代码基本就能理解原理。
5——9章偏理论一些。
这里写图片描述

第5章 分布式索引架构

1、如何选择合适的分片和副本数?

目的:规划索引及配置,适应应用的变化。

正确认知:分片数索引创建后不可以修改,副本数索引创建后可以通过API随时修改。

多副本的缺点:额外副本占据了额外的存储空间,构建索引副本的开销也随之增大。

同时要注意:如果不创建副本,当主分片发生问题时,可能会造成数据的丢失。

配置参考:最理想的分片数量应该依赖于节点的数量。

参考公式:所需的最大节点数 = 分片数 *(副本数+1)
举例:你计划5个分片和1个副本,那么所需要的最大的节点数为:5*(1+1)=10个节点。

2、可不可以基于时间构建索引?

目的:选择感兴趣的索引上进行查询,历史索引(时间比较久)的定期删除。
正确操作方法:通过名称为logs_2017_01, logs_2017_02,…..logs_2017_12来构建索引。

第6章 底层索引控制

1、什么是段?

Elasticsearch中的每个分片包含多个segment(段),每一个segment都是一个倒排索引;在查询的时,会把所有的segment查询结果汇总归并为最终的分片查询结果返回。

在创建索引的时候,ES会把文档信息写到内存bugffer中(为了安全,也一起写到translog),定时(可配置)把数据写到segment缓存小文件中,然后刷新查询,使刚写入的segment可查。

虽然写入的segment可查询,但是还没有持久化到磁盘上。因此,还是会存在丢失的可能性的。所以,ES会执行flush操作,把segment持久化到磁盘上并清除translog的数据(因为这个时候,数据已经写到磁盘上,不再需要了)。
参考:http://t.cn/RjKOMv1

2、什么是段合并?

由于自动刷新流程每秒会创建一个新的段,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。

1)消耗资源:每一个段都会消耗文件句柄、内存和cpu运行周期;
2)搜索变慢:每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。

ES通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

3、段合并做了什么?

段合并的时候会将那些旧的已删除文档从文件系统中清除。
被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。

启动段合并不需要你做任何事。进行索引和搜索时会自动进行。
1)当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用。
2) 合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中。这并不会中断索引和搜索。

4、为什么要进行段合并?

1)索引段的个数越多,搜索性能越低并且消耗更多的内存;
2)索引段是不可变的,你并不能物理上从中删除信息。(可以物理上删除document,但只是做了删除标记,物理上并没有删除)
3)当段合并时,这些被标记为删除的文档并没有被拷贝至新的索引段中,这样,减少了最终的索引段中的document数目。

5、段合并的好处是什么?

1)减少索引段的数量并提高检索速度;
2)减少索引的容量(文档数)——段合并会移除被标记为已删除的那些文档。

6、段合并可能带来的问题?

1)磁盘IO操作的代价;
2)速度慢的系统中,段合并会显著影响性能。

第7章 管理Elasticsearch

1、有了副本机制为什么还需要集群备份?

Elasticsearch 副本提供了高可靠性;它们让你可以容忍零星的节点丢失而不会中断服务。
但是,副本并不提供对灾难性故障的保护。对这种情况,你需要的是对集群真正的备份——在某些东西确实出问题的时候有一个完整的拷贝。

2、集群如何备份?

使用 snapshot API备份你的集群。
它会拿到你集群里当前的状态和数据然后保存到一个共享仓库里。这个备份过程是”智能”的。
ES5.6集群备份官网参考: http://t.cn/RjKEH9G

3、集群备份分类?

完整备份——你的第一个快照会是一个数据的完整拷贝。
增量备份——所有后续的快照会保留的是已存快照和新数据之间的差异。随着你不时的对数据进行快照,备份也在增量的添加和删除。这意味着后续备份会相当快速,因为它们只传输很小的数据量。

4、集群可以备份到哪里?

要使用这个功能,你必须首先创建一个保存数据的仓库。有多个仓库类型可以供你选择:

  • 共享文件系统,比如 NAS
  • Amazon S3:亚马逊Web云服务
  • HDFS (Hadoop集群分布式文件系统)
  • Azure Cloud:微软云平台

5、备份操作API?

PUT _snapshot/my_backup
{
    "type": "fs",
    "settings": {
        "location": "/mount/backups/my_backup"
    }
}

注意:共享文件系统路径必须确保集群所有节点都可以访问到。

第8章 提高性能

1、什么情况下会出现堆内存泄漏?

如果没有足够的堆内存来供你的应用在堆上创建新对象,JVM会抛出一个OutOfMemeory异常,这是一个内存出了问题的迹象,要么是没有足够的内存给它,要么是有内存泄漏,导致没有释放不再使用的对象。

2、推荐的性能测试工具?

1)JMeter
2)ab(Apache基准测试工具)

3、ES需要优化的原因?

1)硬件问题——如机械硬盘和固态硬盘;
2)不良的数据结构;
3)糟糕的查询设计——如wildcard模糊匹配很长的字符串。

4、后台什么在运行导致CPU飙升?如何排查?

热点线程APi能向你提供查找问题根源所必需的信息。
GET /_nodes/hot_threads?pretty

5、如何扩展集群?

1)垂直扩展
向Elasticsearch集群添加更多的资源。
制约因素——如:JVM最大支持31GB物理内存。

2)水平扩展
索引多分片、多副本,集群中分散处理之。

优点:降低运行集群的成本。
版本升级后(如5.X升级到6.0),确保服务仍然可用。

6、集群架构设计考虑因素?

当你在设计架构、决定节点数量、有多少个索引以及每个索引的分片数量时,你需要把能接受的出现故障的节点数量考虑进去。

当然了,你还需要考虑性能,只不过冗余和高可用应该是进行扩展时的一个因子。

7、大规模集群节点角色如何设定?

为了有一个完全容错和高可用的集群,我们应该区分节点,为每个节点一个设计好的角色,角色分类如下:
1)路由节点或查询聚合节点;
发送子查询到其他节点,收集和合并结果,以及响应发出查询的客户端。

node.master: false
node.data: false

2)数据节点;

node.master: false
node.data: true

3)候选主节点。

node.master: true
node.data: false
http.enabled: false

候选主节点禁用Http协议是为了避免意外地在这些节点上进行查询。这样候选主节点相比于数据节点和路由节点可以使用更少的资源,可以确保它们仅仅被用来处理和主节点相关的工作。

8、高负载场景Elasticsearch优化的常规建议?

这里是建议,不是准则。
(1)选择正确的存储
如:选择默认的default存储类型。

(2)按需设定刷新频率
索引刷新频率定义:文档需要多长时间才能出现在搜索结果中。
正确认知:
1)刷新频率越短,查询越慢,且索引文档的吞吐率越低。
2)默认刷新频率:1s刷新一次。
3)无限的增加刷新时间是没有意义的,因为超过一定的值(取决于你的数据负载和数据量)之后,性能提升变得微乎其微。

(3)线程池优化
线程池优化的必要场景:你看到节点正在填充队列并且仍然有计算能力剩余,且这些计算能力可以被指定用于处理待处理的任务。

(4)调整合并过程
index.merge.policy.mery_factory低于默认值10,会导致更少的段,更低的RAM消耗,更快的查询速度和更慢的索引速度;
若大于10,导致索引由更多的分段组成,更高的RAM消耗,更慢的查询速度和更快的索引速度。

(5)合理数据分布
高索引量的使用场景:把索引分散到多个分片上来降低服务器CPU和I/O子系统的压力。

如果你的节点无法处理查询带来的负载,你可以增加更多的ES节点,并增加副本的数量,于是主分片的物理拷贝会部署到新增节点上。这样会使得文档索引慢一些,但是会给你同时处理更多查询的能力。

9.高负载、高查询频率场景的建议

(1)启动过滤器缓存和分片查询缓存
过滤器缓存配置:indices.cache.filter.size
分片查询缓存配置:indices.cache.query.enable

(2)优化查询语句结构
书本中的过滤器已不再使用5.X以及更高版本。
但,依然可以优化查询语句,返回核对查询同样语句返回时间,进行权衡优化。

(3)使用路由
有着相同路由值的数据都会保存到相同的分片上。

(4)并行查询
建议数据平均分配,多个节点可以有相同的负载。

(5)字段数据缓存和断路
当使用聚合和排序等字段数据缓存相关操作时,遇到了内存相关的问题(内存泄漏或者GC停顿),可以考虑使用 doc value。

(6)控制size和shard_size
主要针对聚合操作。
增加size和shard_size能使得聚合结果更准确,代价是:更多的网络开销和内存使用;
减少size和shard_size能使得聚合不那么精确,代价是:网络开销小和内存使用率低。

10、高负载、高索引吞吐量场景

(1)批量索引
批量索引代替逐个索引文档。

(2)doc values和索引速度的取舍
一方面:我们只关心更高的索引速度和更大的索引吞吐量,可以考虑不适用doc values。
另一方面:如果有大量的数据,为了使用聚合和排序功能而不产生内存相关问题,唯一选择——使用 doc values。

(3)控制文档字段
方式一:_source 控制字段输出;
方式二:禁用_all。
减少文档的大小和其内文本字段的数量会让索引稍快一些。

(4)索引的结构和副本
1)主分片部署到所有的节点上,以便:并行的索引文档,加快索引的速度。
2)过多的副本导致索引速度下降。

(5)调整预写日志。

(6)存储优化
1)资金充足,建议购买SSD——原因:速度优势明显;
2)资金不足,考虑ES使用多个数据路径。
3)不要使用共享或者远程的文件系统保存索引——原因:速度慢,整体性能下降。

(7)索引期间的内存缓存
建议给每个索引期间生效的分片分配512MB内存。
indices.memeory.index_buffer_size是设置节点的,而不是分片。

小结

书中基于ES1.X版本的一些优化细节,可能在5.X、6.X甚至更高版本中有所不同,需要根据实战需要、并结合最新官网文档更新相关知识。
ES仍然有很长的路要走,坚持、加油!

——————————————————————————————————
更多ES相关实战干货经验分享,请扫描下方【铭毅天下】微信公众号二维码关注。
(每周至少更新一篇!)

这里写图片描述
和你一起,死磕Elasticsearch
——————————————————————————————————

2017.11.16 19:33 于家中床前

作者:铭毅天下
转载请标明出处,原文地址:
http://blog.csdn.net/laoyang360/article/details/78554610
如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

作者:wojiushiwo987 发表于2017/11/16 19:31:49 原文链接
阅读:36 评论:0 查看评论

C++学习20:运算符重载

$
0
0

推荐参考:
http://blog.csdn.net/zgl_dm/article/details/1767201

运算符重载是c++多态的一种形式,可以实现将运算符扩展到自定义的类型。
运算符实际是一种函数,先来看运算符函数格式:

<返回类型说明符> operator <运算符> (<参数列表>)
{
    <函数体>
}   

对于运算符的重载分为两种:成员函数和友元函数(非成员函数,但与成员函数访问权限相同)。
来看一个例子,现在有一个Time类,其中sum函数就可以使用重载运算符+来替代。

class Time
{
    private:
        int Hour;
        int Minute;
    public:
        void setTime(int h, int m);
        Time sum(const Time&t) const;
        void showTime() const;
};

void Time::setTime(int h, int m)
{
    Hour = h;
    Minute = m;
}


Time Time::sum(const Time&t) const
{
    Time sum;
    sum.Minute = Minute + t.Minute;
    sum.Hour = Hour + t.Hour + sum.Minute / 60;
    sum.Minute %= 60;
    return sum;
};

下面来使用两种方法重载运算符+实现sum函数功能。

1.成员函数运算符

成员函数重载运算符形式和使用方法类似于成员函数,只是形式上有些不同:

<函数类型> operator <运算符> (<参数列表>)
{
    <函数体>
};  

在类中声明成员函数:

Time operator+(const Time&t) const;

定义:

Time Time::operator+(const Time&t) const
{
    Time sum;
    sum.Minute = Minute + t.Minute;
    sum.Hour = Hour + t.Hour + sum.Minute / 60;
    sum.Minute %= 60;
    return sum;
}

这样就可以直接使用+来实现sum功能了:

int main()
{
    Time one,two;
    one.setTime(2,40);
    two.setTime(5,55);
    Time result = one + two;
    result.showTime();
    system("pause");
}

结果如下:

8 hours, 35 minutes
请按任意键继续. . .

这里的Time result = one + two;实际可以转换为Time result = one.operator+(two);

2.友元函数运算符

友元函数形式如下,增加了friend关键字:

friend <函数类型> operator <运算符> (<参数列表>)
{
    <函数体>
};  

在类中声明友元函数,注意+号是为二元运算符,需要两个参数:

friend Time operator+(const Time&t1, const Time&t2);

定义前是不需要写friend关键字的:

Time operator+(const Time&t1, const Time&t2)
{
    Time sum;
    sum.Minute = t1.Minute + t2.Minute;
    sum.Hour = t1.Hour + t2.Hour + sum.Minute / 60;
    sum.Minute %= 60;
    return sum;
};

这样可以实现和刚刚成员函数运算符相同的功能了,但是其实际运行时转换为函数调用形式应为:

Time result = operator+(one,two);

3.重载限制

1.重载后的运算符必须至少有一个操作数是用户定义的类型,这是为了防止用户为标准类型重载运算符。
2.使用运算符时不能违背原运算符的语法规则。
3.只能重载已有的运算符,不能创建新运算符。
4.并不是所有运算符都可以进行重载,无法重载以下运算符:
sizeof——sizeof运算符
.——成员运算符
.*——成员指针运算符
::——作用域解析运算符
?:——条件运算符
typeid——一个RTTI运算符
const_cast,dynamic_cast,reinterpret_cast,static_cast——强制类型转换运算符
5.可重载的运算符中,以下运算符只能使用成员函数进行重载:
()——函数调用运算符
=——赋值运算符
[]——下标运算符
->——通过指针访问类成员的运算符
6.运算符函数只有一个符号,不要随意将运算符定义为与其原始功能不相关的功能。

作者:lin453701006 发表于2017/11/16 20:57:20 原文链接
阅读:0 评论:0 查看评论

Java并发编程札记-(一)基础-03线程的生命周期

$
0
0

本文主要讲解Java中线程的状态。Java中线程的状态和操作系统中线程的状态有所不同。

目录

  1. 线程的生命周期
  2. 线程的状态

线程的生命周期

MarkdownPhotos/master/CSDNBlogs/concurrency/0103/threadStaus.jpg

此图是根据自己的了解画的,如果有不足或错误欢迎指正。

线程的状态

Java中线程有哪些状态在Thread.State枚举中的介绍得很清楚。六种状态分别是NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。在某一时间点,一个线程只能处于这些状态中的一种。这些状态是虚拟机状态,它们并没有反映所有操作系统线程状态。

NEW

新建状态。尚未启动的线程的状态。如MyThread thread = new MyThread();,thread就处于NEW状态。

RUNNABLE

就绪状态(可运行状态)。可运行线程的线程状态。thread.start();后,thread就处在处于RUNNABLE状态。RUNNABLE状态的某一线程可能正在Java虚拟机中运行,但它也可能正在等待操作系统中的其他资源,比如CPU。一个线程在获得CPU的资源后,才可以执行任务,否则排队等待。

BLOCKED

阻塞状态。 线程因为某些原因暂时停止运行,它就进入了阻塞状态。直到某些条件发生,线程进入就绪状态,才有机会继续运行。
线程进入阻塞状态有如下原因:

  • 运行时的线程调用某一对象的同步方法,若该对象的同步锁被别的线程占用,就只好进入阻塞状态。等到获得了同步锁,才能进入就绪状态。(API上只说了这一个原因)
  • 线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。等到获得了相关资源,才能进入就绪状态。(待确定)

WAITING

等待状态。某一等待线程的线程状态。处于等待状态的线程正等待另一个线程,以执行特定操作。某一线程因为调用下列方法之一而处于等待状态:

  • 不带超时值的Object.wait。已经在某一对象上调用了Object.wait()的线程正等待另一个线程,以便在该对象上调用Object.notify()或Object.notifyAll()。
  • 不带超时值的Thread.join。已经调用了Thread.join()的线程正在等待指定线程终止。
  • LockSupport.park。

TIMED_WAITING

定时等待状态。具有指定等待时间的某一等待线程的线程状态。某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态:

  • Thread.sleep。线程执行了Thread.sleep(int n)方法,线程将在n毫秒内放弃CPU,然后进入就绪状态。
  • 带有超时值的Object.wait。已经在某一对象上调用了Object.wait(long timeout)的线程正等待另一个线程,当对应的notify()被调用或者超出指定时间时线程重新进入就绪状态。
  • 带有超时值的Thread.join。例如,已经调用了join(long millis)的线程正在等待指定线程终止。等待该线程终止的时间最长为millis毫秒。超时为 0 意味着要一直等下去。
  • LockSupport.parkNanos。
  • LockSupport.parkUntil。

TERMINATED

终止状态。已终止线程的线程状态。线程已经结束执行。

在对Thread类做讲解时会讲到上述内容涉及到的方法。
本文就讲到这里,想了解更多内容请参考:

END.

作者:panweiwei1994 发表于2017/11/16 21:07:55 原文链接
阅读:2 评论:0 查看评论

【拜小白opencv】36-形态学滤波1——腐蚀

$
0
0

常言道“温故而知新”,写此文章就是对自己目前学习内容的小小的总结与记录。

本文力求用最简洁的语言,详细的代码将此部分内容讲解清楚,但由于博主同样是刚刚接触OpenCV,或许表达上有些瑕疵,还望读者能够指教探讨,大家共同进步。

博主机器配置为:VS2013+opencv2.4.13+Win-64bit。

若本文能给读者带来一点点启示与帮助,我就很开心了。

====================分割线====================


形态学操作就是基于形状的一系列图像处理操作。OpenCV为进行图像的形态学变换提供了快捷、方便的函数。最基本的形态学操作有二种,他们是:腐蚀与膨胀(Erosion 与 Dilation)。

膨胀与腐蚀能实现多种多样的功能,主要如下:

  • 1、消除噪声。
  • 2、分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
  • 3、寻找图像中的明显的极大值区域或极小值区域。

在进行腐蚀和膨胀的讲解之前,首先需要注意,腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。

膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。

腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。


也可以这么理解:

腐蚀是指:将卷积核B滑过图像A,找出卷积核区域内最小像素值作为锚点像素值。这一操作可以扩大低像素值区域。
膨胀是指:将卷积核B滑过图像A,找出卷积核区域内最大像素值作为锚点像素值。这一操作可以缩小低像素值区域。


本文主要说下腐蚀内容,膨胀请见下一篇文章。

=================分割线================

1-腐蚀

  • 1、腐蚀就是求局部最小值的操作。从数学角度来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,称之为A)与核(称之为B)进行卷积。
  • 2、核可以是任何形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoint)。多数情况下,核是一个小的,中间带有参考点和实心正方形或者圆形。其实,可以把核视为模板或者掩码。
  • 3、而腐蚀就是求局部最小的操作。核B与图像卷积,即计算核B覆盖的区域的像素点的最小值,并把这个最小值赋值给参考点指定的像素。这样就会使图像中高亮区逐渐减小,如下图所示。


腐蚀原理示意图

腐蚀的数学表达式如下:



==============分割线==============

2-腐蚀函数erode()

此函数作用:可实现对高亮区域的减少。


下面来看看erode()函数的定义:

void erode( InputArray src, OutputArray dst, InputArray kernel,
                         Point anchor=Point(-1,-1), int iterations=1,
                         int borderType=BORDER_CONSTANT,
                         const Scalar& borderValue=morphologyDefaultBorderValue() );


参数解释
  • 参数1:输入图像,即源图像。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
  • 参数2:输出图像,即目标图像,需要和源图片有一样的尺寸和类型。
  • 参数3:InputArray类型的kernel,腐蚀操作的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数getStructuringElement配合这个参数的使用。getStructuringElement()函数会返回指定形状和尺寸的结构元素(内核矩阵)。有关getStructuringElement()函数请见下面内容。
  • 参数4:Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于单位(element)的中心,我们一般不用管它。
  • 参数5:int类型的iterations,迭代使用erode()函数的次数,默认值为1。
  • 参数6:int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
  • 参数7:const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
使用erode函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。而且往往结合getStructuringElement一起使用。

有关getStructuringElement()函数:
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1));
参数解释:
  • 参数1:表示内核的形状,我们可以选择如下三种形状之一:矩形——MORPH_RECT; 交叉形——MORPH_CROSS; 交叉形——MORPH_CROSS 。
  • 参数2:内核的尺寸。
  • 参数3:锚点的位置。
我们一般在调用erode()以及dilate()函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形的element形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。

====================分割线====================

3-代码演示

/*
	功能:形态学滤波:腐蚀操作
*/

#include <opencv2/core/core.hpp>                
#include <opencv2/highgui/highgui.hpp>                
#include <opencv2/imgproc/imgproc.hpp>               
#include <iostream>              
using namespace std;
using namespace cv;

int main()
{
	Mat srcImage, dstImage; //源图像,输出图像
	//---------【1】读取源图像并检查图像是否读取成功---------      
	srcImage = imread("D:\\OutPutResult\\ImageTest\\xing.jpg");
	if (!srcImage.data)
	{
		cout << "读取图片错误,请重新输入正确路径!\n";
		system("pause");
		return -1;
	}
	imshow("【源图像】", srcImage);
	//---------【2】获取自定义核---------
	Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
	//---------【3】进行腐蚀操作---------
	erode(srcImage, dstImage, element);
	//---------【4】显示效果图---------
	imshow("【效果图--腐蚀操作】", dstImage);
	waitKey(0);
	return 0;
}

======================分割线=====================

4-结果显示



=================分割线===================

5-程序说明

只要记住腐蚀和膨胀都是对白色部分(也就是高亮部分)而言,不是黑色部分。
因此腐蚀操作后,“拜小白”的文字显示比较大,是因为周围白色部分被腐蚀了。

================END=================







作者:sinat_36264666 发表于2017/11/16 21:12:24 原文链接
阅读:0 评论:0 查看评论

查看表的碎片空间并优化表文件

$
0
0
innodb在执行删除时,只是物理上做了被删除的标记,实际上并没有从数据文件中真正删除。即,所占用的空间也没有实际释放。后台的purge线程会定期清理这些已经删除的记录和文件,但并不会回收这些已经删除的空间给操作系统,即会在数据文件中产生许多空洞,数据文件也会越来越大。
查看空洞的方法:

通过SHOW TABLE STATUS的结果,查看实际数据Data_length和空洞数据Data_free的比例。如果Data_free特别大,说明这个表需要优化了,优化方法可以使用ALTER TABLE table_name ENGINE = INNODB;

mysql> show table status like 't2'\G
*************************** 1. row ***************************
           Name: t2
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 13
 Avg_row_length: 1260
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2017-11-16 05:23:08
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.00 sec)


show table status显示的每个列的意义如下:


Name:表名


Engine:存储引擎类型


Version:.frm文件的版本号?


Row_format:行格式


Rows:表中行数,INFORMATION_SCHEMA下的表是NULL


Avg_row_length:平均行长度


Data_length:Myisam表时数据文件的大小,单位字节
                      :innodb表指聚集索引分配的内存大小,以页的大小为单位


Max_data_length:myisam表数据文件的最大长度。如果给定了数据指针的大小,这是可以被存储在表中的数据的字节总数。
                               :InnoDB表未使用


Index_length:MyISAM表索引文件大小;InnoDB表二级索引的大小


Data_free:分配但未使用的字节大小


Auto_increment:AUTO_INCREMENT的下一个值


Create_time:表创建时间


Update_time:表最近更新的实际


Check_time:表最近check的实际


Collation:The table's character set and collation.


Checksum:checksum值


Create_options:CREATE TABLE的额外选项


Comment:创建表时使用的评注(或者有关为什么MySQL可以访问表信息的说明)。



作者:yanzongshuai 发表于2017/11/16 21:37:08 原文链接
阅读:0 评论:1 查看评论

Codeforces Round #443 (Div. 2) A-C 题解

$
0
0

好久不写博客,把最近的cf题解补回来。

A. Borya's Diagnosis
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

It seems that Borya is seriously sick. He is going visit n doctors to find out the exact diagnosis. Each of the doctors needs the information about all previous visits, so Borya has to visit them in the prescribed order (i.e. Borya should first visit doctor 1, then doctor 2, then doctor 3 and so on). Borya will get the information about his health from the last doctor.

Doctors have a strange working schedule. The doctor i goes to work on the si-th day and works every di day. So, he works on dayssi, si + di, si + 2di, ....

The doctor's appointment takes quite a long time, so Borya can not see more than one doctor per day. What is the minimum time he needs to visit all doctors?

Input

First line contains an integer n — number of doctors (1 ≤ n ≤ 1000).

Next n lines contain two numbers si and di (1 ≤ si, di ≤ 1000).

Output

Output a single integer — the minimum day at which Borya can visit the last doctor.

Examples
input
3
2 2
1 2
2 2
output
4
input
2
10 1
6 5
output
11
Note

In the first sample case, Borya can visit all doctors on days 23 and 4.

In the second sample case, Borya can visit all doctors on days 10 and 11.


cf的题就是英语难懂,这次的题还好些,毕竟看示例几乎就能看出题意。第一个题就是医生上班的时间类似于等差数列,要求严格按照输入顺序来对数据进行模拟,就是简单的模拟而已。

代码实现:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
struct node{
	int s,d;
}p[10000];

int main()
{
	int n,i,j,k;
	while(cin>>n)
	{
		for(i=0;i<n;i++)
		cin>>p[i].s>>p[i].d;
		
		int ans=p[0].s;
		for(i=1;i<n;i++)
		{
			while(p[i].s<=ans)
			p[i].s+=p[i].d;
			
			ans=p[i].s;
		}
		cout<<ans<<endl;
	}
	return 0;
}

B. Table Tennis
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

n people are standing in a line to play table tennis. At first, the first two players in the line play a game. Then the loser goes to the end of the line, and the winner plays with the next person from the line, and so on. They play until someone wins k games in a row. This player becomes the winner.

For each of the participants, you know the power to play table tennis, and for all players these values are different. In a game the player with greater power always wins. Determine who will be the winner.

Input

The first line contains two integers: n and k (2 ≤ n ≤ 5002 ≤ k ≤ 1012) — the number of people and the number of wins.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ n) — powers of the player. It's guaranteed that this line contains a valid permutation, i.e. all ai are distinct.

Output

Output a single integer — power of the winner.

Examples
input
2 2
1 2
output
2 
input
4 2
3 1 2 4
output
3 
input
6 2
6 5 3 1 2 4
output
6 
input
2 10000000000
2 1
output
2
Note

Games in the second sample:

3 plays with 13 wins. 1 goes to the end of the line.

3 plays with 23 wins. He wins twice in a row. He becomes the winner


又是一道模拟题,题意是有n个人,每个人都有一个能力值,从第一个人开始,依次跟后面的人进行比赛,输了的去队伍的最尾端,问第一个能连胜k场的人是哪个。

k<=10^12,其实也没那么可怕嘛,n最大不才500,只要k大于等于n输出的一定是最大的那个数,因为只有它才可以连续赢,当k小于n时,模拟就ok了,设置一个计数器从0开始计数,如果它大于前者,达到k-1就可以了。

代码实现:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
int map[505];

int main()
{
	ll n,k,i,j,ans;
	while(cin>>n>>k)
	{
		for(i=0;i<n;i++)
		cin>>map[i];
		if(k>=n)
		{
			sort(map,map+n);
			cout<<map[n-1]<<endl;
			continue;
		}
		int flag=1;
		for(i=0;i<n&&flag;i++)
		{
			if(map[i]<k)
			continue;
			int sum=0;
			if(i&&map[i-1]<map[i])
			sum=1;
			for(j=1;j<=k-sum;j++)
			{
				int temp=(i+j)%n;
				if(map[i]<map[temp])
				break;
				if(j==k-sum)
				{
					flag=0;
					ans=map[i];
					break;
				}
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Short Program
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Petya learned a new programming language CALPAS. A program in this language always takes one non-negative integer and returns one non-negative integer as well.

In the language, there are only three commands: apply a bitwise operation AND, OR or XOR with a given constant to the current integer. A program can contain an arbitrary sequence of these operations with arbitrary constants from 0 to 1023. When the program is run, all operations are applied (in the given order) to the argument and in the end the result integer is returned.

Petya wrote a program in this language, but it turned out to be too long. Write a program in CALPAS that does the same thing as the Petya's program, and consists of no more than 5 lines. Your program should return the same integer as Petya's program for all arguments from 0 to 1023.

Input

The first line contains an integer n (1 ≤ n ≤ 5·105) — the number of lines.

Next n lines contain commands. A command consists of a character that represents the operation ("&", "|" or "^" for AND, OR or XOR respectively), and the constant xi 0 ≤ xi ≤ 1023.

Output

Output an integer k (0 ≤ k ≤ 5) — the length of your program.

Next k lines must contain commands in the same format as in the input.

Examples
input
3
| 3
^ 2
| 1
output
2
| 3
^ 2
input
3
& 1
& 3
& 5
output
1
& 1
input
3
^ 1
^ 2
^ 3
output
0
Note

You can read about bitwise operations in https://en.wikipedia.org/wiki/Bitwise_operation.

Second sample:

Let x be an input of the Petya's program. It's output is ((x&1)&3)&5 = x&(1&3&5) = x&1. So these two programs always give the same outputs.


c题的收获最大,题意说任找出5组以内的操作,使其结果等于n种操作的结果。
大神一句话解决这个题,分别用全1和全0的数进行一遍输入的操作,比较结果中的各个位,如果都是0,则都是0,如果都是1,则都是1,如果原为0后为1原为1后为0则异或,和原来不变则没有操作。
也就是只要是三个& | ^ 操作总能得到结果,然后这个结论我不是很懂,先记住吧。弄懂了再来强行解释一波。
代码实现:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}

int main()
{
	int n,x,i,j,k;
	char ch;
	while(cin>>n)
	{
		int a=0,b=1023;
		for(i=0;i<n;i++)
		{
			cin>>ch>>x;
			if(ch=='&')
			{
				a&=x;
				b&=x;
			}
			else if(ch=='|')
			{
				a|=x;
				b|=x;
			}
			else
			{
				a^=x;
				b^=x;
			}
		}
		int temp1=a&b;
		int temp2=a|b;
		int ans=0;
		for(i=0;i<10;i++)
		{
			if((a>>i&1)&&!(b>>i&1))
			ans|=1<<i; 
		}
		cout<<"3"<<endl;
		cout<<"| "<<temp1<<endl;
		cout<<"& "<<temp2<<endl;
		cout<<"^ "<<ans<<endl;
	}
	return 0;
}


作者:Ever_glow 发表于2017/11/16 21:37:54 原文链接
阅读:0 评论:0 查看评论

Android 源码分析——阅读源码工具选用

$
0
0

此系列文章在 https://github.com/mzlogin/rtfsc-android 集中更新发布,欢迎感兴趣的童鞋们关注。

本篇原始链接:https://github.com/mzlogin/rtfsc-android/blob/master/0x001-tools.md

之前我写过一篇 搭建大型源码阅读环境——使用 OpenGrok,给大家介绍了一款开源的源码阅读工具的安装方法,实际到目前为止,OpenGrok 仍是我最喜爱的源码阅读工具之一。

本次 Android 源码阅读之旅,我也将继续使用 OpenGrok,有网络的时候使用在线的 http://androidxref.com/,离线时使用自己本地搭建的。

但同时在阅读 frameworks 源码时会首选使用 Chrome 插件 Insight.io for GitHub 来打开 GitHub 上的 frameworks base 镜像 android/platform_frameworks_base,它是一款强大的辅助工具,目录树、文件搜索、方法列表、定义跳转、引用查找等等都不在话下,要感受它的妙处可以安装起来体验,你一定会觉得值得拥有,先来几张图感受一下:

目录树、文件搜索:

file tree and search

方法列表、引用查找、弹出注释:

outline and reference

然后,找不到的定义去 OpenGrok,找不到的文件去 OpenGrok,双剑在手,天下我有……其实,也不是很爽,啥时候 Insight.io 有完整的 Android 源码就好了。

欢迎关注我的微信公众号,接收我的 Android 源码分析心得。

作者:mzlogin 发表于2017/11/16 13:53:13 原文链接
阅读:39 评论:0 查看评论

INSTALL_FAILED_TEST_ONLY 运行报错

$
0
0

INSTALL_FAILED_TEST_ONLY 运行报错

在使用Android Studio编译通过后,我们一般会运行程序来查看相应的效果。BUT,有的时候明明编译通过的程序却不能运行甚至是报错不能安装,比如下图所示:

这里写图片描述

这里报了一个错误:

INSTALL_FAILED_TEST_ONLY

按照字面意思:不允许我们调用者运行【测试版】的程序。

常规的原因以及解决办法有两个:

1,编译工具gradle使用了测试版本——XXX-alpha

buildscript {
    ...
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-alpha3'  
    }
    ...
}

很简单,我们只需要使用正式版的gradle编译运行程序即可。

如:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
        ...
    }
}

2,AndroidMainfest有多余的语句

<appliaction
...
    android:testOnly="true"
...>
....
</application>

只要有【testOnly】属性,程序就不会被运行,无论是在真机还是模拟器。

解决的方法就是去掉这一句重新编译运行。

PS:
除了上述两个方法外,我们还有大招:

adb install -t *.apk

使用adb命令安装上述问题也能解决。
其实,这条命令的意思与方法二一样,也是:允许安装 AndroidManifest.xml 里 application 指定 android:testOnly=”true” 的应用

作者:xiaoyaozaimz 发表于2017/11/16 21:52:52 原文链接
阅读:56 评论:0 查看评论

记忆网络之在对话系统中的应用

$
0
0

记忆网络之在对话系统中的应用

前面几天看了下Jason Weston等人在对话系统方面的工作,可以看成是对Memory Networks的扩展吧,应用到了对话领域中,主要看了下面三篇论文,基本上是按照发表时间顺序来的,接下来我们逐篇来介绍一下其主要工作内容:

  • evaluating prerequisite qualities for learning end-to-end dialog system
  • Dialog-based Language Learning
  • learning end-to-end goal-oriented dialog

evaluating prerequisite qualities for learning end-to-end dialog system

这篇文章是15年发表的,主要贡献是提出一个评估端到端对话系统性能的指标以及相关的数据集。目前对话系统可以分成三个类别:

1,传统的对话系统中常常使用对话状态跟踪组件+对话相应生成组件来完成对话,这样就需要结合预先定义好的状态结构、用户话语、上一轮对话以及一些别的外部信息,而且每一轮对话都需要标记其内部状态并精准的分析用户意图,这就导致其很难推广到大规模应用。

2,基于神经网络的端到端对话系统,其不需要状态跟踪组件,直接根据对话的上下文和用户当前输入生成回复,并且可实现端到端的反向传播训练。但是这就导致了其没有办法使用之前的数据集进行训练和测试(都针对状态跟踪设计)。所以目前一般使用人工评分(很难扩展)或者BLEU得分来评价模型的效果,但是往往不能够达到评价的标准。

3,本文提出的数据集和模型,第二种方法的缺点主要在于BLEU在带有目的性的对话中不能够起到很好的效果,比如特定的领域,电影推荐、餐厅助手等。

本文作者认为一个对话系统应该具有下面的四种能力才可以很方便的推广到其他领域中。作者以电影推荐助手为切入点,使用OMDb、MovieLens、Reddit构建了四个数据集,分别解决四个问题。如下:

  • QA:用于测试对话系统能否回答客观问题,类似于一个给予KB知识库的问答系统,给予SimpleQuestions数据集进行修改以适应本文的要求。其中每个问题会有一个答案列表,模型只需要生成一个答案列表即可,而不需要生成自然语言对话。最终使用@1作为评价指标。
  • 推荐:用于测试系统对用户个性化推荐的能力,而不是像上面的通用回答一样。基于MovieLens数据集,构建user*item矩阵记录用户给电影打分,然后在生成仿真对话,对每个用户选择其打5分的电影,然后推荐一个相似的电影。其实就是讲用户喜欢的电影作为上下文,然后需要给出用户潜在喜欢的电影,如下图所示:

    与QA任务相同,本数据集也是生成一个答案列表即可,不过区别在于这里以@100作为评估指标而不是@1,因为推荐矩阵十分稀疏@1准确率会很低。
  • QA+推荐混合能力:上面两个任务都只涉及一轮对话,也就是一个问题对应一个回答,这个任务主要关注于多轮对话。每条数据会有3轮对话,第一轮是Recommendation,第二轮是QA,第三轮也是类似于Recommendation的相似电影推荐任务。每一轮的对话都需要对之前对话的理解和上下文信息的使用。而且会对三轮对话的回答都进行评估,,并且使用@10作为评价指标。
  • chit-chat,闲聊能力:这个数据集是为了评测对话系统的chit-chat闲聊能力。使用Reddit的电影评价回复(两个用户之间)数据构建,76%是单轮回复,17%是两轮,7%是三轮及以上。为了跟前面的几个任务匹配,这里讲对话生成转化为目标选择。即选择10000个没有在数据集中出现过的评论作为负样本,每次的目标是从10001(10000个负样本加1个正确答案)候选答案中选择正确答案。
  • Joint task:将上面的4个任务进行联合训练,这样我们的模型将具有chit-chat(任务4)能力和目的性回答(任务1-3)。

最终作者分别使用了Memory Networks、Supervised Embedding models、LSTMs、QA、SVD、IR等方法对上述五个任务进行了测试,发现MemNN和Supervised Embedding效果比较好,而相比之下,MemNN效果是最好的。结果如下图所示:

本文还提出了一个比较好的想法就是将记忆分为Long-Term Memory和Short-Term Memory,其中Long指的是KB等知识库的记忆,用于回答一些客观的问题,使用三元组存储,而Short指的是当前对话的对话历史,更切合每条数据本身的记忆,可以得到一些对用户主观的了解和回答。这样综合使用Long和Short可以有比较好的回答效果,而且可以很方便地将4个任务joint起来进行训练。

Dialog-based Language Learning

从论文题目可以看出,本文提出基于对话的语言学习,与此同时训练得到一个对话系统。主要贡献在于其提出了10个基于对话的监督任务数据集,如下所示:

  1. Imitating an Expert Student:模仿专家进行对话,需要直接回答正确答案。可以看做剩余任务的baseline。
  2. Positive and Negative Feedback:带有反馈的对话,回答问题会收到对或者错的提示,而且对于正确的回答会有额外的reward信号作为奖励(数据集中使用+表示)。
  3. Answers Supplied by Teacher:当回答错误时,会被告知正确答案。难度介于任务1和2之间;
  4. Hints Supplied by Teacher:回答错误时,会被给关于正确答案的提示,难度介于任务2和3之间;
  5. Supporting Facts Supplied by Teacher:回答错误时,会被给关于正确答案的support facts;
  6. Missing Feedback:有一部分正确答案的reward会丢失(50%),与任务2相对应;
  7. No Feedback:完全没有reward;
  8. Imitation and Feedback Mixture:任务1和2的结合,检验模型是否可以同时学习两种监督任务;
  9. Asking for Corrections:当回答错误的时候,会主动请求帮助“Can you help me”,对应任务3;
  10. Asking for Supporting facts:当回答错误的时候,会主动请求帮助“Can you help me”,对应任务5;

这10个监督数据及是基于bAbI和movieQA两个数据集构建的,在此之上,作者又提出了下面四种使用数据进行训练的策略:

  1. Imitation Learning
  2. Reward-based Imitation
  3. Forward Prediction
  4. Reward-based Imitation + Forward Prediction

论文仍然使用MemNN作为模型进行训练,如下图所示:

Learning End-To-End Goal-Oriented Dialog

这篇文章Memory Network实现了end-to-end的任务型对话系统,旨在对于Goal-Oriented的对话系统构建一个比较完善的数据集和训练方法。因为端到端的深度学习的模型在chit-chat领域已经取得了比较好的效果,但是在Goal-Oriented领域与传统模型还存在一定的Gap,本文提出了一个给予餐厅预定领域的数据集。

首先该数据集中有一个全局的知识库,主要用于保存餐厅信息(菜种类、位置、价格、评分、地址、电话、桌子大小等),该KB可以通过API调用的方式进行访问(类似于SQL查询),然后对话数据可以分为四个任务:Issuing API calls,Updating API calls,Displaying options,Providing extra information,分别对应着根据用户需求调用API(用户需要输入餐厅信息,包括上面提到的存在KB中的餐厅的几个属性),用户更改需求够重新调用API,展示满足条件的结果,最终用户确定某个餐厅后将其位置、电话等信息显示出来的四个任务。以及最中将四个任务连接在一起进行训练。数据集如下图所示:

最终每个任务的数据集除了正常构建的测试集之外还会额外构建一个OOV的测试集,以测试模型是否可以应对不在词汇表中的对话这种情况,而且为了验证模型在其他数据上的效果,作者还将DSTC2(真实的人机对话)的数据集改造成本文所需要的形式,并测试模型在该数据集上的效果。最终作者也尝试了Rule-based System、IR model、Supervised Embedding Model、Memory Networks等几个模型在本任务上面的效果,结果如下图所示:

本文基于TensorFlow的实现方案可以参考下面的链接:

Memory Network实现方案

Supervised Embedding Model实现方案

上面两个实现方案均达到了论文中的效果,大概看了下代码,其实跟End-To-End MemNN基本上没有任何区别,原因就是这里所谓的对话系统并不涉及到对话生成这一块,其所回复的答案仍然是模板,也就是从候选答案池中选择一个作为答案进行回复,这跟用MemNN做QA没有本质的区别,所以模型也基本不需要改变。甚至他们的数据集构建的方法都是那么的相似==

总结

但是这几篇论文怎么说呢,一方面是自己之前还没怎么接触过对话系统这个领域,看这几篇论文相当于是在入门,另外一方面可能相关的论文也好、数据集也好、模型也好都还不是怎么了解,所以整体看下来感觉这几篇论文写的有些不符合我对对话系统的认知==#然后一个就是感觉都把主要精力放在了数据集的构建上,貌似模型的创新和改动都比较少,基本上都是直接把MemNN拿过来用,答案也是模板生成,直接从候选答案中选择即可。所以整体给人的感觉就是创新性不是很大,更多的是在构建不同的数据集以寻找一种更好的对话系统的任务、模板等。

作者:liuchonge 发表于2017/11/16 22:00:50 原文链接
阅读:32 评论:0 查看评论

DSL的诞生 | 复杂sql转成Elasticsearch DSL深入详解

$
0
0

源自死磕ElasticsearchQQ群(626036393)中的一个问题:
问题如下:

where (position=ES or work=ES or content=ES) and academic=本科 and (city=北京 or city=深圳)

怎么构建ES的查询条件?

我的问题拆解与实现如下:

1、sql语句转成DSL有哪些方法?

方案一:借助工具 NLP团体开发的Elasticsearch-sql;
2.X安装过,5.X没有再安装。
方案二:借助工具ElasticHQ的自动转换模块:
这里写图片描述
方案一、方案二和Github上其他语言开发的sql转DSL工具对简单的sql生成的DSL相对准确,但对于复杂的sql生成的不一定精确。(如上所示)

方案三:徒手生成。

2、如何根据复杂的sql语句生成ES的DSL查询语句呢?

步骤1:拆解

where (position=ES or work=ES or content=ES) and academic=本科 and (city=北京 or city=深圳)

这个sql语句由几部分组成呢?
以and作为拆分,共分为3部分:
三个部分sql用and衔接,转换为DSL对应最外层must;

第一部分: position=ES or work=ES or content=ES
三个子条件sql用or衔接,转换DSL对应should;

第二部分: academic=本科
单一条件转换为DSL对应term精确匹配;

第三部分: city=北京 or city=深圳
city的两个or语句转换为DSL对应terms多词精确匹配。

上面的sql都用的=号,假定不需要分词,我们统一采用termquery和termsquery实现。
引申:
如果需要分词,更换为matchquery或者match_parsequery即可。
如果需要模糊匹配,更换为wildcardquery接口。

步骤2:套bool多条件检索DSL模板

复杂bool多条件检索DSL模板:
包含了:查询/检索、聚合、排序、指定字段输出、输出起点、输出多少等信息。

{
  "query": {
  "bool": {
  "must": [],
  "must_not": [],
  "should": []
  }
  },
  "aggs": {
  "my_agg": {
  "terms": {
  "field": "user",
  "size": 10
  }
  }
  },
  "highlight": {
  "pre_tags": [
  "<em>"
  ],
  "post_tags": [
  "</em>"
  ],
  "fields": {
  "body": {
  "number_of_fragments": 1,
  "fragment_size": 20
  },
  "title": {}
  }
  },
  "size": 20,
  "from": 100,
  "_source": [
  "title",
  "id"
  ],
  "sort": [
  {
  "_id": {
  "order": "desc"
  }
  }
  ]
}

简单bool多条件查询DSL模板:
只包含查询。

{
  "query": {
  "bool": {
  "must": [],
  "must_not": [],
  "should": []
  }
  }
}

以上根据我们的sql特点,简单模板即能满足要求。

步骤3:构造生成DSL

根据,步骤1、步骤2,可以构思出根据sql转换后的DSL应该:
1)最外层bool
2)第二层:must 三个并行条件
3)第三层:各自的匹配条件。(存在bool嵌套bool的情况)

3、动动手,验证下。

3.1 创建索引(自动生成mapping)

put test_index_01

3.2 提交数据

post test_index_01/test_type_01/1
{
  "no":"1",
  "city":"北京",
  "academic":"专科",
  "content":"ES",
  "position":"ES",
  "work":"ES"
}
post test_index_01/test_type_01/2
{
  "no":"2",
  "city":"天津",
  "academic":"本科",
  "content":"ES",
  "position":"ES",
  "work":"ES"
}
post test_index_01/test_type_01/3
{
  "no":"3",
  "city":"深圳",
  "academic":"本科",
  "content":"ES",
  "position":"ES2",
  "work":"ES3"
}
post test_index_01/test_type_01/4
{
  "no":"4",
  "city":"北京",
  "academic":"本科",
  "content":"ES1",
  "position":"ES2",
  "work":"ES"
}

插入后ES-head插件控制台查询结果:
这里写图片描述

3.3 完成检索

post test_index_01/_search
{
  "query": {
  "bool": {
  "must": [
  {
  "terms": {
  "city.keyword": [
  "北京",
  "深圳"
  ]
  }
  },
  {
  "term": {
  "academic.keyword": "本科"
  }
  },
  {
  "bool": {
  "should": [
  {
  "term": {
  "content.keyword": "ES"
  }
  },
  {
  "term": {
  "position.keyword": "ES"
  }
  },
  {
  "term": {
  "work.keyword": "ES"
  }
  }
  ]
  }
  }
  ]
  }
  },
  "size": 10,
  "from": 0
}

注意:
没有做分词,做的精确匹配,所以加了”.keyword”。

3.4 返回结果

{
  "took": 1,
  "timed_out": false,
  "_shards": {
  "total": 5,
  "successful": 5,
  "failed": 0
  },
  "hits": {
  "total": 2,
  "max_score": 1.0577903,
  "hits": [
  {
  "_index": "test_index_01",
  "_type": "test_type_01",
  "_id": "4",
  "_score": 1.0577903,
  "_source": {
  "no": "4",
  "city": "北京",
  "academic": "本科",
  "content": "ES1",
  "position": "ES2",
  "work": "ES"
  }
  },
  {
  "_index": "test_index_01",
  "_type": "test_type_01",
  "_id": "3",
  "_score": 0.8630463,
  "_source": {
  "no": "3",
  "city": "深圳",
  "academic": "本科",
  "content": "ES",
  "position": "ES2",
  "work": "ES3"
  }
  }
  ]
  }
}

4、小结

实践是检验真理的唯一标准!
如有不同意见,欢迎拍砖探讨!

——————————————————————————————————
更多ES相关实战干货经验分享,请扫描下方【铭毅天下】微信公众号二维码关注。
(每周至少更新一篇!)

这里写图片描述
和你一起,死磕Elasticsearch
——————————————————————————————————

2017.11.16 22:39 于家中床前

作者:铭毅天下
转载请标明出处,原文地址:
http://blog.csdn.net/laoyang360/article/details/78556221
如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

作者:wojiushiwo987 发表于2017/11/16 22:38:02 原文链接
阅读:58 评论:0 查看评论

数据结构与算法分析(Java语言描述)(25)—— 邻接表表示稀疏图

$
0
0

这里写图片描述

这里写图片描述


package com.dataStructure.graph;

import java.util.ArrayList;
import java.util.List;

//// 稀疏图 - 邻接表
//public class SparseGraph {
//
//    private int n;  // 节点数
//    private int m;  // 边数
//    private boolean directed;    // 是否为有向图
//    private List<Integer>[] g;   // 图的具体数据
//
//    // 构造函数
//    public SparseGraph(int n, boolean directed) {
//        assert n >= 0;
//        this.n = n;
//        this.m = 0;    // 初始化没有任何边
//        this.directed = directed;
//        // g初始化为n个空的 ArrayList , 表示每一个g[i]都为空, 即没有任和边
//        // g 是一个存储 ArrayList 的数组
//        // 数组中的每一个元素都 图中的一个节点和与之有联系的节点 组成的ArrayList
//        g = (ArrayList<Integer>[]) new ArrayList[n];
//        for (int i = 0; i < n; i++)
//            g[i] = new ArrayList<Integer>();
//    }
//
//    public int V() {
//        return n;
//    } // 返回节点个数
//
//    public int E() {
//        return m;
//    } // 返回边的个数
//
//    // 向图中添加一个边
//    public void addEdge(int v, int w) {
//
//        assert v >= 0 && v < n;
//        assert w >= 0 && w < n;
//
//        // v 表示的是 图中节点
//        // g[v] 表示图中与 v 相连的节点组成的 ArrayList
//        // g[v].add(w) 表示 将与 v 相连的节点 w 放到 g[v](ArrayList) 中
//        g[v].add(w);
//        if (v != w && !directed)
//            g[w].add(v);
//
//        m++;
//    }
//
//    // 验证图中是否有从v到w的边
//    boolean hasEdge(int v, int w) {
//
//        assert v >= 0 && v < n;
//        assert w >= 0 && w < n;
//
//        for (int i = 0; i < g[v].size(); i++)
//            if (g[v].get(i) == w)
//                return true;
//        return false;
//    }
//}

// 使用 邻接表 表示 稀疏图
public class SparseGraph {
    private int n;  // 图中节点数量
    private int m;  // 图中边的数量
    private List<Integer>[] g;  // 邻接表 g
    private boolean directed;   // 是否为有向图

    public SparseGraph(int n, boolean directed) {
        this.n = n; // 初始化节点数量
        this.m = 0; // 初始图中边数为 0
        this.directed = directed;

        // 初始化一个用于存储 ArrayList<Integer>类型数据 的数组 g 作为邻接表
        g = (ArrayList<Integer>[]) new ArrayList[n];
        for (int i = 0; i < n; i++) {
            g[i] = new ArrayList<Integer>();
        }
    }

    // 返回图中边的数量
    public int E() {
        return m;
    }

    // 返回图中节点的数量
    public int V() {
        return n;
    }

    // 在节点 v 与 w 之间添加一条边
    public void addEdge(int v, int w) {

        // 当 v 和 w 之间没有边时
        if (!hasEdge(v, w)) {

            // 在邻接表中添加一条 v 、 w 之间的边
            g[v].add(w);
            if (v != w && !directed)
                g[w].add(v);

            // 图中边数+1
            m++;
        }
    }

    // 判断两节点 v、w 之间是否存在边
    private boolean hasEdge(int v, int w) {
        // 遍历 g[i] 中存储的 ArrayList,若其中存在 w ,返回 true
        for (int i = 0; i < g[v].size(); i++) {
            if (g[v].get(i) == w)
                return true;
        }
        return false;
    }

    // 返回节点v 的所有邻接节点
    public Iterable<Integer> adjacentNode(int v){
        return g[v];
    }
}
作者:HeatDeath 发表于2017/11/16 23:47:43 原文链接
阅读:45 评论:0 查看评论

数据结构与算法分析(Java语言描述)(26)—— 邻接矩阵表示稠密图

$
0
0

这里写图片描述

这里写图片描述


package com.dataStructure.graph;

//// 稠密图 - 使用邻接矩阵表示
//public class DenseGraph {
//
//    private int n;  // 节点数
//    private int m;  // 边数
//    private boolean directed;   // 是否为有向图
//    private boolean[][] g;      // 图的具体数据
//
//    // 构造函数
//    public DenseGraph(int n, boolean directed) {
//        assert n >= 0;
//        this.n = n;
//        this.m = 0;    // 初始化没有任何边
//        this.directed = directed;
//        // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边
//        // false为boolean型变量的默认值
//        g = new boolean[n][n];
//    }
//
//    public int V() {
//        return n;
//    } // 返回节点个数
//
//    public int E() {
//        return m;
//    } // 返回边的个数
//
//    // 向图中添加一个边
//    public void addEdge(int v, int w) {
//
//        assert v >= 0 && v < n;
//        assert w >= 0 && w < n;
//
//        if (hasEdge(v, w))
//            return;
//
//        // 连接 v 和 w
//        g[v][w] = true;
//        if (!directed)
//            g[w][v] = true;
//
//        //  边数 ++
//        m++;
//    }
//
//    // 验证图中是否有从v到w的边
//    boolean hasEdge(int v, int w) {
//        assert v >= 0 && v < n;
//        assert w >= 0 && w < n;
//        return g[v][w];
//    }
//
//    // 返回图中一个顶点的所有邻边
//    // 由于java使用引用机制,返回一个Vector不会带来额外开销,
//    public Iterable<Integer> adj(int v) {
//            assert v >= 0 && v < n;
//            Vector<Integer> adjV = new Vector<Integer>();
//            for(int i = 0 ; i < n ; i ++ )
//            if( g[v][i] )
//            adjV.add(i);
//            return adjV;
//            }
//}


import java.util.ArrayList;
import java.util.List;

// 使用 邻接矩阵 表示 稠密图
public class DenseGraph{
    private int n;  // 图中的节点数
    private int m;  // 图中的边数
    private boolean[][] g;  // 邻接矩阵g
    private boolean directed;   // 是否为有向图

    public DenseGraph(int n, boolean directed){
        this.n = n;     // 初始化图中的节点数量
        this.m = 0;     // 图中边(edge)的数量初始化为0
        this.directed = directed;
        g = new boolean[n][n];      // 邻接矩阵 g 初始化为一个 n*n 的二维矩阵
                                // 索引代表图中的节点,g中存储的值为 节点是否有边
    }

    // 返回图中边的数量
    public int E(){
        return m;
    }

    // 返回图中节点的数量
    public int V(){
        return n;
    }

    // 在图中指定的两节点之间加边
    public void addEdge(int v, int w){
        if (!hasEdge(v, w)){

            // 连接[v][w]
            g[v][w] = true;

            // 无向图
            if (!directed)
                g[w][v] = true;

            // 图中边的数量+1
            m++;
        }
    }

    // 判断两节点之间是否有边
    private boolean hasEdge(int v, int w){
        return g[v][w];
    }

    // 返回所有 节点 v 的 邻接节点
    public Iterable<Integer> adjacentNode(int v){
        // adjacentL 用于存储 v 的邻接节点
        List<Integer> adjacentL = new ArrayList<>();
        // 找到所有与 v 邻接的节点,将其加入 adjacentL 中
        for (int i = 0; i < n;i++){
            if (g[v][i])
                adjacentL.add(i);
        }
        return adjacentL;
    }
}
作者:HeatDeath 发表于2017/11/16 23:48:53 原文链接
阅读:46 评论:0 查看评论

CentOS下配置sendmail外部邮箱

$
0
0

这里写图片描述

Sendmail是linux/unix下广泛被使用的一款邮件服务器,这篇文章将会介绍如何在centos7上安装和设定邮箱以便能够正常发送邮件,由于本地邮箱会被大部分邮件服务器认定为垃圾邮件甚至直接拦截,本文以163邮箱为例介绍一下如何使用以及一些常见的问题。

安装

项目 说明 安装命令
sendmail sendmail服务器 yum install sendmail
mailx 邮件发送服务 yum install mailx

安装结果确认

[root@angular ~]# rpm -qa |egrep 'sendmail|mailx'
sendmail-8.14.7-5.el7.x86_64
mailx-12.5-16.el7.x86_64
[root@angular ~]# 

邮件设定

设定/etc/hosts

由于shendmail会从/etc/hosts中确认domain name和host name,请将/etc/hosts中的配置信息加上,比如:

[root@angular ~]# grep angular /etc/hosts
192.168.163.151 angular.com angular
[root@angular ~]# 

常见问题:
此处如不设定,启动sendmail服务时会提示如下问题:

angular sendmail[44298]: My unqualified host name (angular) unknown; sleeping for retry
angular sendmail[44298]: unable to qualify my own domain name (angular) -- using short name

注意hostname的修改往往也会是sendmail不能正常动作的元凶,所以对机器的设定无比考虑到影响。

设定/etc/sysconfig/network

因为本文需要通过外部163的信箱进行发送,可以做如下设定

[root@angular ~]# cat /etc/sysconfig/network
# Created by anaconda
hostname mail.163.com
[root@angular ~]# 

常见问题:
此处如不设定,发送mail时一般会提示如下问题:

smtp-server: 535 Error: authentication failed

设定/etc/mail.rc

将/etc/mail.rc中添加如下信息, 使用smtp方式进行验证。

# Set from address and smtp domain
set from=xxxxxxxx@163.com smtp=smtp.163.com

# Set Smtp authentication 
set smtp-auth-user=xxxxxx@163.com smtp-auth-password=xxxx smtp-auth=login

常见问题:
此处出现的可能性问题较多,比如邮箱写错,空格问题,密码写错等等, 比如密码写错时会提示如下信息:

smtp-server: 535 Error: authentication failed

注意:密码修改该之后,一般不用重启sendmail服务即可起作用,所以修改的时候注意影响。
另外请注意各种邮箱不同一般设定也会有所不同,比如上述密码,163的邮箱不是登陆密码,而是授权码,需要在登陆邮箱在服务器侧设定,发送服务很多时候根据邮箱的不同设定方法有所不同,千万注意。

验证

发送邮件

使用下面简单的mail命令即可发送一封信给liumiaocn@outlook.com

项目 说明
From mail.rc中设定的邮箱
To liumiaocn@outlook.com
Title Greeting from liumiaocn
Message Hello, this is a test mail
[root@angular ~]# echo "Hello, this is a test mail" |mail -s "Greeting from liumiaocn" liumiaocn@outlook.com
[root@angular ~]# 

接收确认

这里写图片描述

问题追踪

日志文件

碰到问题,建议确认日志文件的信息

日志文件:/var/log/maillog

sendmail的debug模式

使用sendmail的debug模式,可以更好的逐步排查问题:

使用方式:sendmail -bt -d

[root@angular ~]# sendmail -bt -d
Version 8.14.7
 Compiled with: DNSMAP HESIOD HES_GETMAILHOST LDAPMAP LOG MAP_REGEX
        MATCHGECOS MILTER MIME7TO8 MIME8TO7 NAMED_BIND NETINET NETINET6
        NETUNIX NEWDB NIS PIPELINING SASLv2 SCANF SOCKETMAP STARTTLS
        TCPWRAPPERS USERDB USE_LDAP_INIT
getla(): 0.09
setoption SevenBitInput (7)=False
setoption AliasWait (a)=10
setoption AliasFile (A)=/etc/aliases
setoption MinFreeBlocks (b)=100
setoption BlankSub (B)=.
setoption HoldExpensive (c)=False
setoption DeliveryMode (d)=background
setoption TempFileMode (F)=0600
setoption HelpFile (H)=/etc/mail/helpfile
setoption SendMimeErrors (j)=True
setoption ForwardPath (J)= 0x81 z/.forward. 0x81 w: 0x81 z/.forward
setoption ConnectionCacheSize (k)=2
setoption ConnectionCacheTimeout (K)=5m
setoption UseErrorsTo (l)=False
setoption LogLevel (L)=9
setoption CheckAliases (n)=False
setoption OldStyleHeaders (o)=True
setoption DaemonPortOptions (O)=Port=smtp,Addr=127.0.0.1, Name=MTA
Daemon MTA flags: 
setoption PrivacyOptions (p)=authwarnings,novrfy,noexpn,restrictqrun
setoption QueueDirectory (Q)=/var/spool/mqueue
setoption Timeout (r).connect=1m
setoption Timeout (r).ident=0
setoption Timeout (r).queuereturn=5d
setoption Timeout (r).queuewarn=4h
setoption SuperSafe (s)=True
setoption StatusFile (S)=/var/log/mail/statistics
setoption DefaultUser (u)=8:12
setoption UserDatabaseSpec (U)=/etc/mail/userdb.db
setoption TryNullMXList (w)=True
setoption SmtpGreetingMessage (0x90)= 0x81 j Sendmail  0x81 v/ 0x81 Z;  0x81 b
setoption UnixFromLine (0x91)=From  0x81 g  0x81 d
setoption OperatorChars (0x92)=.:%@!^/[]+
setoption DontProbeInterfaces (0xa1)=True
setoption AuthOptions (0xbd)=A
drop_privileges(1): Real[UG]id=0:0, get[ug]id=0:0, gete[ug]id=0:51, RunAs[UG]id=0:0
getauthinfo: root@localhost

============ SYSTEM IDENTITY (after readcf) ============
      (short domain name) $w = angular
  (canonical domain name) $j = angular.com
         (subdomain name) $m = com
              (node name) $k = angular
========================================================

setoption HoldExpensive (c)=F
setoption DeliveryMode (d)=
assign_queueid: assigned id vAGMmR3I050207, e=0x7f6a6a982aa0
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
>

总结

这篇文章介绍了sendmail的安装和设定方法,以及常见的问题和解决方法。

作者:liumiaocn 发表于2017/11/17 6:19:43 原文链接
阅读:48 评论:0 查看评论

阅读源码的意义与方法

$
0
0

此系列文章在 https://github.com/mzlogin/rtfsc-android 集中更新发布,欢迎感兴趣的童鞋们关注。

本篇原始链接 https://github.com/mzlogin/rtfsc-android/blob/master/0x002-methods-and-meaning.md

思索了这两个问题良久,也去知乎找了一些相关话题的问答,但并没有标准答案。所以,我这里也只是记录一些我对此的看法,也许会随着 RTFSC 阅历的丰富而发生变化,我会记录更新于 https://github.com/mzlogin/rtfsc-android

意义

在我看来,阅读源码的意义在于学习优秀的「套路」。

这里的「套路」所指范围很广,大到架构设计,小到可取的命名风格,还有设计模式、实现某类功能使用到的数据结构和算法等等。所谓高手,其实就是能比大部分人更早更快地掌握套路并熟练运用之人。

埋头在自己的天地里耕芸固然也能逐渐进步和成长,但总会有时候会遇到一些场景,你苦思良久也无法做出良好的设计,总会有一些时候,纠结如何为一个变量命名让你停下飞速敲击的手指。这些令你为难的场景,先贤们也许早就遇到过,并且给出了优雅的解决方案。看优秀的源码的时候,将这样的场景与对应的方案收入囊中,或者仅仅在脑中留下一个印象也好,以便在需要的时候,你的武器库里总能掏出一把称手的家伙来。

一些方法

不应该这样

不应该漫无目的地随手拿起一分源码,试图去通读。这一方面会过目即忘无所收获,另一方面会枯燥得让你迅速从着手到放弃。学习的方式有很多种,阅读源码并不一定是最适合你当前的情况的。

应该这样

  1. 精心挑选要阅读的源码项目。

    这最好是与你的编程语言、你的工作内容、你的兴趣所在相关的,这样才能更切实地感受到阅读源码给你带来的益处,更有动力继续。

  2. 如果你想学习的知识点有官方文档,先看文档再看源码。

    直接从源码着手,搞清楚原理固然是好,但是源码有可能是难啃的,先熟悉官方提供给所有人看的文档,能较为平滑地对这方面的知识先有个大概的了解,然后再结合源码去深入。

  3. 提出具体的问题,然后带着问题到源码中找答案。

    比如在使用 Toast 的过程中,你可能会想到一些问题:Toast.makeText(...).show() 时发生了什么?Toast 能不能在非 UI 线程调用?能不能自定义 Toast 布局?诸如此类。在源码中探寻完你想要的答案,你的目的也就达到了。

  4. 从一些共性层面入手。

    大部分的程序里都会使用到的东西,比如线程模型、UI 组织结构、任务调度方式等等。针对某一个方面去了解,比漫无目的要有效率得多。

  5. 最好能够编译运行起来。

    如果一份代码你只能看不能跑,那可能读到一些地方你只能猜这个地方的数据值和跳转结构是怎么样的,而很有可能你猜的是错的。但如果你能编译运行,那在需要的时候你可以修改,加日志等等来更好地观察和验证你的想法,得到正确的理解。

  6. 做一些笔记。

    一方面是将你的学习成果保留下来,方便随时查阅,毕竟只凭脑子记忆是不靠谱的;另一方面在学习的过程中,也能帮助理解。

一些小技巧

这部分是在撰写本系列的过程中,发现和收集的一些个人觉得比较有用的小技巧,不断更新中……

逻辑追踪篇

  1. 查看符号、关键字符串被引用和出现的地方;

  2. 根据方法调用一层一层追踪;

  3. 使用 git blame 查看关键代码行的提交日志,里面也许包含有用的信息;

  4. 形如 IXxxManager 这类接口的实现类要么是 XxxManagerService,要么是 XxxManagerImpl;

欢迎关注我的微信公众号,接收我的 Android 源码分析心得。

作者:mzlogin 发表于2017/11/17 8:13:12 原文链接
阅读:54 评论:0 查看评论

pytorch学习笔记(十五):pytorch 源码编译碰到的坑总结

$
0
0

2017.11.17

最近打算学习一下 pytorch 源码,所以按照官网的教程从头编译了一下 pytorch 。在编译的过程中,碰到了两个坑,在这里记录一下。

  • 第一个错误
CMakeFiles/Makefile2:264: recipe for target 'src/ATen/test/CMakeFiles/scalar_test.dir/all' failed
make[1]: *** [src/ATen/test/CMakeFiles/scalar_test.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2
解决方法是:(由于我是 ubuntu16.04 编译的, gcc 默认的版本是 5.4,但是用 4.9 编译就不会有问题)
sudo apt install gcc-4.9 g++-4.9
export CC="gcc-4.9"
export CXX="g++-4.9"
# change to pytorch directory
python setup.py clean
python setup.py install
  • 第二个错误:(编译安装成功后, import torch 时报这个错)
libstdc++.so.6: version `GLIBCXX_3.4.21' not found
解决方法:
conda install libgcc 
然后再 import 就没问题了
  • 第三个错误(编译安装成功后,import torch 时报的错)
ModuleNotFoundError: No module named 'torch._C'
这个错误是 因为 我直接在 `pytorch/` 源码路径下打开的 `ipython`。 `cd` 出来就好了
the problem is that you have a folder called torch in the same directory which is being picked up. Do this: cd .. (to change directory), and then start python and import torch, it should work.
作者:u012436149 发表于2017/11/17 9:10:19 原文链接
阅读:2 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>