概述 本文主要介绍:如何在Android端(手机)利用微软Remote Desktop Client应用远程连接Windows服务器。
Remote Desktop Client是微软旗下一款非常实用的远程桌面客户端软件,也是一款类似于Windows资源管理器的树视图中管理远程桌面,它适用于常用协议RDP,VNC和Hyper-V,通过此连接不需要提升的管理权限,即可让你访问另一台计算机的文件网络资源和应用程序,而且避免了高复杂度和多种配置选项就能简单、有效地安排远程桌面。
步骤 1、下载Microsoft Remote Desktop Client应用。有些市场(比如华为应用市场)里好像找不到这个应用,我是在PC端360手机助手中找到这个应用的。
2、 在手机上安装应用。
3、打开应用,点击右上角的“+”号,选择Desktop。
4、 点击Desktop后会弹出Desktop Detection窗口。如果我们想要登录的桌面不在列表内,我们可以选择手动添加(ADD MANUALLY)。
5、在PC name中填写服务器IP地址,并在User name右方点选下拉菜单,选择Add user account。
6、在Add user account界面填写用户名与密码并保存。
7、远程桌面添加完毕,如下图所示。
8、点击后即可登录远程桌面,如下图所示。
使用体会:在手机上登录Windows平台,肯定不如PC上顺手,使用效率有点低。
如有其他类似功能应用,请在评论区留言,在下不胜感激。
题目描述 有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶有多少种不同方式。
输入输出格式 输入格式:
两个正整数N,K。
输出格式:
一个正整数,为不同方式数,由于答案可能很大,你需要输出ans \bmod 100003后的结果。
输入输出样例 输入样例#1: 复制
5 2 输出样例#1: 复制
8 #include<stdio.h> #define N 100003 long long a[100001]; int main(){ int n,k; scanf("%d %d",&n,&k); a[0]=a[1]=1; for(int i=2;i<=n;i++){ if(i<=k) a[i]=a[i-1]*2%N; //这是神马递推式,自己体会 else { a[i]=a[i-1]*2-a[i-k-1]; a[i]%=N; } } printf("%lld\n",(a[n]+N)%N); //这里如果a[n]<0;就得加上N;我也不是为啥 return 0; }
ADO是ActiveX Data Objects
参考:https://blog.csdn.net/xzsfg6825/article/details/80047946
记录集的open()方法的原型是这样的:
HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection,enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options )
使用方法:_RecordsetPtr m_Rs = NULL; m_Rs->Open(...);
Execute 方法可执行指定查询、SQL 语句、存储过程或提供者特有的文本。返回的 Recordset 对象始终是只读的、仅向前的游标。
CString sql = "select * from test_tb";
m_Rs = theApp.m_pCon->Execute((_bstr_t)sql,NULL,adCmdText);返回的 Recordset 对象始终是只读的、仅向前的游标。不能使用MoveLast()和MovePrevious(),可以使用MoveNext()。
CString sql = "delete from test_tb where id=0";
theApp.m_pCon->Execute((_bstr_t)sql,NULL,adCmdText);
CursorTypeEnum
{
adOpenUnspecified = -1,
adOpenForwardOnly = 0, adOpenKeyset = 1, adOpenDynamic = 2, adOpenStatic = 3
import numpy as np from collections import Counter # 方法一 data = np.array([1,1,1,2, 2, 3, 4, 4,4,4]) d = Counter(data) d_s = sorted(d.items(),key=lambda x:x[1],reverse=True) print(f'这个值:{d_s[0][0]}出现的次数最多,为{d_s[0][1]}次') # 方法二 mask = np.unique(data) tmp = [] for v in mask: tmp.append(np.sum(data==v)) ts = np.max(tmp) max_v = mask[np.argmax(tmp)] print(f'这个值:{max_v}出现的次数最多,为{ts}次') 第一种方法调用时候麻烦,第二种方法相对简单。
struts2工作原理
1、tomcat启动,会先去读取web.xml文件;然后会去初始化struts2核心过滤器StrutsPrepareAndExecuteFilter,在该过滤器中第一次会调用过滤器中的init方法进行初始化,而初始化方法中就有一个对象,Dispatcher对象,该对象会去读取并解析struts2.xml,struts-default.xml等文件。
2、客户端向服务器发送请求,服务器将请求转交给struts2核心过滤器,该过滤器将请求和struts.xml文件中的package节点中的namespace的属性值加上action的name属性值相匹配;如果匹配,则创建action代理类,并创建action请求对象中对应的拦截器,形成一个拦截器链,执行完Interceptor链中所有的拦截器后,才会执行Action类中默认处理方法execute()。
3、struts2根据处理方法返回的结果字符串和struts.xml文件中对应的result节点的值去匹配,匹配完之后,根据struts2提供的模板生成页面,将其处理结果生成一个一个页面,存入response中,然后又按之前经过拦截器相反的顺序,将响应信息传递给前端页面进行显示。
获取页面中的值:
1、属性驱动,直接在action类中编写属性,提供get,set方。在action类中的属性名和jsp页面中请求的name保持一致。
2、模型驱动,action类实现ModelDriven<对应表单属性的实体类>,实现getModel()方法,在该方法中显示的new一个实体类并返回。注:该对象在访问Action类的时候,这些组件全部会自动的被struts2的过滤器,拦截器注入数据进去。
3、通过获取request,response等这些对象来获取页面请求的数据。
文件的上传和下载:
上传:
1、在struts2中想要使用文件上传和下载的功能需要导入额外的apache的jar包。
2、设置form表单的表单提交方式为enctype=“multipart/form-data”,然后表单提交方式为post。
3、在action处理方法中设置设置三个属性,第一个,File 变量名为表单的input框的文件上传name属性值,第二个,表单的input框的文件上传name属性值加上ContentType,第三个,表单的input框的文件上传name属性值加上FileName,因为在strust2中的FieluploadInterceptor拦截器中这三个名字就是这样存入值栈的;如果不同名字的话,则会出现属性不能自动注入的问题。
在action类中处理文件就可以了,可以通过原生的IO流将内容写入到tomcat服务器中,也可以使用apache提供的工具包中的**FileUtils.copyFile()**将文件上传。
4、在struts2.xml文件中配置处理文件上传的action的配置信息。
例如:
<action name="uploadAction" class="com.ztkj.action.UploadAction"> <result name="success">success.jsp</result> <interceptor-ref name="defaultStack"/> <interceptor-ref name="fileUpload"> <!--这两个param名字和fileUpload拦截器中的属性名是一致的--> <param name="maximumSize">800000</param> <param name="allowedTypes">text/plain,image/jpeg,image/png</param> </interceptor-ref> </action> 下载
1、在actino类中创建一个InputStream属性,然后提供get和set方法。既然客户端想要下载一个文件,那肯定这个文件是服务器中所存在的文件名,action类获取到客户端请求的文件名,然后就相对应的获取到了该文件所对应再服务器端的文件路径,通过该路径就可以创建一个File对象,然后创建出InputStream对象。
2、再struts2.xml文件中配置,result的type类型为stream,设置响应的参数因为stream在后台实际上对应的也是一个拦截器,而拦截器中的处理实际上就是,将inputStream中的数据读取出来,然后将其写入到response中。而前端页面就可以直接获取了。这也是为什么这里需要传一个is,这个is就是action类中的一个InputStream输入流。
注意:前端的页面可以直接通过<img 标签中的src属性直接访问该action,然后直接显示出来。img标签的src底层应该也是做了一定的处理。
<action name="down" class="com.ztkj.action.DownAction"> <result name="success" type="stream"> <param name="contentDisposition">attachment;fileName=${fileName}</param> <param name="inputName">is</param> </result> <interceptor-ref name="defaultStack"/> </action> ajxa请求:
1、struts2处理ajax请求需要使用到额外的jar包,例如:json-lib.jar。
2、在action中直接使用属性驱动或者ModelDriven模型驱动,获取前端传递过来的ajax请求参数,action处理方法处理业务,返回一个字符串。
3、在struts2.xml配置文件设置package的extends这里不能设置成struts-default,因为在struts2的默认这个package中没有处理ajax的拦截器,因此要使用json-default,然后配置result节点信息,type为json当然这里其实在底层也是对应了一个json的interceptor拦截器,其内部就是去处理这些传递过去的java数据,然后将其转成json对象,然后写入response中。需要注意的是这里需要配置一个param节点name为root,value值为action处理方法中的结果数据。
例如:
<package name="ajax" namespace="/" extends="json-default"> <action name="ajaxAction" class="com.ztkj.action.AjaxAction"> <result name="success" type="json"> <!--json所对应的拦截器中有一个属性root,接收action类处理方法传递过去的数据--> <param name="
一、概述
蓝牙是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换。最多可以同时和7个其它蓝牙设备建立连接,进行通信。蓝牙可分为两大类:传统蓝牙(蓝牙3.0规范之前),低功耗蓝牙(蓝牙4.0规范之后)。
Android 从4.3版本(API Level 18)开始支持低功耗蓝牙Bluetooth Low Energy(BLE)通信。Android提供了相应的 API, 应用程序通过这些 API 可以实现 蓝牙设备扫描、配对、连接、传输数据等功能。
二、Android BLE API几个重要类
1、BluetoothAdapter
本地的蓝牙适配器。是所有蓝牙交互操作的入口点。通过这个类可以发现其他蓝牙设备,查询已配对的设备列表,使用一个已知的MAC地址来实例化一个BluetoothDevice,以及创建一个BluetoothServerSocket来为监听与其他设备的通信。
2、BluetoothDevice
远程蓝牙设备。使用这个类来请求一个与远程设备的BluetoothSocket连接,或者查询关于设备名称、地址、类和连接状态等设备信息。
3、BluetoothSocket
代表一个蓝牙socket的接口(和TCP Socket类似)。这是一个连接点,它允许一个应用与其他蓝牙设备通过InputStream和OutputStream交换数据。
4、BluetoothServerSocket
代表一个开放的服务器socket,它监听接受的请求(与TCP ServerSocket类似)。为了连接两台Android设备,一个设备必须使用这个类开启一个服务器socket。当一个远程蓝牙设备开始一个和该设备的连接请求,BluetoothServerSocket将会返回一个已连接的BluetoothSocket,接受该连接。
三、蓝牙开发
1、流程
2、开启权限
<uses-permission android:name="android.permission.BLUETOOTH"/> //开启蓝牙时,mBluetoothAdapter.enable()需要以下权限 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 3、开启蓝牙
public void isBluetoothEnable() { //获取蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter != null){ // 蓝牙已打开 if (mBluetoothAdapter.isEnabled()){ }else{//未打开则开启,此处可以通过弹框提示来提示用户开启 mBluetoothAdapter.enable() } } } 4、搜索附近蓝牙设备
/** * 注册搜索蓝牙设备的广播 */ private void startDiscovery() { IntentFilter filter = new IntentFilter(BluetoothDevice.
定义vector对象的常用方法:
初始化vector对象的方法vector<T> v1v1是一个空vector,它潜在的元素是T类型,执行默认初始化vector<T> v2(v1)v2中包含v1所有元素的副本vector<T> v3(n,val)v3包含了n个重复的元素,每个元素的值都是valvector<T> v4(n)v4包含了n个重复地执行了值初始化的对象vector<T> v5{a,b,c...}v5包含了初始值个数的元素,每个元素被赋予相应的初始值vector<T> v5={a,b,c...}等价于vector<T> v5{a,b,c...} 默认初始化vector对象,创建一个指定类型空vector:
vector<string> svec;//默认初始化,svec不含任何元素 允许把一个vector对象的元素拷贝给另外一个vector对象:
vector<int> ivec;//初始状态为空 vector<int> ivec2(ivec);//把ivec的元素拷贝给ivec2 vector<int> ivec3 = ivec;//把ivec的元素拷贝给ivec3 vector<string> svec(ivec2);//错误:sevc的元素是string对象,不是int 列表初始化vector对象
列表初始化,用花括号括起来的0个或多个初始值被赋予给vector对象:
vector<string> articles = {"a","an","the"}; 提供的是初始元素值的列表,只能把初始值都放在花括号里进行列表初始化,而不能放在圆括号里:
vector<string> v1 = { "a","an","the" };//列表初始化 vector<string> v2=("a","an","the");//错误 创建指定数量的元素
vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象:
vector<int> ivec(10,-1);//10个int类型的元素,每个都被初始化为-1 vector<string> svec(10, "hi");//10个string类型的元素,每个都被初始化为"hi!" 值初始化
只提供vector对象容纳的元素数量而略去初始值,库会创建一个值初始化的元素初值,并把它赋给容器中的所有元素,初值由vector对象中元素的类型决定:
vector<int> ivec(10);//10个元素,每个都初始化为0 vector<string> svec(10);//10个元素,每个都是空string对象 特殊限制:
如果vector中元素的类型不支持默认初始化,就必须提供初始的元素值。如果只提供了元素的数量而没有设定初始值,只能使用直接初始化: vector<int> vi = 10;//错误:必须使用直接初始化的形式指定向量大小 本意是想创建含有10个值初始化了的元素的vector对象,而非把数字10“拷贝”到vector中,此时不宜使用拷贝初始化。
列表初始值还是元素数量?
vector<int> v1(10);//v1有10个元素,每个的值都是10 vector<int> v2{ 10 };//v2有1个元素,该元素的值是10 vector<int> v3(10, 1);//v3有10个元素,每个元素的值都是1 vector<int> v4{ 10,1 };//v4有2个元素,值分别是10和1 如果用的是圆括号,提供的值是用来构造vector对象的。如果用的是花括号,列表初始化vector对象。初始化过程会尽可能把花括号内的值当成是元素初始值的列表来处理,只有在无法执行列表初始化时才会考虑其他初始化方式: vector<string> v5{"
axios.post('/api',{ // 传参 }, { responseType:'blob' // 设置响应数据类型 }) .then(res=>{ if (res.status == 200) { let url = window.URL.createObjectURL(new Blob([res.data])) let link= document.createElement('a') link.style.display='none' link.href=url link.setAttribute('download', fileName) // 自定义下载文件名(如exemple.txt) document.body.appendChild(link) link.click() } }) 源码
elasticsearch的curl命令如何使用,点击查看: curl增删改查操作ES elasticsearch的get、put、post、delete如何使用,点击查看: elasticsearch常用的文档命令
查看es的集群状态
http://IP:9200/_cat/health?v
注: IP指es集群某个ip地址, ?v表示格式化输出
查看es集群节点列表
http://IP:9200/_cat/nodes?v
查看es集群所有索引及数据大小
http://IP:9200/_cat/indices?v
查看单个索引结构信息
http://IP:9200/indexName?pretty=true
注: indexName是索引名字, pretty=true表示格式化输出
全词搜索
http://IP:9200/indexName/_search?pretty=true
精准搜索
http://IP:9200/indexName/_search?q=123&pretty=true
注: ?q=123表示搜索123
模糊搜索
http://IP:9200/indexName/_search?q=*123*pretty=true
(code=exited, status=1/FAILURE),
lock file "postmaster.pid" already exists,Failed to start PostgreSQL 11 database server.
第一步:
去postgresql的安装目录删除postmaster.pid该文件
第二步:
删除后重启postgresql
service postgresql-11 restart
第三步:
查看 postgresql的状态
service postgresql-11 status
题目描述 请实现两个函数,分别用来序列化和反序列化二叉树。
示例 二叉树序列化 {8,4,#,3,#,2} 反序列化 序列化指的是遍历二叉树为字符串;反序列化指的是依据字符串重新构造成二叉树。下面两种方法,使用ArrayList层次遍历是完全符合二叉树层次序列化示例,即示例输入。而递归的方法不是,这题的输入输出要求并不明确,可能序列化与反序列化函数的结果能互相匹配就能AC。
解题思路—使用ArrayList层次遍历:序列化时使用ArrayList依次保存树的每一层结点,若结点为空,则保存"#,",最后得到结果{8,4,#,3,#,2,#,#,#,}。为了完全匹配示例输入{8,4,#,3,#,2},最后要将多余的"#,"删除。反序列化时,使用",“分割字符串,同样使用ArrayList依次保存生成的结点,同时设置标志位par来记录当前父结点,遍历字符串时,每次遍历两个字节。因为只要当前父结点存在,字符串如果没有遍历完,那就必然有它的左右子结点(如果左子结点处于字符串最后一位,那么右子结点肯定是null,在序列化时被当作多余的”#,“删除了),每次遍历完两个字符后,par++,直至字符串遍历结束。
解题思路—递归:这个方法非常简洁,但是它的序列化结果并不是常规的层次遍历,以示例中的二叉树为例,递归得到的序列化为{8,4,3,2,#,#,#,#,#,}。序列化使用了前序遍历,从根结点开始保存,若结点为null,则保存”#,"。反序列化时,也是前序遍历的思想,将序列化结果按顺序放置左右结点。虽然递归的结果不符合标准输入,但是序列化与反序列化函数的结果能互相匹配应该就能AC。
Java解题—使用ArrayList层次遍历 /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ import java.util.ArrayList; public class Solution { public String Serialize(TreeNode root) { if(root==null) return null; StringBuilder str = new StringBuilder(); ArrayList<TreeNode> list = new ArrayList<>(); list.add(root); str.append(root.val+","); while(!list.isEmpty()){ TreeNode node = list.get(0); if(node.left!=null){ str.
有时候我们在使用pycharm的时候,想创建py文件的时候,自动添加文件头注释,包括创建时间,作者,文件名称等,怎么操作呢,下面来分享一下方法
如果对你有用的话,关注我吧
1.打开pycharm,点击file-->settings 2.Editor-->Code Style-->File and Code Templates-->Python Script 3.python script中的代码 #!/usr/bin/env python # coding:utf-8 """ Name : ${NAME}.py Author : 写上自己的名字 Contect : 邮箱地址 Time : ${DATE} ${TIME} Desc: """ 4.我们来创建一个脚本,来看看效果
文章目录 准备工作什么是内核模块编写 hello.c模块编译相关指令测试结果模块加载模块卸载 准备工作 在进行以下操作前,首先我准备了一台电脑,并且安装了虚拟机,系统是Ubuntu16.04。如果是开发板,那么需要安装交叉编译器,但是目前我只在虚拟机的Ubuntu16.04系统里完成驱动模块的加载和卸载,实现了一个最最简单的内核模块,并且通过这个最简单的驱动,学习最基本的概念。
什么是内核模块 模块是可以根据实际需要可以动态加载和卸载到内核中的代码。它们扩展了内核的功能,而无需重启系统,就可以进行模块加载,并工作。例如,一种类型的模块是设备驱动程序,它允许内核访问连接到系统的硬件。没有模块,我们必须构建整个内核并将新功能直接添加到内核映像中。除了拥有更大的内核之外,这还有一个缺点,就是每次我们想要新功能时都需要我们重新编译内核并烧录到设备。
编写 hello.c #include <linux/init.h> //所有模块都会需要这个头文件 #include <linux/module.h> //下面的宏需要 static int __init hello_init(void){ printk(KERN_INFO "module init success\n"); return 0; } static void __exit hello_exit(void){ printk(KERN_INFO "module exit success\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); //开源协议 MODULE_AUTHOR("作者"); MODULE_DESCRIPTION("功能描述"); 这是一个简单内核模块程序,可以动态加载和卸载。虽然没有实际的功能。
模块加载的时候系统会打印module init success\n
模块卸载的时候系统会打印module exit success\n
模块编译 obj-m := hello.o PWD := $(shell pwd) KVER := $(shell uname -r) KDIR :=/lib/modules/$(KVER)/build/ all: $(MAKE) -C $(KDIR) M=$(PWD) clean: rm -rf *.
Vector类底层其实就是一个Object数组,Vector类中的方法是支持同步(方法使用synchronized修饰)的
源码如下:
Vector类存储原理:
通过源码分析,发现在Vector类中有一个Object[]类型数组.
1):表面上把数据存储到Vector对象中,其实底层依然是把数据存储到Object数组中的.
2):我们发现该数组的元素类型是Object类型,意味着集合中只能存储任意类型的对象.
集合中只能存储对象,不能存储基本数据类型的值.
在Java5之前,必须对基本数据类型手动装箱.
如:v.addElement(Integer.valueOf(123));
从Java5开始支持自动装箱操作,代码.
如:v.addElement(123);其实底层依然是手动装箱.
注意:修改项目的编译级别到Java5或者Java5之上.
3):集合类中存储的对象,都存储的是对象的引用,而不是对象本身.
集合类的操作方法:
常用方法:
增加:
boolean add(Object e) 将指定元素添加到此向量的末尾,等价于addElement方法。 void add(int index, Object element) 在此向量的指定位置插入指定的元素。 boolean addAll(Collection c) :把c集合中的元素添加到当前集合对象中.
删除:
Object remove(int index) :删除指定索引位置的元素,并返回删除之后的元素.
boolean remove(Object o):删除指定的元素.
boolean removeAll(Collection c):从此集合中移除包含在指定 集合c中的所有元素。 boolean retainAll(Collection c):在此集合中仅保留包含在指定 集合c中的元素,求两个集合的交集。 修改:
Object set(int index, Object element) :修改当前集合中指定索引位置的元素.返回被替换的旧的元素.
查询:
int size() :返回当前集合中存储几个元素.
boolean isEmpty():判断当前集合中元素个数是否为0. Object get(int index):查询指定索引位置的元素.
Object[] toArray():把集合对象转换为Object数组.
HashMap的实现原理:
1.基于哈希表(数组+链表+二叉树(红黑树))2.默认加载因子为0.75,默认数组大小是16,3.把对象储存到哈希表中,如何存储 ?把key对象通过hash()方法计算hash值,然后用这个hash值对数组长度取余(默认16)来决定该Key对象在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,jdk1.8后,当链表长度大于8时,链表将转换为红黑树结构存储。目的是为了取值时,提高效率,取值更快扩充原理:当数组的容量超过了75%,表示该数组需要扩充扩充的算法是:当前数组容量<<1(右移一位)(相当于*2),扩充一倍;缺点:扩充次数过多,会影响性能,每次扩充表示哈希表重新散列(重新计算每个对象的储存位置),在开发中要尽量减少扩充次数带来的性能问题。线程不安全,适合在单线程中使用
LinkedHashMap
LinkedHashMap是HashMap的子类,由于HashMap不能保证顺序恒久不变,此类使用了一个双重链表来维护元素添加顺序
Hashtable 基于哈希表实现默认数值大小为11,加载因子0.75扩充方式:原数组大小*2+1;原数组大小<<1+1线程安全的,用在多线程 import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * Map接口: * 1.键值对储存一组对象 * 2.Key保证唯一,不能重复,Value可以重复 * 3.具体的实现类:HashMap TreeMap Hashtable LinkedHashMap * * HashMap的实现原理: * 1.基于哈希表(数组+链表+二叉树(红黑树)) * 2.默认加载因子为0.75,默认数组大小是16, * 3.把对象储存到哈希表中,如何存储 ? * 把key对象通过hash()方法计算hash值,然后用这个hash值对数组长度取余(默认16)来决定该Key对象 * 在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,jdk1.8后,当链表长度大于8时,链表将 * 转换为红黑树结构存储。 * 目的是为了取值时,提高效率,取值更快 * 扩充原理:当数组的容量超过了75%,表示该数组需要扩充 * 扩充的算法是:当前数组容量<<1(右移一位)(相当于*2),扩充一倍;缺点:扩充次数过多,会影响性能,每次扩充表示哈希表重新散列 * (重新计算每个对象的储存位置),在开发中要尽量减少扩充次数带来的性能问题。 * 5.线程不安全,适合在单线程中使用 * * */ public class MapDemo { /** * LinkedHashMap是HashMap的子类,由于HashMap不能保证顺序恒久不变,此类使用了一个双重链表来维护元素添加顺序 */ private static void HashMap(){ Map<String,String> table=new LinkedHashMap<>(); table.
之前曾经总结过关于SLAM的资源,但感觉有些零零散散,在此进行补充与完善,分享给大家。
SLAM,全称叫做Simultaneous Localization and Mapping,中文叫做同时定位与建图。
二 干货
1.PnP算法简介与代码解析(视频+PPT课件+代码解析)
链接https://pan.baidu.com/s/1d9e0FaIvK_s8m1pMJvNXtg 密码:hf22
2.LeastSquare_and_gps_fusion(视频+PDF)
链接https://pan.baidu.com/s/1hi-fvkGwNM40esUueIDQzQ 密码:upcc
3.Scan Matching in 2D SLAM(视频+PPT)
链接https://pan.baidu.com/s/1TZkuqp428bQZpnGw5-SiZg 密码:xocd
4.LSD-SLAM深度解析(视频)
链接https://pan.baidu.com/s/1yKnrkiC-8LS0ahBN5r0UBA 密码:74br
5.非线性优化与g2o(视频+PPT)
链接https://pan.baidu.com/s/1E3HuhLLrkrMLZGf1ZyNDag 密码:n1oh
6.COP-SLAM - 杨俊(视频+PPT+其他)
链接https://pan.baidu.com/s/1dxm3xzBTyQ50WPkd0IyjQw 密码:4285
7.KinectFusion 和 ElasticFusion 三维重建方法 (视频+PDF)
https://pan.baidu.com/s/1cVlvM6bdDXZmqxnjxDeZAQ
密码:23ky
8.rosbridge的原理和应用-董超(视频+PPT)
https://pan.baidu.com/s/1Xgc4y8-C5OnHF0MPXj2D0w
密码:r5tl
9.优化与求解(视频+PDF)
链接https://pan.baidu.com/s/1wIjg38aOdav1pi-dwwhy9g 密码:kmoz
10.图像技术在AR中的实践(视频+PDF)
链接https://pan.baidu.com/s/1xGBYrShOcZcDFtKMXg7dlA 密码:ylik
11.激光SLAM(视频+PDF)
链接:https://pan.baidu.com/s/1KGsn8LfZzFxQNiI0f2aHtQ 密码:iw7y
12.双目视觉里程计(视频+课件+相关论文)
链接https://pan.baidu.com/s/1ckcc5pfmPgkMn9DxrCkVIg 密码:uj7l
13.MEMS IMU的入门与应用(视频+PPT)
链接https://pan.baidu.com/s/115ZXuku0fH6Rt-mKzusSVQ 密码:6s5z
14.IMU+动态背景消除(视频+PDF)
链接https://pan.baidu.com/s/1Ya36oenZpLS-6rTyAxEX2Q 密码:yrgu
15.视觉SLAM中的矩阵李群基础(视频+课件)
链接https://pan.baidu.com/s/1PqiwvyvGSJxx3yKSgeehDA 密码:0n30
16.TLS安全网络传输协议简介(视频+PDF)
链接:https://pan.baidu.com/s/1lwAd_yd5IuP7sU-Rb-JF-w 密码:g9ky
17.深度学习及应用-颜沁睿
链接https://pan.baidu.com/s/1G_uSO-xonvWb8jU_c4_J9Q 密码:9c8g
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:
class Box { double width; public: double length; friend void printWidth( Box box ); void setWidth( double wid ); }; 声明类 ClassTwo 的所有成员函数作为类 ClassOne 的友元,需要在类 ClassOne 的定义中放置如下声明: friend class ClassTwo; 请看下面的程序: #include <iostream> using namespace std; class Box { double width; public: friend void printWidth( Box box ); void setWidth( double wid ); }; // 成员函数定义 void Box::setWidth( double wid ) { width = wid; } // 请注意:printWidth() 不是任何类的成员函数 void printWidth( Box box ) { /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */ cout << "
这是我在学习中的一些笔记总结,包括闭包、作用域、原型等等常考热点,这些将以面试题的方式呈现给大家,全文分为 JS 基础、JS 高级、jQuery 和 vue 四部分,认真读完并且敲几遍代码,您定会受益匪浅,同时希望大家批评指正。 1. 闭包 1. 涉及面试题:什么是闭包? 闭包的定义其实很简单:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。
function A(){ let a=1; window.B=function(){ console.log(a) } } A(); B();//1复制代码 很多人对于闭包的解释可能是函数嵌套了函数,然后返回一个函数。其实这个解释是不完整的,就比如我上面这个例子就可以反驳这个观点。
在 JS 中,闭包存在的意义就是让我们可以间接访问函数内部的变量。
2. 经典面试题:循环中使用闭包解决`var `定义函数的问题; 需求:每隔一秒输出一个数字,从 0 - 5; for(var i=0;i<=5;i++){ setTimeout(function timer(){ console.log(i) },i*1000) } console.log(i)复制代码 输出结果:立即输出一个6,然后每隔一秒输出一个6;
首先因为 setTimeout 是个异步函数,所以会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。
解决办法有3种,
第一种是利用闭包的方式:
for(var i=0;i<=5;i++){ (function(j){ setTimeout(function timer(){ console.log(j) },j*1000) })(i) }复制代码 在上述代码中,我们首先使用了立即执行函数将 i 传入函数内部,这个时候值就被固定在了参数 j上面不会改变,当下次执行 timer 这个闭包的时候,就可以使用外部函数的变量 j,从而达到目的。
今天遇到Vue 使用 axios post请求后台数据时 404 使用postman 就能获取到 网上找了大半天 终于找到了解决方法,传送门:https://www.jianshu.com/p/b10454ed38ba
转载于:https://www.cnblogs.com/badake/p/10777113.html
随机游走 随机游走(Random Walk,缩写为 RW),是一种数学统计模型,它是一连串的轨迹所组成,其中每一次都是随机的。它能用来表示不规则的变动形式,如同一个人酒后乱步,所形成的随机过程记录。
1905年,由卡尔·皮尔逊首次提出。
随机游走的形式有:
马尔可夫链或马可夫过程醉汉走路(drunkard’s walk)莱维飞行(Lévy flight) 随机游走(random walk)矩阵可以看做是马尔科夫链的一种特例。
喝醉的酒鬼总能找到回家的路,喝醉的小鸟则可能永远也回不了家。
一维、二维随机游走过程中,只要时间足够长,我们最终总能回到出发点;
三维网格中随机游走,最终能回到出发点的概率只有大约 34%;
四维网格中随机游走,最终能回到出发点的概率是 19.3% ;
八维空间中,最终能回到出发点的概率只有 7.3% ;
定理是著名数学家波利亚(George Pólya)在 1921 年证明的。
物理意义 随机游走是现实生活中常见的一种模型:
气体分子的运动、滴入水中的墨水 、气味的扩散、醉汉行走轨迹、花粉的布朗运动、证券的涨跌、抛硬币…
物理学、化学:Random Walk是扩散过程的基础模型。统计领域:马尔可夫链蒙特卡罗,解决近似计算问题。信息检索: 早期搜索引擎如Yahoo使用的是关键字匹配技术,性能容易受到关键词频率的欺骗,所以搜索效果不是很好。
1998年Jon Kleinberg 提出了HITS算法,Sergey Brin 和 Larry Page 提出了 PageRank算法之后,搜索的正确率就得到了巨大的改观,这两种技术都是基于Random Walk。
经济学:证券的涨跌 Reference 维基百科火星十一郎数学中竟然还有这样的定理!
1.观察者模式的定义 工作让人头昏眼花
对于观察者模式,官方的定义是“用于定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。”,说穿了,就是对于对象的状态监控,将对象的状态改变变为信号,通过这个状态改变的信号,用于做别的事情。
而观察者模式,这个名字其实理解性不是很高,他还有另一个名字—发布/订阅模式(publish/subscribe)。这样就更便于理解了,观察者观察被观察者,每当被观察者发生状态改变,则会传递改变的信息到观察者(至于只是改变的信号,还是附带所改变的信息,根据实际情况而定),观察者得到信息后,记录被观察者改变的信息。对比到发布/订阅模式,就是观察者订阅了被观察者,每当被观察者有新的动向时,就会将变化发布给观察者,观察者继续加以处理或记录等操作。
2.观察者模式的类图 通过观察者模式的可以看到,这不是一个只面向抽象类的设计模式,在实例类ConreteObserver中,其拥有ConcreteSubject的成员。而在使用时,主要也是通过ConreteObserver实例观察类中实现后续的操作。
同时信息的传递函数Notify和更新函数Update都是无参的,代表着两者其实传递的是一个信号,得到该信号后ConcreteObserver类应该直接在其成员变量Subject类中读取相应的信息。
类图中的各个元素介绍如下:
Subject抽象类:这是被观察者类的抽象类,通常,其内部会定义一个成员变量/列表来存储其观察者的信息。其主要用于定义接口,比如增删观察者,传递信息等接口。;Observer抽象类:其为观察者类的抽象类,其用于定义接口,其中最为主要的就是Updata接口的声明,所有的观察者都必须要有Updata自己信息的函数;ConcreteSubject实例类:其继承自Subject抽象类,在实现已经声明的固有接口后,根据其实际情况可增加自己的成员变量与函数。ConcreteObserver实例类:其继承自Observer抽象类,在实现已经声明的固有接口后,根据其实际情况可增加自己的成员变量与函数。但其内部必须要有其所观察的观察者的成员变量(常为指针),通过调用该成员变量,获取所观察对象的内部数据的具体改变情况。 3.观察者模式的代码实现 本例的代码实现是参照Steins;Gate的世界观来写的,在该作中,冈部伦太郎作为世界线的唯一观测者而不断跳跃时空来改变过去/未来。由此,将世界World作为本例的Subject抽象类,而世界线WorldLine则作为本例的ConcreteSubject实例类。观测者类仍为Observer类,其中仅定义了接口Updata,世界线的观测者类WorldLine_Observer即为ConcreteObserver实例类,其内部存储了其所观测的世界线(是α还是β世界线),当世界线开始变动时,其内的Update函数将会被世界线的通知函数Notify所调用,然后观测者读取其内部成员变量(所储存的世界线)来得知当前的世界线是多少。
#include <iostream> #include <string> #include <list> using namespace std; class Observer { public: virtual void Update() = 0; }; class World { public: World() { m_observerlist.clear(); } virtual void Attach(Observer *observer) = 0; virtual void Delete(Observer *observer) = 0; virtual void Notify() = 0; protected: list<Observer*> m_observerlist; }; class WorldLine : public World { public: void Attach(Observer *observer) override { m_observerlist.
比如我的数据如下图所示,查询目的是查询出main重复的,并且保留main分组中score最大的一条数据,也参考了很多答案但是并不理想,后来在技术群里请教了一位大神 最后的sql贴出来:
select id, main, score from ( select id, score , main, if(@pmain = main, @rank:=@rank+1, @rank:=1) as rank, @pmain:=main from student order by main, score desc )tmp where rank = 1 sql提供者微信名:伍鲜 特此标明
Text := '<input style="cursor:pointer;" type="button" class="but_zhy" value="按钮" οnclick="ajaxRequest(MainForm.UniDBGrid1, ''Test'', [''param0=delete'']);" />';
procedure TMainForm.UniDBGrid1AjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings);
begin
if EventName = 'Test' then
begin
if Params['param0'].Value = 'delete' then
UniEdit1.Text := TimeToStr(now);
end;
end;
附着过程:
一、UE向MME发送Attach request请求:
接口:S1-MME UE发起附着请求消息以及网络选择指示给eNodeB:
1、InitialUEMessage消息:
Item 0:ENB-UE-S1AP-ID每个手机在s1上的控制面连接的enb端的标识。 (2)Item 1:
EPS attach type附着类型。
Type of identity:GUTI下是GUTI的组成,可以根据GUTI选择MME。
UE network capability:UE支持的业务和能力。
PDN type:PDN支持的IP类型;
Tracking area code(TAC):TAC标识;
Location Area Code (LAC):LAC标识;
Voice domain preference:支持的语音业务类型。
(3)Item 2:tAC TAC标识。
(4)Item 3: cell-ID E- UTRAN全球小区标识符。
(5)Item 4:RRC-Establishment-Cause。
2、eNodeB根据RRC参数中的旧的GUMMEI标识和选择网络指示得到MME。如果得不到MME,就由选择功能选择MME,对于同一个POOL中的MME,eNodeB中存有MME的权重。然后eNodeB将附着消息和UE所在小区的TAI+ECGI标识一起转发给新的MME。如果MME不认识UE,则MME发送标识请求给UE以请求IMSI。则UE使用包含IMSI的标识响应消息通知网络。
二、MME收到Attach Request消息后向HSS发送Authentication Information Request(IMSI),HSS响应Authentication Information Answer消息,携带EPS安全向量。
接口:S6a
1、Authentication Information Request消息:
Diameter中以AVP的形式存储用户信息:
AVP: Session-Id中含有MME的信息;
AVP: Auth-Session-State会话状态;
AVP: Origin-Host一台运行Diameter应用的请求服务主机;
AVP: Origin-Realm一组运行Diameter应用请求主机;
AVP: Destination-Realm一组Diameter应用服务主机;
AVP: User-Name主要是用户的IMSI;
AVP: Visited-PLMN-Id所属的PLMN信息;
AVP: Vendor-Specific-Application-Id中Auth-Application-Id表明接口类型;
android应用程序的编写是在java的基础上进行的,android为了更方便的在线程中操作Ui,延伸出了AsyncTask,因此如果在做android的应用开发的时候,如果需要用到与界面相关的线程的时候首选AsyncTask,如果线程主要用来处理数据,不参与界面操作的时候尽量用Thread线程,因为Thread较AsyncTask比有很多优点(参考javaAPI),另外如果在应用中需要启动多个线程的时候,也要使用Thread,它自带多线程处理。
总的来说,如果需要简单的操作Ui,AsyncTask更好一些。如果不操作UI或者后台线程比较复杂,Thread更好一些。
测试环境
# 环境一 Python 3.6.5 Scrapy==1.5.0 # 环境二 Python 2.7.5 Scrapy==1.1.2 一、命令行运行爬虫 1、编写爬虫文件 baidu.py
# -*- coding: utf-8 -*- from scrapy import Spider class BaiduSpider(Spider): name = 'baidu' start_urls = ['http://baidu.com/'] def parse(self, response): self.log("run baidu") 2、运行爬虫(2种方式)
# 运行爬虫 $ scrapy crawl baidu # 在没有创建项目的情况下运行爬虫 $ scrapy runspider baidu.py 二、文件中运行爬虫 1、cmdline方式运行爬虫
# -*- coding: utf-8 -*- from scrapy import cmdline, Spider class BaiduSpider(Spider): name = 'baidu' start_urls = ['http://baidu.com/'] def parse(self, response): self.
Vector(std::initializer_list<double>) //{1.2,12.3,111.2}
关键字virtual的意思是可能随后在其派生类中重新定义;含有纯虚函数的类称为抽象类;
Vector::Vector(Vector&& a):elem{a.elem},sz{a.sz}
{ a.elem = nullptr;
a.sz = 0;
}
//移动语义的关键在于:1:移动过来的对象要清零;2.要把移动的对象给当前对象;要令源对象处于可析构和赋值的状态。
y = std::move(x);
Vcetor(Vector&) = delete; // 抑制操作;删除默认的构造
typename另外一个作用为:使用嵌套依赖类型(nested depended name),如下所示:
class MyArray
{
public:
typedef int LengthType;
}
template<class T>
void MyMethod( T myarr )
{
typedef typename T::LengthType LengthType;
LengthType length = myarr.GetLength;
}
这个时候typename的作用就是告诉c++编译器,typename后面的字符串为一个类型名称,而不是成员函数或者成员变量,这个时候如果前面没有typename,编译器没有任何办法知道T::LengthType是一个类型还是一个成员名称(静态数据成员或者静态函数),所以编译不能够通过。
[&](int a){ return a < x; } // 返回bool;
using size_t = unsigned int;
using value_type = T;
小孙我自己很久之前就对金融市场交易很感兴趣,从三年前开始,便不断地学习和吸收交易方面的知识,包括最近发现的一个叫QR量化投资社区的不错的平台,也给了自己很多启发。结合最近的市场情况,心血来潮,在此就分享一篇自己最近学习的体会和经验。
最近股市波动不断,不论是同一个还是不同市场状态下,交易的操作方法上都是有共性的,任何人也都可以参与市场。这里小编我就给各位介绍一下投机者处理2019-03-20的市场的独门绝技 - 底部放量。
笔者先讲一下投机者是怎么样的一种定义:
投机者是一个人或一个实体,押注价格,预测会上涨或者下跌,因此通常具有高于平均水平的风险承受能力。尽管有人会说所有的投资都是投机行为,但一个公认的投机人买卖一种证券仅仅是为了从这种证券的价格波动中获得典型的短期利润。这种动机与更传统的投资者或套期保值者的动机存在显著差异。
市场中不乏具有良好参考价值的干货和观点,比如像《人工智能和股市三大猜想》中强调过的,不论是什么样的市场参与者,在不同的市场环境中存活下去并稳定赚钱,才是最重要的。比如这里要讲到的2019-03-20的市场。
根据截至到2019-03-20收盘时的数据可知,上证指数当日开盘3084.17,最高3102.52,最低3053.45,收盘于3090.64, 收盘价相较于前一天变动-0.01%;沪深300当日开盘3825.34,最高3855.15,最低3790.51,收盘于3835.44,收盘价相较于前一天变动0.04%;上证50当日开盘2799.33,最高2831.63,最低2787.28,收盘于2812.92,收盘价相较于前一天变动0.21%。
底部放量出现的三种走势:
第一种是放量上涨
既然股价处于长期低位中,那么绝大部分的筹码肯定已经被高高地套在上面,而且手拿资金准备买进该股的投资者也一定是凤毛麟角,因此出现大成交量的唯一理由就是残存主力的对倒,为了吸引市场资金的跟进。这里特别要说明的是,即使该股的基本面突然出现利好,放出的大量也很有可能是主力所为,因为好消息的出台并不会导致大量的高位套牢盘放血。如此一来,底部放量上涨一般都是盘中主力所为,同时也说明该股还有主力没有“死掉”。
第二种是底部放量下跌
既然是底部放量下跌,实际上就是突破底部平台以后的持续性下跌,因此放量的时机是判断的要点。如果刚向下突破就放量(跌幅在5%以内),表明有非市场性交易的成分,不一定是主力自己的对倒,但可能是新老主力的交班,或者是某张大接单要求主力放盘。不管怎么说,一开始向下突破就放量至少以后还有回升的希望。
第三种是盘整放量
盘整放量的情形相对来说比较复杂。比如大盘一路盘跌,股价应该也是盘跌,但现在依然只是盘整,那就说明有资金在承接,只要不是特别大的量,表明有主力护盘,但并不一定表明后市一定涨势超过大盘,这还是取决于该主力护盘的动机和资金状况。若大盘一样是盘整,那么该股的放量盘整就是主力自己所为了,目的无非是为了吸引市场的买单。
下面还要简单来了解一下程序化交易,相信结合了上述底部放量之后,实际操作便不是一个难题了。
程序化交易是把可量化的分析方法,用计算机编成交易策略进行自动下单交易,程序化交易是量化交易的一部分,或者是某些量化交易的进一步升级。区别程序化交易和量化交易的标准是人工下单还是计算机程序自动委托下单。对于拥有计算机和编程经验的人群来说,程序化交易是一个能够将金融和科技完美结合的工具;而对于非计算机专业出身或者编程能力不强的人群,也可以通过一些市面上已有的自动交易程序,将交易思路变为计算机可以执行的过程,让机器操作下单、风控。
综上所述,在2019-03-20的市场中或大多市场环境中使用底部放量,已证明被大量有经验的人所使用。然而纸上得来终觉浅,如果不自己钻研,那也很难体会到这个指标的真谛。然而,底部放量只是分析中的一种途径,结合考虑更多指标与分析手段,并且不断从各种优质渠道和资源中汲取营养,例如学习QR量化投资社区的内容,才能够使操盘过程更加完备。
架构综述 通过对12306业务系统的需求分析之后可以发现,架构设计主要要解决的问题有:数据库高并发读写、有效的容灾机制与系统高可用、数据的安全以及对虚拟化云计算的支持。
为解决上述问题,本架构以混合云为云端架构,采用读写分离的分布式架构设计数据库,使用hadoop与openstack统筹算力资源并组织、管理集群,同时利用双活容灾机制保障系统的高可用。具体架构如下图所示:
所用到的与产品主要包括三个层面:云端、分布式系统以及数据库。云端依靠阿里云与openstack进行混合云的部署。分布式系统主要依托hadoop与openstack作为系统支撑,Pivotal GemFire作为分布式内存对象缓存系统进行部署。数据库采用PostgreSQL作为数据库管理系统,Pivotal GemFire作为内存数据库,同时使用HybridDB为大数据计算提供支持。云产品及其关系如下图所示:
混合云架构设计 混合云是融合公有云和私有云,是近年来云计算的主要模式和发展方向。企业用户出于安全考虑,更愿意将数据存放在私有云中,但是同时又希望可以获得公有云的计算资源,所以可以将业务进行分流,同时使用私有云与共有云。
混合云架构以铁路总公司数据中心与铁科院数据中心为私用云,在保障数据安全的前提下,租用阿里云进行查询业务的分流。分流依靠CDN进行请求的分配,提供高质量的网络服务。
分布式数据库设计 数据库主要由主数据库与下属18个路局的分数据库组成,并采用读写分离机制,主数据库负责数据的写入,分数据库负责数据的读取。数据的写操作主要依赖PostgreSQL进行,而读操作主要依赖GemFire。设计简图如下图所示:
PostgreSQL是一个开源的对象-关系数据库服务器,配合的开源软件很多,很容易做读写分离、负载均衡、数据水平拆分等方案。它在支持大部分 SQL标准的同时有许多现代化的特性和方便快捷的数据结构,这些特性能够解决很多12306的问题如余票统计、单行锁冲突、并行计算等。
GemFire是一个高性能的分布式内存对象缓存系统(内存数据库)。把对象或数据缓存在内存中,减少对传统关系型数据库的读写次数(减少IO瓶颈),从而使我们的应用支持更多的TPS,更多的并发用户数。GemFire能够在部分场景下对关系型数据库起到很好的补充,能够进行低延迟的余票查询。
数据中心架构设计 数据中心主要由数据库服务器,缓存服务器,web服务器以及业务集群组成,其中业务集群为数据中心的主要算力来源。架构设计图如下所示:
集群与数据中心的组织管理依靠在OpenStack云环境中部署Hadoop集群的方式(主要面向私有云),既最大限度提高了服务器的资源利用率,又大大降低了大数据处理的准入门槛。
Openstack是云操作系统,是将物理机虚拟化的云服务平台,包含各种管理组件及API。它的核心是虚拟化,主要负责云架构系统层的组织与管理。
Hadoop则是“云计算”中分布式计算核心,侧重hdfs云存储与mapreduce云数据分析。它的核心是算力分配,将廉价的计群算力和存储集中。
对于12306系统而言高性能的保障主要由GemFire实现。
GemFire是一个位于应用集群和后端数据源之间的高性能、分布式的操作数据(operational data)管理基础架构。它提供了低延迟、高吞吐量的数据共享和事件分发。GemFire充分利用网络中的内存和磁盘资源,形成一个实时的数据网格,基于内存的海量数据实时处理平台。
它有许多实用的特性:多种网络拓扑、高并发的内存数据结构,避免锁争夺、可选的ACID、序列化和智能缓冲保证消息快速分发、同步或异步写磁盘、冗余内存拷贝。这些特性能够为整个12306系统提供:超低延迟和超高吞吐量、动态的线性扩展能力、持续高可用性、MapReduce并行处理、数据感知路由。
在实际中12306主要面临海量的用户访问带来的高并发问题、余票查询的延迟带来的高流量问题,以及读写分离带来的数据同步问题。
对于高并发问题,GemFire是基于内存的架构,有天然的IO优势,而且本身是分布式数据库,能够分散访问请求,降低负荷。同时很容易实现动态的分布式架构,可以动态添加服务节点。
对于高流量问题,GemFire提供类Map-Reduce的操作以进行并行处理,并将耗时计算单元提前处理,生成查询缓存,即到即用,同时在余票数据变化时动态更新查询缓存。
数据同步则依赖于Gemfire良好的事件处理架构,同时配合Postgresql的异构系统消息服务。具体流程如下图所示:
容灾与高可用设计 容灾主要依赖铁路总公司数据中心与铁科院数据中心实现双活容灾。两个主备数据中心都同时承担用户的业务,此时,主备两个数据中心互为备份,并且进行实时备份。在业务的分配上,铁路总公司数据中心承担较多的业务,保证了当其中一边发生故障时,不至于造成业务无法处理的情况。架构设计图如下所示。
双活的实现依赖openstack的虚拟化系统管理,同时可以配合HybridDB与PostgreSQL,以及GemFire实现仲裁、自动fallover,fallback以及数据同步。
程序员的十个层次,你属于哪一层? 第1层 菜鸟第2层 大虾第3层 牛人第4层 大牛第5层 专家第6层 学者第7层 大师第8层 科学家第9层 大科学家第10层 大哲总之第11层 上帝 自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。
那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。
当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。
第1层 菜鸟 第1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript,…,均可入门迈进这层。
在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。
没有多少人愿意一辈子做菜鸟,因为做"菜鸟"的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气"好"的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。
所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。
第2层 大虾 从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过2~3年的努力,都可以爬到第2层,晋升为"大虾"。
中国的"大虾"数量和"菜鸟"数量估计不会少多少,所以这层上仍然远领先于西方。
大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通常是非常崇拜的,国外的如Robert C. Martin、Linus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。
第3层 牛人 由于"大虾"们经常被一些疑难问题给卡住,所以有了"大虾"们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。
学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个5~10本这方面的著作;以软件设计来说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、情感化设计等,否则是很难进到这个楼层的。
当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如Apache或Linux操作系统的源代码实现等。此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很"牛",你也就爬到了第3层,晋升为"牛人"了。
看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你"牛"呢?
需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。
在国内, 一旦成为"牛人",通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个"首席架构师"或者"首席xx学家"的头衔也不足为奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。
也有不少谦虚的"牛人",知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。
第4层 大牛 从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为"大牛"了。
当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为"大牛"一定需要掌握这些知识,以时下热门的多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为"大牛",又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为"大牛"。
要成为"大牛"并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。
当"牛人"晋升为"大牛",让"牛人们"发现有比他们更牛的人时,对"牛人"们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用"引无数菜鸟、大虾、牛人竞折腰"来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。
虽然成为"大牛"的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多"牛人"可以爬到这一层的。由此可知,"大牛"这个楼层的人数其实并不像想像的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。
由于"大牛"这层的人数不少,所以也很难统计除到底是中国的"大牛"数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的"大牛"们会更多一些。
看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了著名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的"大牛"怎么能和西方的比呢? 不知大家注意到没有,Linus Torvalds只是写出了一个"象模象样"的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。
可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:
Linus,Richard Stallman和Don Knuth(高德纳)一同参加一个会议。
Linus 说:“上帝说我创造了世界上最优秀的操作系统。”
Richard Stallman自然不甘示弱地说:“上帝说我创造了世界上最好用的编译器。”
Don Knuth一脸疑惑的说:“等等,等等,我什么时候说过这些话?”
1.html说明 1.1<!--注解 -->
注释:解释说明,对代码的说明;注释浏览器不解析
2html:超文本标签语言
浏览器解析;
弱语言:偶尔写错浏览也能解析;程序员编写的时候尽量规范; 3标签的作用:让html页面语义化 4标准的html格式 文档声明:<!doctype html> html标签:包括所有内容 head标签:文档头,包括一些关于页面的说明性的东西。 body标签:文档主体,包括页面显示的所有内容。 <meta charset="utf-8" />语言格式 5标签“一般来说”都是由开始标记和结束标记组成 6html框架 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> </body> </html>
1 Python保存numpy数据:
numpy.savetxt("result.txt", numpy_data) 2 保存list数据:
file = open('data.txt', 'w') file.write(str(list_data)); file.close() 转载于:https://www.cnblogs.com/hellojack/p/10767707.html
定义符号常量:#define PI 3.1415926 //没有分号
定义常变量 :const float PI=3.1415926;
符号常量和常变量的区别: 常变量:具有变量的特征是存在一个以变量名命名的存储单元,在一般情况下,存储单元中的内容是可以变化的。而对于常变量,在变量的基础上加了一个限定:存储单元中的内容不允许变化,仍然是有存储单元的。
符号常量:是使用一个字符串代替程序中出现的一个标识符,是编译时把所有的符号常量都替换成制定的字符串,它没有类型,在内存中也不存在以符号常量命名的存储单元。在其作用域内其值不能改变和赋值。
常变量具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度。与一般变量惟一的不同是指定变量的值不能改变。用#define命令定义符号常量是C语言所采用的方法,C++把它保留下来是为了和C兼容。C++的程序员一般喜欢用const定义常变量。虽然二者实现的方法不同,但从使用的角度看,都可以认为用了一个标识符代表了一个常量。有些书上把用const定义的常变量也称为定义常量,但读者应该了解它和符号常量的区别。
常变量和文字常量的区别: 常量指值不可改变的量。在C/C++中常量分为两种:文字常量(Literal constant)和常变量(constant variable)。 文字常量和常变量的本质区别:文字常量编译之后存储在代码区,不可寻址,常变量存储在数据区,可寻址。
常变量:前面已经说明概念,它本身的存储区和普通变量的存储也没什么区别,只不过分类不同。 文字常量:文字常量又称为“字面常量”,包括数值常量、字符常量和符号常量。其特点是编译后写在代码区,不可寻址,不可更改,属于指令的一部分。 int& r=5;//编译错误 这条语句出现编译错误,原因是文字常量不可寻址,因而无法为文字常量建立引用。 下面这条语句又是合法的:
const int& r=5; 原因是编译器将一个文字常量转化成常变量的过程。在数据区开辟一个值为5的无名整型常变量,然后将引用r与这个整型常变量进行绑定
数值常量:包括整型常量和实型常量。整型常量就是指常整数,有十进制、八进制、十六进制三种表示形式。实型常量只采用十进制小数形式和指数形式表示,包括单精度浮点数(float)、双精度浮点数(double)和长双精度浮点数(long double)。
int a=4;//4为文字数值常量中的整型常量 float b=4.4//4.4为单精度实型常量 double c=1.4e10//1.4e5表示的值为1.4×10^5,双精度实型常量 字符常量:指单个ASCII码字符,有256个,如’a’和’b’。
符号常量:用标示符代表一个常量,使用之前必须定义。
#define NUM 100//NUM为符号常量,100为整型常量 enum Weekday{SUN, MON, TUES, WED, THU, FRI, SAT};//SUN,MON等均为符号常量 关于static我会自己再在后面去补充。
https://github.com/rafaelpadilla/Object-Detection-Metrics 写在开头:
(1) mAP总是在固定的数据集上计算 (2)它不是量化模型输出的绝对度量,但是是一个比较好的相对度量。当我们在流行的公共数据集上计算这个度量时,这个度量可以很容易的用来比较不同目标检测方法 (3)根据训练中类的分布情况,平均精度值可能会因为某些类别(具有良好的训练数据)非常高(对于具有较少或较差数据的类别)而言非常低。所以我们需要MAP可能是适中的,但是模型可能对于某些类非常好,对于某些类非常不好。因此建议在分析模型结果的同时查看个各类的平均精度,这些值也可以作为我们是不是需要添加更多训练样本的一个依据。
目标检测中的mAP是什么含义?
目标检测中衡量识别精度的指标是mAP(mean average precision)。多个类别物体检测中,每一个类别都可以根据recall和precision绘制一条曲线,AP就是该曲线下的面积,mAP是多个类别AP的平均值。
在VOC2010以前,只需要选取当Recall >= 0, 0.1, 0.2, ..., 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值。在VOC2010及以后,需要针对每一个不同的Recall值(包括0和1),选取其大于等于这些Recall值时的Precision最大值,然后计算PR曲线下面积作为AP值。
参见:The PASCAL Visual Object Classes Challenge 2012 (VOC2012) Development Kit
mAP定义及相关概念 mAP: mean Average Precision, 即各类别AP的平均值AP: PR曲线下面积PR曲线: Precision-Recall曲线Precision: TP / (TP + FP),Precision是从已经预测为同一类别的样本抽样Recall: TP / (TP + FN),召回率(Recall)是从数据集的同一类的样本抽样TP: IoU>threshold的检测框数量(同一Ground Truth只计算一次)FP: IoU<=threshold的检测框,或者是检测到同一个GT的多余检测框的数量FN: 没有检测到的GT的数量 Precision
查准率(Precision)是针对预测结果而言的,它表示的是预测为正的样本中有多少是真正的正样本。
Recall
召回率(Recall, 又称为 TPR)是针对原来的样本而言的,它表示的是样本中的正例有多少被预测正确了。
一个例子帮助我们更好地理解mAP的概念: 7张图,15个真实框(绿色),24个检测到的框(红色),每个框有它的置信度,并给它从A开始定义
IOU的阈值为0.3,计算prdiction_box与gt_box的iou,大于阈值的为TP,小于的为FP.当一个gt_box有多个prediction_box相交时,此时选取IOU大的作为TP,其他为FP。
算出准确率和召回率
准确率(Precision)=TP/TP+FP=TP/all detections
召回率(recall)=TP/TP+TN=TP/all ground truths=TP/15
由置信度从大到小排列,Acc TP:累计的TP Acc FP:累计的FP
画出P-R曲线:
序列化是指将数据存储到文件中。
先序遍历序列化
public static String serialByPre(Node head) { if (head == null) { return "#!"; } String res = head.value + "!"; res += serialByPre(head.left); res += serialByPre(head.right); return res; } 上面的代码是将一个二叉树序列化,如果遇到空则用#字符占位,中间用叹号分割。
用什么方式序列化的,就直接用什么方式反序列化
先序遍历反序列化
public static String serialByPre(Node head) { if (head == null) { return "#!"; } String res = head.value + "!"; res += serialByPre(head.left); res += serialByPre(head.right); return res; } public static Node reconByPreString(String preStr) { String[] values = preStr.
@echo off
title maven自动打包拷贝
color 03
mode con cols=40 lines=15
:: todo call mvn clean install --settings E:\999\apache-maven-3.5.2\setting123.xml -Dmaven.test.skip=true cd ../
call mvn clean install --settings E:\999\apache-maven-3.5.2\setting123.xml -Dmaven.test.skip=true cd ..
mkdir build_war
cd build_war
copy /y E:\idea-gitWork\ems2.0\CommonWeb\target\*.war E:\idea-gitWork\build_war\ copy /y E:\idea-gitWork\ems2.0\process-web\target\*.war E:\idea-gitWork\build_war\ copy /y E:\idea-gitWork\ems2.0\reimbursexxxService\target\*.war E:\idea-gitWork\build_war\ copy /y E:\idea-gitWork\ems2.0\Reimbursexxx\target\*.war E:\idea-gitWork\build_war\ copy /y E:\idea-gitWork\ems2.0\Reimbursexxx\target\*.war E:\idea-gitWork\build_war\ cd E:\idea-gitWork\ems2.0_9
call mvn clean install --settings E:\999\apache-maven-3.5.2\setting123.xml -Dmaven.test.skip=true copy /y E:\idea-gitWork\ems2.0_9\jobschedular-web\target\*.war E:\idea-gitWork\build_war\ copy /y E:\idea-gitWork\ems2.
BLS签名方案是一个基于双线性映射的密码学算法,它可以应用于可验证随机函数的设计,具有可验证性、随机性、唯一性、确定性。
记,e: G*G->G'为一个非退化的双线性映射,G和G'为素数r阶乘法群,根据双线性映射性质有e (g1^x, g2^y) = e (g1, g2)^(x * y)。BLS签名包括三个算法。
算法描述:
(1)密钥生成算法KeyGen:随机选取x in [0, r-1]作为私钥,sk=x,计算公钥pk = g^x,g是群G的生成元;
(2)签名算法Sign:消息m的签名为sign = h^x,h = Hash(m)
(3)验证算法Verify:验证者拥有G, g^x (pk), m 和 sign,验证e(sign, g)和e(Hash(m), pk)是否相等,如果相等那么签名验证通过;
证明过程:
由双线性映射性质有
e (g1^x, g2^y) = e (g1, g2)^(x * y)
可得 e(sign, g) = e(h^x, g) = e(h, g)^x
e(Hash(m), pk) = e(h, g^x) = e(h, g)^x
因此
e(sign, g) = e(Hash(m), pk)
冒险岛079linux服务端(原豆豆冒险岛,好像叫豆豆冒险单)
有Linux的小伙伴研究,没有linux基础的小伙伴,就别看了。。 在申明一遍,没有linux基础的小伙伴,请放弃!!!! 在申明一遍,没有linux基础的小伙伴,请放弃!!!! 在申明一遍,没有linux基础的小伙伴,请放弃!!!! 经本人亲测,已成功运行!! 经本人亲测,已成功运行!! 经本人亲测,已成功运行!! 老哥这块有你想要的NB东西,在手机上运行143冒险岛服务端!!![Android手机] 老哥这块有你想要的NB东西,在手机上运行143冒险岛服务端!!![Android手机] 老哥这块有你想要的NB东西,在手机上运行143冒险岛服务端!!![Android手机] 老哥这块有你想要的NB东西,在手机上运行143冒险岛服务端!!![Android手机] 老哥这块有你想要的NB东西,在手机上运行143冒险岛服务端!!![Android手机] https://blog.csdn.net/qq_31392539/article/details/89925363 欢迎使用XINHAO_HAN服务端! 运行环境:mysql:5.7 java版本为:openjdk version “1.8.0_191” OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-2ubuntu0.18.04.1-b12) OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode) 如果出现选择人物退到登陆页面,请在Settings.ini中吧Tms.IP改为你服务器的IP 成功运行图(如果一直卡在"------------------------------------------------",请检查你的数据库有没有连接好): 关于mysql(需要你导入你的mysql文件)
请按照步骤一步一步走
在ubuntu或CentOS 安装mysql5.7(强烈推荐)
吧远程连接mysql配置好(百度搜索,mysql远程连接)
然后下载 Navicat for MySQL
现在linux下创建一个名为:mser的数据库
语句:create database mser;
完成之后下载window服务端:链接: 链接: https://pan.baidu.com/s/1zS-FvjUMzG0z0Z6Uw6lHiA 提取码: 88a5 复制这段内容后打开百度网盘手机App,操作更方便哦
下载完成之后(解压)打开:
服务端/mSer/Mysql/phpStudy.exe
就这个:
然后开启mysql,好了,接下来打开 Navicat for MySQL
连接这个服务端的远程
账号:root
密码: root
连接成功后如下
连接成功:
第一个:127.0.0.1 是你本地的那个mysql服务器
第二个:192.168.1.171 是你服务端的mysql服务器
今天继续刷牛客真题,给定四个边长,求拼凑成正方形的最短更改次数。
分析:
要想需要最短次数,那么就是按照中位数来进行比较,对输入的数组进行排序,然后计算每个值与该数的差的和。
问题:
1、C++中排序函数和Python中排序函数的差别。
附上C++代码:
#include<iostream> #include<algorithm> using namespace std; int main() { int a[4]; cin>>a[0]>>a[1]>>a[2]>>a[3]; sort(a,a+4); int sum=0; for(int i=0;i<4;i++) { sum+=abs(a[i]-a[2]); } cout<<sum<<endl; return 0; } 附上Python代码:
n=list(map(int,input().split())) n=sorted(n) sum=0 for i in range(4): sum+=abs(n[i]-n[2]) print(sum) ps:后面看别人的代码发现,针对这个场景,可以有更简单的方法。根据数学推到发现,最长和最短的两根木棍要达到相同长度,那么需要进行max-min次,第二长与第二短要达到相同长度,需要进行a-b。发现这两个结果是一样的。
附上代码:
#include<iostream> #include<algorithm> using namespace std; int main() { int a[4]; cin>>a[0]>>a[1]>>a[2]>>a[3]; sort(a,a+4); int sum=(a[3]-a[0]+a[2]-a[1]); cout<<sum<<endl; return 0; } 时间没有减小,但是空间占用少了。(排序的改进可能减小时间。)
一般依赖
sudo yum install protobuf-devel leveldb-devel snappy-devel opencv-devel boost-devel hdf5-devel 剩余的依赖关系,最近的操作系统
sudo yum install gflags-devel glog-devel lmdb-devel 剩余的依赖项,如果找不到
# glog wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/google-glog/glog-0.3.3.tar.gz tar zxvf glog-0.3.3.tar.gz cd glog-0.3.3 ./configure make && make install # gflags wget https://github.com/schuhschuh/gflags/archive/master.zip unzip master.zip cd gflags-master mkdir build && cd build export CXXFLAGS="-fPIC" && cmake .. && make VERBOSE=1 make && make install # lmdb git clone https://github.com/LMDB/lmdb cd lmdb/libraries/liblmdb make && make install 请注意,glog不能使用最新的gflags版本(2.1)进行编译,因此在解决之前,您需要先使用glog进行构建。
数据不同步的异常情况通常出现在,在同一时刻有多个写数据的操作发生。因此要避免数据库的数据不同步这个问题,就要避免同时有多个写数据的操作,同时只能有一个写操作。
这在一台服务器运行的时候似乎是没有问题的,但是如果多台web服务器的话,就出现问题了。
一个不错的办法就是,可以将读写分离,所有的读操作都可以直接从数据库服务器当中读出。但写操作,一般web服务器没有这个权限,如果需要写那就需要设定一个专门负责写数据库的代理服务器,让所有web服务器的写操作都通过这个有写数据库权限的代理服务器,让写操作不存在并行,而是串行,同时只能对一个数据进行一个写操作。
Mysql默认引擎在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。
以上对于博主来说尚且还为理论,未实际实验过。
1、concat()
a=[]; a.concat([1,2,3,4]); 此时a还是为[],返回的结果为合并后的值。因为concat()方法不会改变原来的数组,只会返回合并后新的数组,所以如果a想要得到合并的值,就必须将返回的值赋值给a:
a = a.concat([1,2,3,4]); 2.、for循环 + push() 或者用ES6的扩展运算符…
for( var t in [1,2,3,4]){ a.push(t); } 或者
a.push(...[1,2,3,4]); 3、push.apply()
b=[]; b.push.apply(b,[1,2,3,4]); push()和push.apply()的区别:
如:
a.push([1,2,3,4]); b.push.apply(b,[1,2,3,4]); 结果为:
a:
[Array(4)] 0: (4) [1, 2, 3, 4] length: 1 此时b:
[1, 2, 3, 4] 也就是说a[0]与b相同。
当然也可以用扩展运算符:
a.push(...[1,2,3,4]); 此时a与b相同
推荐使用Array.prototype.push.apply(),因为这个方法的效率更高,但其实它与push.apply()方法的本质是一样的。
1,n个有序链表的合并:除了两两合并之外,更高效的方法
2,为什么batch训练可行:loss的推导。。loss是加和形式,独立同分布,。。
3,决策树的分界面形状
4,异常检测lof, oneclass svm
5,如何解决梯度消失和梯度爆炸
6,哈希表、最小堆、堆排序、常见数据结构和算法
7,如何解决过拟合
8,
学习笔记
目标 函数参数和返回值的作用函数的返回值 进阶函数的参数 进阶递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式
无参数,无返回值无参数,有返回值有参数,无返回值有参数,有返回值
定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的!
如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值 1.1 无参数,无返回值 此类函数,不接收参数,也没有返回值,应用场景如下:
只是单纯地做一件事情,例如 显示菜单在函数内部 针对全局变量进行操作,例如:新建名片,最终结果 记录在全局变量 中 注意:
如果全局变量的数据类型是一个 可变类型,在函数内部可以使用 方法 修改全局变量的内容 —— 变量的引用不会改变在函数内部,使用赋值语句 才会 修改变量的引用 1.2 无参数,有返回值 此类函数,不接收参数,但是有返回值,应用场景如下:
采集数据,例如 温度计,返回结果就是当前的温度,而不需要传递任何的参数 1.3 有参数,无返回值 此类函数,接收参数,没有返回值,应用场景如下:
函数内部的代码保持不变,针对 不同的参数 处理 不同的数据例如 名片管理系统 针对 找到的名片 做 修改、删除 操作 1.4 有参数,有返回值 此类函数,接收参数,同时有返回值,应用场景如下:
函数内部的代码保持不变,针对 不同的参数 处理 不同的数据,并且 返回期望的处理结果例如 名片管理系统 使用 字典默认值 和 提示信息 提示用户输入内容 如果输入,返回输入内容如果没有输入,返回字典默认值 02.
亚马逊EC2自带的g++是4.8,比较老的版本,许多新的代码都编译不了。因此需要升级g++。
升级方法如下:
1、安装依赖
sudo yum install libmpc-devel mpfr-devel gmp-devel 2、获得源码
以获得5.4.0的源码为例
cd /tmp curl -o "gcc-5.4.0.tar.gz" https://ftp.gnu.org/gnu/gcc/gcc-5.4.0/gcc-5.4.0.tar.gz tar -xvzf gcc-5.4.0.tar.gz 如果你想获得其他版本,可以去这个网站https://ftp.gnu.org/gnu/gcc查看,然后修改版本号就行,比如将5.4.0修改为5.5.0
3、配置和编译
./configure --with-system-zlib --disable-multilib --enable-languages=c,c++ make -j8 4、安装
sudo make install 上面就是安装完成了,可以使用
g++ -v 查看当前使用的g++版本,如果没有变成你想要的版本,那是因为软链接的问题。
首先使用
which g++ 查看当前使用g++的具体路径,很有可能给出的路径是/usr/bin/g++
实际上,你刚刚安装的g++是在/usr/local/bin中的,而使用ll /usr/bin/g++会发现这是个软链接,并且指向的位置并不是咱们刚刚安装的g++,所以我们只要将这个软件删除,重新建一个指向咱们新安装的g++即可。具体:
cd /usr/bin sudo rm g++ ln -s /usr/local/bin/g++ g++ 此时再使用g++ -v就发现使用的是咱们刚刚安装的版本了。
同样的,使用相同的方法修改gcc。
一、文件操作
1、C++从txt文件中读取二维的数组
转载于:https://www.cnblogs.com/Tang-tangt/p/10756391.html
fiddler只能抓到苹果手机http请求,抓不到https请求
1、fiddler设置完成
2、苹果手机安装完成证书之后,要到通用->关于本机->证书信任设置中打开信任证书
3、如果前两步设置之后,还是找不到https的请求,再试一下下面的方法
点击此处下载证书,重启下fiddler
打开fiddler后,浏览器访问会出现不是私密链接提示
把下面的两个设置取消勾选
fiddler 腾讯的APP能够连上,其他app连上不网
解决办法:把电脑的防火墙关了,重启fiddler;如果还是不行,把电脑的360安全卫士等其他软件也退出,再重启fiddler。
依然没有效果的话再试下把下面红线标记的取掉重启fiddler
如果还是不行的话,再查看下其他原因
重启电脑后,fiddler又连不上了
把电脑中的杀毒软件都关了
把Gateway 做如下更改,真是醉了,就是不知道哪天又会出什么幺蛾子
电脑,苹果都可以使用,安卓手机微信能使用,但是微信访问H5测试的页面,样式可以访问,但是请求的接口调不到
小米手机:更多设置->系统安全->清除凭据,把安装的证书删掉,然后再浏览器重新下载证书再重试
华为手机:找到系统安全设置,清除凭据之后,重新按照证书就可以抓到接口
忽略报错
如果还是会保存,先选择一个别的选择保存之后,再选择Do nothing保存,就不会再报错了。
2019独角兽企业重金招聘Python工程师标准>>> 新Gitlab系统是自己搭建的,为了使用pages功能,因为少于8.8版本貌似就不能使用!下一篇我会补充,毕竟是转发的!
更新代码后,上传到gitlab,使用Pipelines进行检查部署,可就是等了几个小时一直显示running状态,最后当然是失败了!因为更新的都是文本文件,纯粹是文字,对gitlab来讲仅仅是更新文件罢了,可就是不通过,也无从下手找原因,如有大侠知道,请留言指点!
临时解决办法
gitlab服务器执行代码
gitlab-runner --debug run 然后弹出一大堆东西,然后你查看Pipelines,你会发现通过了!神奇!!!
然后你可以Ctrl + c断掉了
Reference
https://docs.gitlab.com/runner/faq/
转载于:https://my.oschina.net/doctorlzr1988/blog/3041075
软件测试入行容易进阶难。从测试小白成长为测试经理、总监级别人才,要跨越长长的技术栈升级之路,挑战非常高的综合能力要求。
大牛都是相似的:具备扎实的测试方法论基础,能深入理解业务逻辑,会利用先进的技术工具,可以自主开发定制化服务,情商高善于沟通表达,懂管理能带项目和团队。
在成长过程中,从经典好书中汲取养分是提升技能的核心方式之一。
4.23 世界读书日,霍格沃兹测试学院参考测试大咖 @skytraveler 书评以及豆瓣高分推荐,梳理了一个「测试开发工程师必读好书清单」V1.0 版供大家参考阅读。
肯定还有不少其他好书,欢迎大家在评论区留言推荐!
「测试开发工程师必读好书清单」V1.0 版 测试理论与实践 •《软件测试经验与教训》https://book.douban.com/subject/1139061/
如果只让推荐一本书,推荐这一本。书由很多看似零散的小知识点组成,但是字字珠玑。真正做过2年~20年测试的人,拿起它来,每一条和自己的工作做对照,都会有共鸣或者”原来如此“的感受。工作经验越多,体会越深,是一本常看常新,并且能够一直指导你的书。从某种意义上,它教会测试人员的是“思辨思维”,这才是最重要的财富。
•《有效软件测试:提高测试水平的 50 条建议》https://book.douban.com/subject/1146227/
跟《软件测试经验与教训》一样是一部分实战很强的总结类书籍,我觉得也可以列入经典。推荐阅读的时候同自己的工作一条一条做对照,肯定会有很深体会。(里边的一些观点也许你不同意,但是,能够促进你思考就是好事情)。
•《软件测试基础教程》https://book.douban.com/subject/3612082/
如果你入行不深,想从最基本的地方补一下测试理论。这本书无疑是相当合适的教材。看过很多书,ISTQB 系列还是最成体系化,内容也最好的书之一。
•《Google 测试之道:像 Google 一样进行软件测试》https://book.douban.com/subject/25742200/
Google 大牛 James A. Whittaker 分享测试实践经验,开拓视野、提升水平必读经典好书,引发很多关注讨论。
•《探索吧!深入理解探索式软件测试》https://book.douban.com/subject/25829182/
近些年难得的测试好书。这本书中对探索式软件测试的定义,作用,局限性和实施方法可能都是最好的。就算不是做纯粹的 ET,这本书的很多内容都能直接帮助你提高测试质量。强烈推荐。
•《实例化需求:团队如何交付正确的软件》https://book.douban.com/subject/11611022/
每个测试人员都值得一读(应该推荐团队所有成员读),你绝对会眼前一亮并说:太棒了!就该这么干!书的最高境界是一个理想的“活文档系统”,实际上这很难完全实现,但里边的东西每实现一部分,测试的效果就会提高一部分,团队离失败就会远一点。
•《Scrum 要素》 https://book.douban.com/subject/20507350/
近年来,国内的团队都在做敏捷转型。所以很多测试人员都会遇到在敏捷团队工作的经历。敏捷实施给软件人员带来的冲击还是很大的,过程中我们也听到了各种声音。Scrum 元素以很多小故事的形式讲述了敏捷团队如何工作,非常实用,测试人员值得一读。
•《海盗派测试分析:MFQ & PPDCS》https://book.douban.com/subject/27021193/
国内资深测试专家邰晓梅老师关于测试思维的书,书中的知识其实是国内很多测试人员的能力短板。推荐阅读。
性能测试 •《性能之巅:洞悉系统、企业与云计算》https://book.douban.com/subject/26586598/
这本书其实不是专门写给测试人员的。但是如果想做好性能测试,强力推荐这本书。如果你能够全部读懂(全部读懂需要一些功力),性能测试对你来说会是小菜一碟。
•《应用程序性能测试的艺术》https://book.douban.com/subject/4156318/
•《软件性能测试过程详解与案例剖析》https://book.douban.com/subject/1912900/
以上两本书,一本外国人写的,一本是国人段念写的。主要告诉你性能测试如何来做,为什么要这么做,还有评判准则,还有很好的案例。如果真正的做性能测试,推荐一定要读这两本,因为这是在讲方法论的东西,没有方法论指导,你就不知道怎么建模,怎么设计场景,怎么评判测试结果。
另外,如果性能测试做得比较深入了,其实可以看相关的开发书籍,比如架构相关的书,数据库管理、调优,JVM 调优,Web 服务器管理、调优,高性能程序设计、调优等。对被测物理解越深,性能测试才能越深入。这方面的书可以自行根据关键字进行搜索。
安全测试 •《渗透测试实践指南:必知必会的工具与方法》https://book.douban.com/subject/20366359/
最好的渗透测试入门书,也是一本目录,可以由它打开安全测试之门。
自动化测试 •《自动化测试最佳实践》https://book.douban.com/subject/22232395/
这是一本案例教学的书。里边有几十个例子,其中一半的例子非常有参考价值。
自动化要做好至少要有4点:合适的技术,合适的策略,合适的团队,合适的时机。技术对于自动化实施成功充其量只占到四分之一。
书里讲了很多技术之外的东西。真正做自动化实施的同学读了肯定会有很多感触。如果是初学者,建议你先买了放着,经过一两个失败的项目(没有非常好的工程师带,没有好的团队,通常第一次实施肯定是失败的)后再反过来读。另外《测试之美》里边也有几章是自动化测试相关的案例,值得一看。
•《测试之美》https://book.douban.com/subject/4805950/
编程语言与开发技能 测试开发工程师最常用 Java 和 Python ,推荐几本入门和高级经典书目,以及算法、Linux 基础技能、SQL、正则表达式、MySQL 数据库、以及最流行的 Spring 框架好书,经典不多说。
一、卷积神经网络的基本概念 受Hubel和Wiesel对猫视觉皮层电生理研究启发,有人提出卷积神经网络(CNN),Yann Lecun 最早将CNN用于手写数字识别并一直保持了其在该问题的霸主地位。近年来卷积神经网络在多个方向持续发力,在语音识别、人脸识别、通用物体识别、运动分析、自然语言处理甚至脑电波分析方面均有突破。
卷积神经网络与普通神经网络的区别在于,卷积神经网络包含了一个由卷积层和子采样层构成的特征抽取器。在卷积神经网络的卷积层中,一个神经元只与部分邻层神经元连接。在CNN的一个卷积层中,通常包含若干个特征平面(featureMap),每个特征平面由一些矩形排列的的神经元组成,同一特征平面的神经元共享权值,这里共享的权值就是卷积核。卷积核一般以随机小数矩阵的形式初始化,在网络的训练过程中卷积核将学习得到合理的权值。共享权值(卷积核)带来的直接好处是减少网络各层之间的连接,同时又降低了过拟合的风险。子采样也叫做池化(pooling),通常有均值子采样(mean pooling)和最大值子采样(max pooling)两种形式。子采样可以看作一种特殊的卷积过程。卷积和子采样大大简化了模型复杂度,减少了模型的参数。
二、卷积神经网络的应用场景
三、卷积神经网络的原理
3.1 神经网络
首先介绍神经网络,这一步的详细可以参考资源1。简要介绍下。神经网络的每个单元如下:
其对应的公式如下:
其中,该单元也可以被称作是Logistic回归模型。当将多个单元组合起来并具有分层结构时,就形成了神经网络模型。下图展示了一个具有一个隐含层的神经网络。
其对应的公式如下:
比较类似的,可以拓展到有2,3,4,5,…个隐含层。
神经网络的训练方法也同Logistic类似,不过由于其多层性,还需要利用链式求导法则对隐含层的节点进行求导,即梯度下降+链式求导法则,专业名称为反向传播。关于训练算法,本文暂不涉及。
3.2 卷积神经网络
受Hubel和Wiesel对猫视觉皮层电生理研究启发,有人提出卷积神经网络(CNN),Yann Lecun 最早将CNN用于手写数字识别并一直保持了其在该问题的霸主地位。近年来卷积神经网络在多个方向持续发力,在语音识别、人脸识别、通用物体识别、运动分析、自然语言处理甚至脑电波分析方面均有突破。
卷积神经网络与普通神经网络的区别在于,卷积神经网络包含了一个由卷积层和子采样层构成的特征抽取器。在卷积神经网络的卷积层中,一个神经元只与部分邻层神经元连接。在CNN的一个卷积层中,通常包含若干个特征平面(featureMap),每个特征平面由一些矩形排列的的神经元组成,同一特征平面的神经元共享权值,这里共享的权值就是卷积核。卷积核一般以随机小数矩阵的形式初始化,在网络的训练过程中卷积核将学习得到合理的权值。共享权值(卷积核)带来的直接好处是减少网络各层之间的连接,同时又降低了过拟合的风险。子采样也叫做池化(pooling),通常有均值子采样(mean pooling)和最大值子采样(max pooling)两种形式。子采样可以看作一种特殊的卷积过程。卷积和子采样大大简化了模型复杂度,减少了模型的参数。卷积神经网络的基本结构如图所示:
卷积神经网络由三部分构成。第一部分是输入层。第二部分由n个卷积层和池化层的组合组成。第三部分由一个全连结的多层感知机分类器构成。
3.2.1局部感受野
卷积神经网络有两种神器可以降低参数数目,第一种神器叫做局部感知野。一般认为人对外界的认知是从局部到全局的,而图像的空间联系也是局部的像素联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。网络部分连通的思想,也是受启发于生物学里面的视觉系统结构。视觉皮层的神经元就是局部接受信息的(即这些神经元只响应某些特定区域的刺激)。如下图所示:左图为全连接,右图为局部连接。
在上右图中,假如每个神经元只和10×10个像素值相连,那么权值数据为1000000×100个参数,减少为原来的万分之一。而那10×10个像素值对应的10×10个参数,其实就相当于卷积操作。
3.2.3 权值共享
但其实这样的话参数仍然过多,那么就启动第二级神器,即权值共享。在上面的局部连接中,每个神经元都对应100个参数,一共1000000个神经元,如果这1000000个神经元的100个参数都是相等的,那么参数数目就变为100了。
怎么理解权值共享呢?我们可以这100个参数(也就是卷积操作)看成是提取特征的方式,该方式与位置无关。这其中隐含的原理则是:图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
更直观一些,当从一个大尺寸图像中随机选取一小块,比如说 8x8 作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8x8 样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从 8x8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。
如下图所示,展示了一个3×3的卷积核在5×5的图像上做卷积的过程。每个卷积都是一种特征提取方式,就像一个筛子,将图像中符合条件(激活值越大越符合条件)的部分筛选出来。
3.2.4 多卷积核
上面所述只有100个参数时,表明只有1个10*10的卷积核,显然,特征提取是不充分的,我们可以添加多个卷积核,比如32个卷积核,可以学习32种特征。在有多个卷积核时,如下图所示:
上图右,不同颜色表明不同的卷积核。每个卷积核都会将图像生成为另一幅图像。比如两个卷积核就可以将生成两幅图像,这两幅图像可以看做是一张图像的不同的通道。如下图所示,下图有个小错误,即将w1改为w0,w2改为w1即可。下文中仍以w1和w2称呼它们。
下图展示了在四个通道上的卷积操作,有两个卷积核,生成两个通道。其中需要注意的是,四个通道上每个通道对应一个卷积核,先将w2忽略,只看w1,那么在w1的某位置(i,j)处的值,是由四个通道上(i,j)处的卷积结果相加然后再取激活函数值得到的。
所以,在上图由4个通道卷积得到2个通道的过程中,参数的数目为4×2×2×2个,其中4表示4个通道,第一个2表示生成2个通道,最后的2×2表示卷积核大小。
3.2.5 Down-pooling
在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96X96 像素的图像,假设我们已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) × (96 − 8 + 1) = 7921 维的卷积特征,由于有 400 个特征,所以每个样例 (example) 都会得到一个 7921 × 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,并且容易出现过拟合 (over-fitting)。