文章目录 API网关(服务网关)概念API 网关的作用常用网关解决方案1. Netlix Zuul2. Spring Cloud Gateway3. Nginx + Lua4. Kong5. Traefik6. Orange API网关(服务网关) 概念 APl Gateway (API网关),顾名思义,是出现在系统边界上的一个面向API的、串行集中式的强管控服务,这里的边界是企业Ⅰ系统的边界,可以理解为企业级应用防火墙,主要起到隔离外部访问与内部系统的作用。在微服务概念的流行之前,API网关就已经诞生了,例如银行、证券等领域常见的前置机系统,它也是解决访问认证、报文转换、访问统计等问题的。
API网关的流行,源于近几年来移动应用与企业互联需求的兴起。移动应用、企业互联,使得后台服务支持的对象,从以前单一的Web应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着徵服务架构概念的提出,API网关成为了微服务架构的一个标配组件。
API网关是一个服务器,是系统对外的唯一入口。API网关封装了系统内部架构,为每个客户端提供定制的API。所有的客户端和消费都通过统一的网关接入微服务,在网关层处理所有非业务功能。
但对于服务数量众多、复杂度比较高、规模比较大的业务来说,引入API网关有一系列的好处:
聚合接口使得服务对调用者透明,客户端与后端的耦合度降低聚合后台服务,节省流量。提高性能,提升户体验提供安全、流控、过滤、缓存、计费、监控等API管理功能 API 网关的作用 API网关的主要作用包括如下几点:
1. 统一对外接口
当用户需要集成不同产品或者服务之间的功能,调用不同服务提供的能力。利用APIGateway可以让用户在不感知服务边缘的情况下,利用统一的接口组装服务。
对于公司内部不同的服务,提供的接口可能在风格上存在一定的差异,通过APIGateway可以统一这种差异。 当内部服务修改时,可以通过APIGateway进行适配,不需要调用方进行调整。
2. 增加系统安全性
APIGateway对外部和内部进行了隔离,减少对外暴露服务可以增加系统安全性,保障了后台服务的安全性。
3. 统一鉴权
通过APIGateway对访问进行统一鉴权,不需要每个应用单独对调用方进行鉴权,应用可以专注业务。
4. 服务注册与授权
可以控制调用方可以使用和不可以使用的服务。
5. 服务限流
通过APIGateway可以对调用方调用每个接口的每日调用及总调用次数限制。
6. 提升预发能力
为服务熔断,灰度发布,线上测试提供简单方案。
7. 全链路跟踪
通过APIGateway提供的唯一请求Id,监控调用流程,以及调用的响应时间。
常用网关解决方案 1. Netlix Zuul zuul是Netflx公司开源的一个API网关组件,Spring Cloud对其进行二次基于Spring Boot的注解式封装做到开箱即用。目前来说,结合sring Cloud 提供的服务治理体系,可以做到请求转发,根据配置或者默认的路由规则进行路由和Load Balance,无痛集成hystrix。
虽然可以通过自定义Filter实现我们想要的功能,但是由于zuul本身的设计是基于单线程的接收请求和转发处理,是阻塞10,不支持长连接。目前来看ZuulI就显得很鸡肋,随着Zuul2.x一直跳票(2019年5月发布了Zuul 2.0版本),Spring Cloud推出自己的网关组件Spring Cloud Gateway。
2. Spring Cloud Gateway Spring Cloud Gateway作为Spring Cloud 生态系统中的网关,目标是替代 Netlix Zuul,其不仅提供统一的路由方式,并且还基于Filter链的方式提供了网关基本的功能。
多线程 优点:同时处理多个请求,适合cpu密集型运算
缺点:如果多个线程操作同一个资源得上锁。多线程并不是一起去干一些事情,而是靠切换上下文(浪费一些性能)
单线程 node的主线程是单线程,不需要开启多个线程,节省资源,不适合做大量的cpu操作。但是node提供了开启子进程,可以将比较大的操作放入子进程去运行。
同步异步和阻塞非阻塞 阻塞非阻塞是相对于操作方的,操作放调用了同步方法,这时候就会阻塞。同步异步是相对于调用的方法。比如调用readFile就是异步的。
异步非阻塞:调用异步的方法,操作方不会被阻塞。
event loop 因为node的主线程是单线程,所以node也实现了自己的event loop。
1 代码会交给v8引擎进行处理2 代码中可能会调用nodeApi,node会交给libuv库处理3 libuv通过阻塞i/o和多线程实现了异步io。4 通过事件驱动的方式,将结果放入事件队列中,最终交给我们的应用。 node使用 默认执行一个文件的时候,在命令行运行node index.js文件的时候,他会把整个文件当成一个模块,默认把this修改了。
在全局下指向的就是global。
node新增的全局属性 buffer node中的二进制对象(最早的时候浏览器不能直接读写文件)process 进程
process中的一些属性: platform 当前执行环境的平台(如window(win32),mac(darwin))chidir,以更改当前工作的目录env 执行代码的时候可以传入一些环境变量argv 执行代码的时候可以传入的参数
可以通过传入参数获取。第一二个值是固定的,
[执行node所在的exe文件,当前的执行文件,…其他参数],用户脚手架启动项目的时候传入一些参数,然后在配置文件中获取这些值。
解析可以用到commander库(命令行管家)
nextTick
下面祥讲cwd (current working directory)当前工作的目录,比如webpack会自动擦护照运行webpack的目录下查找webpack.config.js文件。 __dirname(当前执行时的目录,绝对路劲) __filename(当前执行时的文件的绝对路劲)
setImmediate nextTick与node的eventloop node中自己实现的,不属于node的eventloop。优先级比Promise更高。nextTick算是微任务,他是当前栈中同步代码执行完毕后立即执行的。因为Node里也有一些异步操作,所以node实现了自己的eventLoop。
而node中的异步队列不比浏览器,node有很多类型的宏任务队列。
这是官网的案例。
一共有六种。 第一种是setTImeout等到时间就放入这个队列。
第二种就是一些回调函数,还有第四种io任务非常多,导致只能下一个循环执行,就会放入这里。
第三种是内部使用的
第四种是与io相关的回调 (poll, 比如readFIle)。
第五种是setImmediate的回调函数
第六种是一些关闭的回调函数。
我们重点需要关注第一种,第四种,第五种。
poll主要是放Io的回调,必须对文件的读写这些readFile等。
第五种check放一些setImmediate的回调。代码是从上往下执行的,从第一种走到第六种,走完之后继续走,是个死循环。但是有个问题,比如setTimeout按道理是在setImmediate前执行,但是有时候会setImmediate先执行。是因为当前默认执行主栈代码,主栈代码执行完毕后要执行定时器,但是定时器可能还没到时间,所以就先往下走,所以setImmediate可能会先执行。
有个特殊情况。就是
当执行io操作的时候,如上,主栈执行完代码之后,会走eventloop,此时同步代码没有setTimeout等,会直接走到第四种,poll,poll中有readFile这个io操作已经完成好的的回调,放在了poll,然后执行回调函数,检查到了setTImeout和setImmediate,分别放入timer队列,和check队列。接着执行完毕后会检查check队列,因为刚才已经放入一个了,所以会立马执行。然后等待setTimeout执行完之后再回到第一种往下执行,所以poll队列的特点是执行完当前队列会先检查有没有check队列的要执行,有的话会先执行第五个队列check的东西。
所以会出现这种情况。等待完毕后会往回去执行第一个timer队列里面的东西。
浏览器的特点是,先执行栈中代码,清空后为执行微任务,然后渲染页面,再从宏任务队列中取出一个来执行。node是先执行栈代码,执行完毕后,清空当前的微任务队列,会进入事件环中(evetloop),拿出一个来执行,执行完毕后再次清空当前微任务队列。(以前是一个队列! 清空完,再清空微任务,现在是一个执行完,就清空微任务,为的就是跟浏览器表现一致) global的其他重要属性 global上可以直接访问的属性叫全局属性,而requrei,exports,moudel也可以直接访问,但是不在global。因为每个文件都是一个模块,就好比自执行函数。如
(function(rqeuire, exports, module){})(require,exports,module) 他是作为入参传入,然后在这个模块就可以使用这些。而global上没有。
模块化 为什么要有模块化?
弗洛伊德算法选取某个节点k作为i到j需要经过的中间节点,通过比较d(i,k)+d(k,j)和现有d(i,j)的大小,将较小值更新为路径长度,对k节点的选取进行遍历,以得到在经过所有节点时i到j的最短路径长度,通过不断加入中间点的方式更新最短路径。
具体过程看下文:
给出一个有向图,并带有权值
1,先写出图的邻接矩阵 邻接矩阵中的元素就是有向图中两点的权值,不可直接到达的两个点的权值为无穷(∞)
2,选源点,求该源点到其他各点的最短路 从源点所在的那一行选出第一个权值最小的点,这里我们选v0为源点,权值最小是10,顶点为v2,
v0->vv2 最短路就是v0->v2 路径长度为10 为什么权值最小就是到达该店的最短距离? 说明:如果有到2这个点有更短的路径,第一个选择的顶点v2。
3,更新两点距离 选出v2这个顶点后,将其清除。已经选出了v0->v2这条路径,0到其他点的最短路径就可能相对之前会有所变化,这时候就要更新路径距离,用状态转移方程a[0][i]=min(a[0][i],a[0][2]+a[2][i])来更新权值。
更新后,选出顶点v3的最小权值25,并且将a[0][3]清除,并且重复上次更新操作。因为操作相同,在这里不一一画出了(偷懒了giao)
4,最短路径 5,求各个点之间的最短路径 上面举出求源点顶点v0的最短路径,要想求各个点的最短路径,只需要将源点更换,重复上述一样过程即可求出各点间的最短路径。
6弗洛伊德算法代码实现 #include <iostream> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f int main() { int a[21][21],m,n,i, j, w; for (int i = 1; i <= 20; i++) { for (int j = 1; j <= 20; j++) { if (i == j) {a[i][j] = 0;} else a[i][j] = INF; } } cin>>n>>m; for (int k = 1;k<= m;k++) { cin>>i>>j>>w; a[i][j] = w; a[j][i] = w; } for (int p = 1; p <= n; p++) { for (int i = 1; i <= n; i++) { if (a[i][p] == INF) continue; for (int j = 1; j <= n; j++) { if (i==j)continue; a[i][j] = min(a[i][j], a[i][p] + a[p][j]); } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { cout << a[i][j] << "
1.先检查系统是否装有mysql rpm -qa | grep mysql 如有,需要卸载
rpm -e mysqlXXX.rpm
2.下载mysql的repo源 cd /software
wget -c http://repo.mysql.com/mysql57-community-release-el7-9.noarch.rpm 如果提示没有wget 执行 yum -y install wget安装
3.安装mysql rpm包 rpm -ivh mysql57-community-release-el7-9.noarch.rpm
安装了这个,yum就可以在线安装mysql了,这里版本是mysql5.7.36
4.安装MySQL yum install mysql-server
5.重置MySQL密码 5.1首先,修改配置文件 vi /etc/my.cnf
在文件末尾增加一行跳过权限验证
skip-grant-tables
然后重启mysql
service mysqld restart
接着可以用root免密登录
mysql -uroot -p
直接回车不用输入密码
5.2修改密码 切换mysql库
use mysql;
执行修改密码命令
update user set authentication_string=password('123456') where user='root' and Host='localhost';
执行允许任意ip
UPDATE mysql.user SET Host='%' where user='root' AND Host='localhost' LIMIT 1;
看看是不是跳转前后 http 和 https 是否统一!!! 查了一下午,心态爆炸!
编写切面,可以加到公共模块里面,也可以放到网关层
/** * @author * @title: OpreateLogAop * @projectName commerce * @description: TODO * @date 2021/11/2919:06 */ @Aspect @Component public class OpreateLogAspect { private final static Logger LOGGER = LoggerFactory.getLogger(RequestLogAspect.class); @Pointcut("execution(* com.scm..*.controller..*(..))") public void requestServer() { } @Around("requestServer()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { OperateLogDTO log = new OperateLogDTO(); long beginTime = System.currentTimeMillis(); Object result = pjp.proceed(); try { ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (Objects.nonNull(sra)) { HttpServletRequest request = sra.
搭载NVIDIA Jetson Xavier NX的高算力“魔盒”来了!飞凌嵌入式发布AI边缘计算终端FCU3001
如果您正从事人工智能边缘计算的项目开发,那么英伟达推出的Jetson Xavier NX平台绝对是理想之选。作为Jetson系列的明星产品,Jetson Xavier NX用高达21 TOPS的算力和高性价比得到了广大工程师的青睐。
虽然英伟达推出了Jetson Xavier NX系统模组,但是对于一些缺少硬件开发经验的人工智能研发团队来说,在其基础上设计出稳定的终端产品仍然是一个挑战。此时,一款成熟稳定的硬件设备,无疑为专注算法和应用程序开发的用户带来了巨大帮助。AI边缘计算终端FCU3001应用而生。
一、性能强劲,人工智能和边缘计算的理想硬件 飞凌嵌入式推出的AI边缘计算终端FCU3001是一款搭载NVIDIAJetson Xavier NX的人工智能边缘计算设备,采用6核64位ARM架构处理器,其GPU拥有384个Volta核心和48个Tensor核心,算力高达21 TOPS,配置8GB LPDDR4内存和16GB eMMC存储,是实现嵌入式和边缘系统中高性能计算和人工智能的理想之选。
依托飞凌成熟的硬件设计经验所打造的FCU3001,将通过稳定的性能、小巧的体积、丰富的拓展性和便捷的安装方式,助力用户轻松实现人工智能边缘计算应用的批量化落地。
二、结构紧凑,拓展丰富 AI边缘计算终端 FCU3001结构紧凑,尺寸仅178*110*55mm,方便安装固定或嵌入到设备机箱。优秀的工业设计在保证产品坚固耐用的前提下实现了稳定的无风扇散热,可确保产品在21 TOPS满负载算力下长时间稳定运行。
AI边缘计算终端 FCU3001提供了丰富的功能拓展性,包括4xEthernet、2xUSB3.0、2xUSB2.0,方便接入各种传感器和外设,如连接摄像头进行图像采集等。同时还支持HDMI显示,以及RS485、CAN工业总线,实现视觉识别+设备联动的一站式控制。可拓展安装TF卡、SSD硬盘等存储设备,使数据存储不受局限。支持双频WiFi以及4G/5G通讯,与云端通信方式更灵活,让“5G+AI”为行业赋能。
三、静电防护设计,接口更稳定 AI边缘计算终端 FCU3001上的Ethernet、USB、RS485、CAN等接口全部具备ESD 4级防护能力,接触放电±8KV,空气放电±15KV,可以满足大部分应用场景下对静电防护的要求,让设备的运行和工作更稳定可靠。
四、定制化产品细节,打造优秀用户体验 FCU3001提供CUDA、cuDNN、TensorRT在内的丰富开发资料和开发工具,并将其优化整理打包,方便用户下载即用。
飞凌充分考虑用户产品化后的维护便捷性,因此FCU3001除支持英伟达原厂的OTG(须用Linux PC)更新操作系统外,还为用户提供了U盘(Windows)更新操作系统的方式,同时提供开机LOGO修改工具及操作指导,满足用户定制化需求。
五、强大“魔盒”,开启人工智能科技未来 作为一款可适用于多种行业的人工智能边缘计算设备,FCU3001搭载用户所开发的各种人工智能边缘计算算法与程序,便可激发出强大“魔力”,助力用户在相关领域开启科技未来。机器人、AGV、智能路况分析、视觉检测、无人驾驶、智慧医疗、智慧工厂,智慧城市, 更多AI边缘计算终端FCU3001强势应用,等您亲自解锁!
AI边缘计算终端FCU3001已正式发布,欢迎咨询飞凌嵌入式客服人员了解更多产品详情。
https://www.forlinx.com/article_view_790.html
swagger Swagger2ControllerWebMvc 返回值修改 有些场景下相对swagger-doc 返回的文档信息做些增强等. 但pringfox.documentation.swagger.v2.path 无法自定义controller , 所以可以使用切面方式拦截下最后序列化的地方.
序列化 @Aspect @Component @AllArgsConstructor public class SwaggerAspect { private final ServerProperties serverProperties; @Around("execution(* springfox.documentation.spring.web.json.JsonSerializer.toJson(..))") public Object switchDataSource(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); if (ArrayUtils.isEmpty(args)) { return joinPoint.proceed(args); } String serverIp = "127.0.0.1"; HttpServletRequest request = getRequest(); if (request != null) { serverIp = request.getHeader("X-GATEWAY-CLIENT-IP"); //如果是nvriot-saas-uaa需要改成ip ? if (StringUtils.isEmpty(serverIp)) { //获取本机 serverIp = NetUtils.localIP() + ":" + serverProperties.getPort(); } } String finalServerIp = serverIp; Arrays.
有时候一个变量命名要想上半天,怎么命名合适,怎么才不显得别扭,怎么才显得更舒适,下面提供一些参考,如果某个变量意义一个单词无法表达,可以用多个单词缩写然后用下划线间隔表达,譬如:文件地址:file_addr
A
addr = address
app = application
arg = argument
asm = assemble
asyn = asynchronization
auth = authorization / authentication
avg = average
B
buf = buffer
btn = button
C
calc = calculate
cert = certificate
cmd = command
cmp = compare
col = column
coord = coordinates
cur = current
D
db = database
dec = decrease
del = delete
dst = destination
dev = device
浅析SSL/TLS的会话流程和源码实现 一、SSL/TLS的概念二、SSL/TLS的会话交互流程(1) client_hello(2) server_hello + certificate + sever hello done(3) client key exchange + change cipher spec + encrypted handshake message(4) new session ticket+change cipher spec+envrypted handshake message 三、源码实现 一、SSL/TLS的概念 官方解释TLS叫做安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。SSL就是TLS的前身,从最初的SSL3到现在的TLS 1.3,其协议核心并没有大幅改变。只是为了解决几个安全性问题。TLS实际是在明文的上层和 TCP 层之间加上一层加密,这样就保证上层信息传输的安全,所以在网络模型中它运行于传输层之上,隶属于会话层。实际应用例如在浏览器访问中,在HTTP 协议中加上 SSL 层之后,就有了HTTPS。
二、SSL/TLS的会话交互流程 ssl实际应用中具体的交互流程如下图所示:
(1) client_hello 客户端发起协议交互请求,其中包含tls的版本信息,加密套件候选列表,随机数等相关信息,以我们的设备为例抓包来分析具体实况:
tls的版本信息主要是当前客户端所支持的最高 TLS 协议版本 ,目前已有的TLS 协议版本总共有五种,从低到高依次 SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2客户端所支持的加密套件cipher suites, 每个加密套件对应TLS 原理中的四个功能的组合: 认证算法 Au (身份验证)密钥交换算法 KeyExchange (密钥协商)对称加密算法 Enc (信息加密)信息摘要 Mac (完整性校验) 随机数 random_C,用于后续的密钥的生成 (2) server_hello + certificate + sever hello done server_hello, 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 等,其中随机数用于后续的密钥协商server_certificates, 服务器端配置对应的证书链,用于身份验证与密钥交换server_hello_done,通知客户端 server_hello 信息发送结束 (3) client key exchange + change cipher spec + encrypted handshake message client_key_exchange: 合法性验证通过之后,客户端计算产生随机数字 pre-master,并用证书公钥加密,发送给服务器此时客户端已经获取全部的计算协商密钥需要的信息:两个明文随机数 random_C 和 random_S 与自己计算产生的 pre-master,计算得到协商密钥enc_key=Fuc(random_C, random_S, pre-master)change_cipher_spec: 客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信;encrypted_handshake_message: 结合之前所有通信参数的 hash 值与其它相关信息生成一段数据,采用协商密钥 session secret 与算法进行加密,然后发送给服务器用于数据与握手验证 (4) new session ticket+change cipher spec+envrypted handshake message session ticket,SessionTicket是一种不需要服务器端状态的,恢复TLS session的方式。SessionTicket可以用于任何CipherSuite,服务器如果使用 SessionTicket 机制,服务器需要把本地的 session 状态存入一个ticket中,ticket会被加密,并被MAC保护,无法篡改,加密和算MAC用的key只有服务器知道。加密并MAC过的ticket用 NewSessionTicket 消息分发给客户端, 客户端把收到的ticket和master secret等其它与当前session有关的参数一起,缓存起来。当客户端希望恢复会话时,就把ticket包含在 ClientHello 的 SessionTicket 扩展中发给服务器。服务器收到后,解密ticket,算MAC确认ticket没有被篡改过,然后从解密的内容里面,获取session 状态,用来恢复会话。如果服务器成功地验证了ticket,可以在 ServerHello 之后返回一个 NewSessionTicket 消息来更新ticket。服务器用私钥解密加密的 pre-master 数据,基于之前交换的两个明文随机数 random_C 和 random_S,计算得到协商密钥:enc_key=Fuc(random_C, random_S, pre-master); 计算之前所有接收信息的 hash 值,然后解密客户端发送的 encrypted_handshake_message,验证数据和密钥正确性;change_cipher_spec, 验证通过之后,服务器同样发送 change_cipher_spec 以告知客户端后续的通信都采用协商的密钥与算法进行加密通信;encrypted_handshake_message, 服务器也结合所有当前的通信参数信息生成一段数据并采用协商密钥 session secret 与算法加密并发送到客户端; 三、源码实现 这里针对ssl的交互流程,我们搭配openssl的库来实现一套具体的交互配置流程,前提是我们已经申请过了CA证书。
一、列转行 1、背景描述 在日常处理数据过程中,你们可能会经常遇到这种类型的数据:
而我们用pandas进行统计分析时,往往需要将结果转换成以下类型的数据:
2.方法描述 准备数据
df = pd.DataFrame({'姓名': ['A','B','C'], '英语':[90,60,70], '数学':[80,98,80], '语文':[85,90,75]}) 这个实现的方法有多种形式,这里集中进行展示
2.1 方法1 tmp=df.set_index(['姓名']).stack() tmp2=tmp.rename_axis(index=['姓名','科目']) tmp2.name='分数' tmp2.reset_index() 2.2 方法2 tmp=df.set_index(['姓名']).stack() tmp.index.names=['姓名','科目'] tmp.reset_index(name='分数') 2.3 方法3 tmp=df.set_index(['姓名']).stack().reset_index() tmp.columns=['姓名','科目','分数'] 2.4 方法4 tmp=pd.melt(df,id_vars='姓名',var_name='科目',value_name='分数') 3 思考与总结 通过上述的对比,相信各位已经明白其中的厉害之处了,下面就来重点讲解一下melt这个函数。melt函数共有以下几个:
frame: 需要处理的数据帧id_vars: 不需要做列转行处理的字段,如果不设置该字段则默认会对所有列进行处理value_vars: 需要做列转行的字段,不指定则不处理var_name: 列转行处理后,生成字段列,对列转行之前的字段名称进行重命名value_name: 列转行处理后,生成数值列,对列转行之前的数值进行命名col_level: 指定具体的列名等级,通常在有多级列名时使用。 4 思维延伸 4.1 例子1 转换前:
转换后:
实现的1种方法:
#准备数据 df2 = pd.DataFrame({'姓名': ['A', 'B', 'C'], '班级':[1,2,1], '期中考试-英语': [90, 60, 70], '期中考试-数学': [80, 98, 80], '期中考试-语文': [85, 90, 75], '期末考试-英语': [92, 63, 76], '期末考试-数学': [85,100, 89], '期末考试-语文': [87, 91, 80]}) #实现部分 t1=pd.
74HC595驱动四位数码管 数码管编码 出处硬件原理图 出处驱动程序 出处 1.数码管编码介绍 它每一段是一个发光二极管,排成一个“日”字形。通过控制某几段发光二极管的发光来显示数字0~9或字母A、B、C、D…。通常有8个发光二极管,其中七个为日字型,另外一个发光二极管表示小数点。如图1所示,如a、b、g、e、d段亮显示2;f、b、e、c、g段亮显示H。注意:dp段表示右下角的小数点。
连接分为共阳极和共阴极两种接法。(1)共阳极数码管所有发光二极管阳极连在一起,接高电平。而阴极通过串联一个限流电阻接在驱动器一侧。当一段输出为低电平时,发光二极管导通而发光。(2)共阴极数码管是所有的发光二极管的阴极接在一起接地,阳极串联一个限流电阻接在驱动器一侧。当某段输出为高电平时,发光二极管导通发光。如下图2、图3。
相应得出,共阳极对应编码(小数点用最高位表示)。
unsigned char LED_0F[] =
{// 0 1 2 3 4 5 6 7 8 9 A b C d E F -
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf
};
2.硬件原理图 本设计使用了一个4位的数码管,为共阳型,为了节省单片机的IO口,使用了两片74HC595作为数码管的驱动芯片,共占用3个IO口。
与单片机相连接的三个脚分别为: HC_DAT,HC_RCK,HC_CLK。两片595采用级联方式,即U2的第9脚接到U3的第14引脚。
74HC595是8位的移位寄存器,串入并出,并具有锁存功能,被广泛的用于数码管、点阵的驱动电路中。其管脚介绍如下:
15: 数据输出A-接数码管数据A段;
l: 数据输出B-接数码管数据B段;
2: 数据输出C-接数码管数据C段;
3: 数据输出D-接数码管数据D段;
4: 数据输出E-接数码管数据E段;
5: 数据输出F-接数码管数据F段;
6: 数据输出G-接数码管数据G段;
7: 数据输出H-接数码管数据H段;
16: 电源正脚-接电源正;
8: 电源负脚=接电源负;
14: 数据输入脚-接单片机管脚;
12: 数据锁存时钟-接单片机管脚;
11: 数据输入时钟-接单片机管脚;
13: 使能输出脚-低电平有效,接低电平;
10 :数据清零-不清零,接高电平;
9:数据级联输出-接下一片595的数据输入脚
html中所有元素都可以看成一个盒子,他包括边距,边框,填充,实际内容
简单来说盒子模型分为两种:
W3C盒子模型(标准盒模型)
设置width的时候,指的是单纯content的宽高 盒子宽高=content+padding+border+margin IE盒模型(怪异盒模型)
设置width的时候,指的是content+padding+border的宽高 盒子宽高=width(content+padding+border)+margin 设置盒子模型(css指定盒子模型种类)
box-sizing: content-box 设置为w3c模型 box-sizing: border-box 设置为IE盒模型 box-sizing: inherit 从父元素继承
chmod用于改变文件或目录的访问权限。用户用它控制文件或目录的访问权限。该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。
1. 文字设定法
语法:chmod [who] [+ | - | =] [mode] 文件名
命令中各选项的含义为:
操作对象who可是下述字母中的任一个或者它们的组合:
u 表示“用户(user)”,即文件或目录的所有者。
g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。
o 表示“其他(others)用户”。
a 表示“所有(all)用户”。它是系统默认值。
操作符号可以是:
+ 添加某个权限。
- 取消某个权限。
= 赋予给定权限并取消其他所有权限(如果有的话)。
设置 mode 所表示的权限可用下述字母的任意组合:
r 可读。
w 可写。
x 可执行。
X 只有目标文件对某些用户是可执行的或该目标文件是目录时才追加x 属性。
s 在文件执行时把进程的属主或组ID置为该文件的文件属主。
方式“u+s”设置文件的用户ID位,“g+s”设置组ID位。
t 保存程序的文本到交换设备上。
u 与文件属主拥有一样的权限。
g 与和文件属主同组的用户拥有一样的权限。
o 与其他用户拥有一样的权限。
文件名:以空格分开的要改变权限的文件列表,支持通配符。
在一个命令行中可给出多个权限方式,其间用逗号隔开。例如:
chmod g+r,o+r example % 使同组和其他用户对文件example 有读权限。
2. 数字设定法
我们必须首先了解用数字表示的属性的含义:0表示没有权限,1表示可执行权限, 2表示可写权限,4表示可读
权限,然后将其相加。所以数字属性的格式应为3个从0到7的八进制数,其顺序是(u)(g)(o)。
MPLS VPN适用于公司各分支机构访问公司总部场景。公司的各点可以通过多种方式连接到MPLS VPN网络和MPLS VPN网络完成后,可以实现任何一点到其他各点的连接,任何地方都可以访问其他地方的资源,同时实现企业内部安全性的要求。
知识点 单源最短路径:Dijkstra
Dikstra算法也用来解决单源最短路径问题。Dijkstra是非常高效而且稳定的算法。
Bellman-Ford算法,提到它在现实中的模型是找警察问路。在现实中 Dijkstra有另外的模型,例如多米诺骨牌,可以想象下面的场景:
在图中所有的边上排满多米诺骨牌,相当于把骨牌看成图的边。一条边上的多米诺骨牌数量和边的权值(例如长度或费用)成正比,规定所有骨牌倒下的速度都是一样的。如果在一个结点上推倒骨牌,会导致这个结点上的所有骨牌都往后面倒下去。
在起点 s s s 推倒骨牌,可以观察到,从 s s s 开始。它连接的边上的骨牌都逐渐倒下,并到达所有能达到的结点。在某个结点 t t t ,可能先后从不同的线路倒骨牌过来;先倒过来的骨牌,其经过的路径肯定就是从 s s s 到达 t t t 的最短路径;后倒过来的骨牌,对确定结点 t t t 的最短路径没有贡献,不用管它。
从整体看,这就是一个从起点;扩散到整个图的过程。在这个过程中观察所有结点的最短路径是这样得到的:
在 s s s 的所有直连邻居中,最近的邻居 u u u ,骨牌首先到达。 u u u 是第一个确定最短路径的结点。从 u u u 直连到 s s s 的路径肯定是最短的,因为如果 u u u 绕道别的结点到 s s s ,必然更远。然后,把后面骨牌的倒下分成两个部分,一部分是从 s s s 继续例下到 s s s 的其他的直连邻居,另一部分是从 u u u 出发倒下到 u u u 的直连邻居。那么下一个到达的结点 v v v 必然是 s s s 或者 u u u 的一个直连邻居。 v v v 是第二个确定最短路径的结点。继续以上步骤,在每一次迭代过程中都能确定一个结点的最短路径。 Dijkstra算法应用了贪心法的思想,即“抄近路走"
问题: 将exe程序设置为开机自启动,启动后最小化至托盘。
思路: 1、程序开机自启动:修改注册表RegOpenKeyEx
2、程序最小化至托盘:Shell_NotifyIcon创建托盘对象
3、开机自启动和双击打开的区分:增加启动命令参数,使用GetCommandLine获取命令内容
解决: 1、设置程序开机自启动,修改注册表信息。
bool ModifyRegedit(bool bAutoRun) { charpFileName[MAX_PATH] = { 0 }; DWORD dwRet = GetModuleFileName(NULL, (LPWSTR)pFileName, MAX_PATH); HKEY hKey; LPCTSTR lpRun = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"); long lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpRun, 0, KEY_WRITE, &hKey); if(lRet != ERROR_SUCCESS) return false; if (bAutoRun) RegSetValueEx(hKey, _T("AutoRun"), 0, REG_SZ, (const BYTE*)(LPCSTR)pFileName, MAX_PATH); else RegDeleteValueA(hKey, "AutoRun"); RegCloseKey(hKey); return true; } 2、 程序最小化至托盘。
//.h NOTIFYICONDATA m_trayIcon; //!< 定义托盘图标对象 //资源中添加程序托盘图标bmp文件 IDR_TRAYICON //.cpp void CreateTrayIcon() { CreateSemaphore(NULL, 1, 1, _T("
前言 在参考李沐老师《动手学深度学习》tensorflow版本实现多层感知机时,需要安装"d2lzh_tensorflow2"包,笔者尝试直接pip install d2lzh,却出现了以下错误:
AttributeError: ‘tensorflow.python.framework.ops.EagerTensor’ object has no attribute ‘sum’
初步判断是d2lzh包的版本问题。
解决方式 到github项目中下载d2lzh_tensorflow2文件。
地址:https://github.com/TrickyGo/Dive-into-DL-TensorFlow2.0/tree/master/code
将d2lzh_tensorflow2文件夹拷贝到自己的项目目录中。
运行报错: ModuleNotFoundError: No module named ‘tqdm’
在终端中执行 pip install tqdm,重新运行。
输出正常。 epoch 1, loss 0.8183, train acc 0.694, test acc 0.816
epoch 2, loss 0.4892, train acc 0.818, test acc 0.834
epoch 3, loss 0.4206, train acc 0.843, test acc 0.851
epoch 4, loss 0.3869, train acc 0.856, test acc 0.859
epoch 5, loss 0.
1.介绍
论文研究了gnn中的其他计算模块,如跳过连接和池化操作。
Skip Connections(或 Shortcut
Connections),跳过连接,会跳过神经网络中的某些层,并将一层的输出作为下一层的输入。
gnn分为四类:循环图神经网络、卷积图神经网络、图自编码器和时空图神经网络。
论文讨论了异构图、动态图和组合优化的gnn
论文的贡献是:提供了对现有图神经网络模型的详细回顾。提出了一个通用的设计管道,并讨论了每个模块的变体。本文还介绍了GNN模型的理论研究和实证分析。我们对应用程序进行系统分类,将应用程序分为结构化场景和非结构化场景。我们针对每个场景给出了几个主要的应用程序及其相应的方法。我们提出四个有待进一步研究的问题。我们对每个问题进行了深入的分析,并提出了未来的研究方向。
2.GNN模型设计的一般流程:
该流程包括四个步骤:(1)查找图的结构,(2)确定图的类型和比例,(3)设计损失函数,(4)使用计算模块构建模型。
2.1查找图结构
必须找出应用程序中的图结构。通常有两种场景:结构化场景和非结构化场景。在结构型场景中,图形结构在分子、物理系统、知识图等应用中是明确的。在非结构化场景中,图是隐式的,因此我们必须首先从任务中构建图,例如为文本构建一个完全连接的“单词”图,或为图像构建一个场景图。在我们得到这个图之后,后面的设计过程试图在这个特定的图上找到一个最优的GNN模型。
2.2确定图的类型和比例
在应用程序中获得图形后,我们必须找出图形类型及其比例。具有复杂类型的图可以提供关于节点及其连接的更多信息。图表通常被分类为:
有向图/无向图:有向图中的边都是从一个节点指向另一个节点,这比无向图提供了更多的信息。无向图中的每条边也可以看作是两条有向边。
同构图/异构图:同构图中的节点和边具有相同的类型,异构图中的节点和边具有不同的类型。节点和边的类型在异构图中起着重要的作用,需要进一步考虑。
静态图/动态图:当图的输入特征或拓扑随时间变化时,将图视为动态图。在动态图中应该仔细考虑时间信息。
注意,这些类别是正交的,这意味着这些类型可以组合,例如,可以处理动态有向异构图。还有一些其他的图类型是为不同的任务设计的,比如超图和符号图。我们不会在这里列举所有类型,但最重要的想法是考虑这些图表提供的附加信息。一旦我们指定了图形类型,在设计过程中应该进一步考虑这些图形类型提供的附加信息。在图的尺度上,对于小图和“大”图并没有明确的分类标准。这个标准仍然随着计算设备(例如gpu的速度和内存)的发展而变化。在本文中,当一个图(空间复杂度isOðn2Þ)的邻接矩阵或图拉普拉斯算子不能被设备存储和处理时,我们将该图视为一个大规模图,然后考虑一些采样方法。
2.3设计损失函数
在这一步中,我们需要根据我们的任务类型和训练设置来设计损失函数。对于图学习任务,通常有三种任务:
节点层数:任务以节点为中心,包括节点分类、节点回归、节点聚类等。节点分类试图将节点分类为几个类,节点回归预测每个节点的连续值。节点聚类的目的是将节点划分为几个不相交的组,相似的节点应该在同一组中。
边层数:任务是边缘分类和链接预测,这需要模型对边缘类型进行分类或预测给定的两个节点之间是否存在一条边
图层数:任务包括图分类、图回归和图匹配,所有这些都需要模型来学习图的表示。
从监督的角度,我们也可以将图学习任务分为三种不同的训练设置:
监督环境:为训练提供标记数据
半监督环境:为训练提供了少量的标记节点和大量的未标记节点。在测试阶段,转导设置要求模型预测给定的未标记节点的标签,而归纳设置提供来自相同分布的新的未标记节点来推断。大多数节点和边缘分类任务是半监督的。最近,wang和Leskovec(2020)以及rossi等人(2018)提出了一种混合的转导-诱导方案,寻求通向混合环境的新途径。
非监督环境:只提供未标记的数据供模型查找模式。节点聚类是典型的无监督学习任务。
通过任务类型和训练设置,我们可以为任务设计一个特定的损失函数。例如,对于节点级半监督分类任务,交叉熵损失函数可以用于训练集中标记的节点。
2.4使用计算模块构建模型
最后,我们可以开始使用计算模块构建模型。一些常用的计算模块有:
传播模块:传播模块用于在节点之间传播信息,从而聚合的信息既可以捕获特征信息,也可以捕获拓扑信息。在传播模块中,通常使用卷积算子和递归算子来聚合邻居的信息,而跳过连接操作则用来从节点的历史表示中收集信息,从而缓解过平滑问题
采样模块:当图较大时,通常需要采样模块对图进行传播。采样模块通常与传播模块结合使用。
池化模块:当我们需要高级子图或图的表示时,需要池模块从节点中提取信息
利用这些计算模块,通常将它们结合起来建立一个典型的GNN模型。图的中间部分给出了GNN模型的典型结构。其中利用卷积算子、递归算子、采样模块和跳跃连接在每一层传播信息,然后加入池化模块提取高层信息。这些层通常是堆叠起来以获得更好的表示。注意,这种架构可以推广大多数GNN模型,但也有例外,例如,NDCN
(zan和Wang,
2020)结合了常微分方程系统(ode)和GNN。它可以被看作是一个连续时间的GNN模型,在连续时间内集成GNN层,而不通过一个离散的层数传播。图中显示了通用设计管道的说明。
3.计算模块的实例化
在本节中,我们将介绍三个计算模块的现有实例化:传播模块、采样模块、和池化模块。我们分别在3.1节、3.2节和3.3节中介绍了传播模块的三个子组件:卷积算子、递归算子和跳跃连接。然后在3.4节和3.5节中介绍了采样模块和池模块。GNN模型的一般设计管道和计算模块的概述如图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vga46pqA-1638176337186)(media/cf6c624f2cbfe45a80388f36ee8c3c71.png)]
GNN模型的一般设计管道
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XogT6oK8-1638176337190)(media/20fbc7992e7d7d79bcd5dacff7fe7029.png)]
计算模块的概述
3.1传播模块-卷积算子
本节介绍的卷积算子是GNN模型中最常用的传播算子。卷积算子的主要思想是将卷积从其他域推广到图域。这方面的进展通常分为光谱方法和空间方法。
3.1.1谱方法
谱方法使用图的谱表示。这些方法在理论上基于图信号处理(Shuman et al.,
2013),并在谱域定义卷积算子。在谱方法中,首先通过图的傅里叶变换f将图信号变换到谱域,然后进行卷积运算。卷积后,结果信号用反图傅里叶变换f
’ 1进行变换。这些转换定义为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jFmEvjzr-1638176337192)(media/50892b9a0d95ed715a1abd8babf20312.png)]
这里是归一化图拉普拉斯特征向量的矩阵:(其中为N维单位向量)D是度矩阵,是图的邻接矩阵,归一化图拉普拉斯算子是实对称正半正定的,所以它可以分解为
Λ是特征值的对角矩阵,基于卷积定理(Mallat, 1999),将卷积运算定义为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wT4gajlR-1638176337195)(media/ee7393a65381a21fa2bcf3337f0b1de2.png)]
其中为光谱域的滤波器,如果我们简化过滤器通过使用一个可学习的对角矩阵,然后我们有了光谱方法的基本函数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jPAFuAf5-1638176337197)(media/aee2a34825acc14d08f5c04807d632dc.png)]
接着介绍了几种设计不同滤波器的典型光谱方法 。
光谱网络:光谱网络使用可学习对角矩阵作为滤波器,这是=diag(w),
是作为参数,然而,这种操作的计算效率很低,而且过滤器是非空间本地化的。Henaff等人(2015)试图通过引入光滑系数参数化来实现光谱滤波器的空间局部化。
ChebNet:Hammond等人(2011)认为可以通过切比雪夫多项式上升到排序,Defferrard等(2016)基于这一理论提出了ChebNet。因此,这个运算可以写成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2R6aldaZ-1638176337199)(media/a97e0d69d79f7231fef813fba3b8d51f.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONTYySV9-1638176337202)(media/20b5204605289825fadacc359eff1884.png)]表示L的最大特征值。的取值范围是[-1,1],
是切比雪夫系数的向量。
切比雪夫多项式定义为当=1和=x
由于在拉普拉斯变换中是一个k阶多项式,因此可以看出操作风险是局部化的。Defferrard等人(2016)使用这种k
gradle版本过低,修改项目gradle文件中的gradle版本到4.2.0+
问题;
输入两个数x和y,如果x或y小于等于0,则提示输入正整数,求这两个数的最大公约数和最小公倍数。
注意:可以用欧几里得辗转相除算法来求最大公约数。最小公倍数的计算方法是两数的乘积除以两数最大公约数的结果。
python代码如下:
x=int(input()) y=int(input()) if x<=0 or y<=0: print("请输入正整数") if x<y: x,y=y,x v1=x*y v2=x%y while v2!=0: x=y y=v2 v2=x%y v1=v1/y print("最大公约数为:%d"%y) print("最小公倍数:%d"%v1) 这种提属于基础算法类型,较为简单!
感谢观看!
1、在java中可以通过变量表示数组的长度,定义数组的时候传递这个变量,new String[length]
,就可以在程序运行的时候动态定义一个数组
下面是示例代码:
public class Test { public static void main(String[] args) { String[] strArray = createArray(5); } static String[] createArray(int length) { //虽然说在java中数组的长度是固定的,在定义的时候就必须指定,但是你传递一个变量给它也是行的 return new String[length]; } } 2、在java里,数组属于引用类型,
int[] arr; //声明一个int型数组的引用变量
…
arr = new int[n];//n在运行时确定长度。
使用场景 系统压力测试时,想简单记录一下系统什么时间死机。就用python写一个定时一分钟往txt文件写入当前时间的脚本。
实现代码 # !/usr/bin/python # coding=UTF-8 import time import os # 生成log文件 def Numberlog(): nowtime = time.strftime('%Y_%m_%d_%H_%M_%S',time.localtime(time.time())) print(nowtime) # 时间写入日志文件 with open('time_log.txt','a+',newline='') as screen_log: screen_log.writelines(nowtime) screen_log.writelines("\n") screen_log.close() # count=0 while True: Numberlog() # count += 1 count=len(open('time_log.txt','r').readlines()) # 记录一下写入次数 with open('number.txt','w',newline='') as number: number.write(str(count)) number.close() time.sleep(60) #定时60s看一下
感谢《机器人工程师进阶之路:matlab-robotics-toolbox安装方法》
目录
一、matlab-robotics-toolbox安装方法
二、改进DH法对myCobot进行仿真
一、matlab-robotics-toolbox安装方法 【来自知乎】:
Matlab中关于机器人的应用程序还是蛮多的。Peter为了方便教学和研发,他和他的团队开发了Robotics Toolbox这么一个工具箱。
工具箱介绍和安装方法都在下面这个链接中可以找到 https://petercorke.com/toolboxehttps://link.zhihu.com/?target=https%3A//petercorke.com/toolboxes/robotics-toolbox/
打开官方网站,选择RTB10.4.mltbx,进行下载
将下载好的RTB10.4.mltbx移动到matlab的工作文件夹下。打开matlab,在matlab浏览器找到安装包,双击打开。选择合适的文件夹进行安装。
在matlab命令窗口,执行命令。
>> rtbdemo 出现如下界面即表示安装成功!
二、改进DH法对myCobot进行仿真 还记得完整的DH法参数吗?
具体的matlab代码如下:
clear,close all %% MDH figure %% 建立机器人MDH参数,初始姿态为竖直。 ML(1) = Link('d', 180, 'a', 0, 'alpha', 0, 'offset',0, 'modified'); ML(2) = Link('d', 0, 'a', 0, 'alpha', pi/2, 'offset',pi/2, 'modified'); ML(3) = Link('d', 0 , 'a', 140, 'alpha', 0, 'offset',0, 'modified'); ML(4) = Link('d', 90, 'a', 100, 'alpha', 0, 'offset',pi/2, 'modified'); ML(5) = Link('d', 80, 'a', 0, 'alpha', pi/2, 'offset',-pi/2, 'modified'); ML(6) = Link('d', 60, 'a', 0, 'alpha', pi/2, 'offset',0, 'modified'); robotM=SerialLink(ML,'name','mycobot_6L3-MDH'); robotM.
目录 一、编程思路二、代码三、运行效果 一、编程思路 大概思路:
1、打印出界面(40*40) initscr();//ncurses界面的初始化函数 GraphInterface();//打印界面 getch();//当用户按下某个字符时,函数自动读取,无需按回车 endwin();//恢复终端机原来的状态 2、初始化蛇身 2.1 确定蛇身的初始位置(一个节点) 2.2 添加蛇神的节点(总共3-4个) 3、识别键盘,开始对进行蛇进行移动 3.1移动蛇身 3.1.1 如向右移动,向右添加一个节点,左边删除一个节点 3.1.2 如向左移动,向左添加一个节点,右边删除一个节点 3.1.3 如向上移动,向上添加一个节点,下边删除一个节点 3.1.4 如向下移动,向下添加一个节点,上边删除一个节点 3.2 移动完蛇身,要进行界面的刷新 (1)再打印一次页面 (2)move(0,0);加载到打印函数里面 4、创建线程th1,让蛇身初始移动方向向右(每半秒刷一次) 5、创建线程th2,不断检测按键来改变蛇的移动方向 6、主函数要在程序结束之前有个while(1);防止程序退出; 7、初始化食物位置,random()随机 8、界面初始化中,找到食物的位置,打印食物 9、判断食物是否被蛇碰到,碰到的话添加一个节点 10、判断食物死亡的情况,两种:边界和碰到自己蛇身 二、代码 #include <stdio.h> #include <ncurses.h> #include <stdlib.h> #include <pthread.h> #define UP 1 #define DOWN -1 #define LIGHT 2 #define RIGHT -2 int graphLength = 0; int graphWide = 0; int keyValue; int dir = 0; struct Snake { int hang; int lie; struct Snake *next; }; struct Snake food; struct Snake *head = NULL; struct Snake *tail = NULL; //蛇食物的位置(随机) void initFood() { int x=rand()%20;//随机位置 int y=rand()%20; food.
目录
数据类型简介
数据存储(整型+浮点型)
整型存储
大小端
浮点型存储
实践练习
今天我们来了解一下数据在内存中是如何存储的 看看下面的代码可以算出结果嘛,如果不确定或是有不会的就请看完这篇博客,相信对你有不少帮助
数据类型简介 char //字符数据类型 1字节 short //短整型 2字节 int //整形 4字节 long //长整型 4字节 long long //更长的整形 8字节 float //单精度浮点数 4字节 double //双精度浮点数 8字节 注意在C语言中没有字符串类型,字符串是由char类型的数组定义的
类型的意义: 1. 使用这个类型开辟内存空间的大小(大小决定了使用范围) 2. 如何看待内存空间的视角 数据存储(整型+浮点型) 我们知道一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的,我们接着看看数据是如何在内存中开辟空间存储的 整型存储 a为什么是按照这样在内存中存储的呢
这时我们就要先介绍一下整型在内存中是如何存储的
计算机中整型数据有三种表示方式 原码 补码 反码
正数:正数的原、反、补码都相同
负数:负数的三种表示形式不同
原码 ——>符号位不变其他位按位取反——>反码——>+1——>补码
整型数据在内存中都是以补码方式存储的
知道了原反补的知识我们发现还是不能解释数据的存储
我们发现存储的顺序好像是反的这是为什么呢?
这时就要了解大小端知识了
大小端 大端存储 :是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中 小端存储 :是指数据的低位保存在内存的低地址中,而数据的高位, ,保存在内存的高地 址中 为什么存在大小端呢
因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit 对于大于一字节的类型存储方式就会有多种方式,每种存储又没有否定的理由所以出现了大端存储和小端存储(大部分计算机小端储存)
知道这些我们来看看一道面试题来加深对于大小端的理解
请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序 我们来试试实现代码
immediate :首次加载执行函数,默认为false。deep:需要监听的数据的深度,一般用来监听对象中某个属性的变化,数组字符串一般不需要,默认为false。handle:watch中需要具体执行的方法。
官方:watch监听器 watch:{ "total":{ // total要监听的变量 immediate:true, // 首次加载的时候执行函数 deep:true, // 深入观察,监听数组值,对象属性值的变化 handler:function(){ } }
#include<bits/stdc++.h> using namespace std; int main() { int n,sh; int h_1=0,h_5=0,h_10=0; int i; cin>>n; for(i=1; i<=n; i++) { cin>>sh; if(sh==1) h_1++; if(sh==5) h_5++; if(sh==10) h_10++; } cout<<h_1<<endl; cout<<h_5<<endl; cout<<h_10<<endl; return 0; }
后端小白在进行IDEA数据库连接的时候会进行以下报错
这是没有mysql驱动的问题
填错了就会报以下的错误哦
解决方法:在URL后面添加: ?serverTimezone=GMT
从之前比较熟悉的Python转到新学的C++, 踩了一些坑之后,总结出了以下的C++和Python的等号操作的区别,
C++ 和 Python 的赋值操作("=")的区别 C++ 的赋值操作总是默认执行拷贝 拷贝出来的副本与原来变量的地址不同除非是指针拷贝给指针的浅拷贝才会指向相同地址auto a = b; 改变b之后并不会改变a Python赋值分两种情况,对于a = b, 可变类型的赋值默认使用引用方式(可变类型包括列表、字典、自定义类等;a和b指向相同内存,改变b之后a也会跟着改变)不可变类型的赋值默认使用拷贝方式(不可变类型包括字面值, tuple等;a和b地址不同,b的改变不影响a) 关于两者区别的思考 Python的等号操作,对于可变类型,默认以引用方式赋值,主要原因应该在于节省时空开销, 可变类型如列表、字典、数组、自定义类等,其占用内存空间有可能非常大,如果非要拷贝到新地址中,内存空间需要新开辟一份,且拷贝操作也需要花时间,在大数据量的情况下时间和空间开销都可能非常大;引用方式则可以节省掉上述的开辟新空间以及拷贝操作。把默认方式设置为合理高效的方式,可以节省人类精力,使人机交互更加方便引用计数器记录一个对象被引用多少次,直到引用次数为0则销毁该对象,节省内存非要copy的话,可以用a = copy.deepcopy(b) C++ 的等号操作,默认拷贝赋值,原因可能在于C++是相对底层一些的语言,需要靠开发者来发挥操作自由度, 根据实际情况设计对应的高效合理的方式 想要用引用的方式来避免拷贝的话,可以用"&"符号,比如 auto& a = b;
算法思想(递归) 左边界为l 右边界为r 当l>=r的时候 排序结束
不断取中点递归两边 从小回推出大
下面是实现
0000000
i
0000000
j
这里有两条队列
比较a[i]和a[j]大小
小的存到新数组中存储
直到有一个列表已经被删去了
此时对剩下的列表进行扫尾
并将结果赋回给原数组 以进行下一步的递归
代码模板如下
void Merge_sort(int a[],int l,int r) { if(l>=r) return; int mid=(l+r)>>1;int i=l,j=mid+1,k=0; Merge_sort(a,l,mid),Merge_sort(a,mid+1,r); while(i<=mid && j<=r) { if(a[i]<a[j]) tem[k++] = a[i++]; else tem[k++] = a[j++]; } while(i<=mid) tem[k++] = a[i++]; while(j<=r) tem[k++] = a[j++]; for(int i=l,j=0;i<=r;i++,j++) a[i] = tem[j]; }
文章目录 卷积神经网络CNN卷积CNN基本原理经典CNNLeNet-5AlexNetVGGNet CNN主要应用 卷积神经网络CNN 之前我们介绍了全连接神经网络,它的权重矩阵的参数非常多。
而且往往自然图像中的物体都具有局部不变性特征,即尺度缩放、平移、旋转等操作不影响其语义信息,但是全连接前馈网络很难提取这些局部不变特征,这就引出了我们将要介绍的卷积神经网络(Convolutional Neural Networks,CNN)。
卷积神经网络也是一种前馈神经网络,是受到生物学上感受野(感受野主要是指听觉系统、本体感觉系统和视觉系统中神经元的一些性质)的机制而提出的(在视觉神经系统中,一个神经元的感受野是指视网膜上的特定区域,只有这个区域内的刺激才能够激活该神经元)。
卷积 (f*g)(n)成为 ff 和 gg 的卷积,连续卷积和离散卷积可以表达为如下形式:
卷积有很多应用,经常用于处理一个输入,通过系统产生一个适应需求的输出。
在图像处理中,图像是以二维矩阵的形式输入到神经网络中,因此我们需要二维卷积。
CNN基本原理 卷积神经网络的基本结构大致包括:卷积层、激活函数、池化层、全连接层、输出层等。
经典CNN LeNet-5 LeNet-5由LeCun等人提出于1998年提出,主要进行手写数字识别和英文字母识别。经典的卷积神经网络,LeNet虽小,各模块齐全,是学习 CNN的基础。
网络结构
AlexNet AlexNet由Hinton的学生Alex Krizhevsky于2012年提出,获得ImageNet LSVRC-2012(物体识别挑战赛)的冠军,1000个类别120万幅高清图像(Error: 26.2%(2011) →15.3%(2012)),通过AlexNet确定了CNN在计算机视觉领域的王者地位。
VGGNet VGGNet由牛津大学和DeepMind公司提出
Visual Geometry Group:https://www.robots.ox.ac.uk/~vgg/
DeepMind:https://deepmind.com/
参考:K. Simonyan and A. Zisserman. Very deep convolutional networks for large-scale image recognition. In ICLR, 2015.
比较常用的是VGG-16,结构规整,具有很强的拓展性
相较于AlexNet,VGG-16网络模型中的卷积层均使用 333∗3 的 卷积核,且均为步长为1的same卷积,池化层均使用 222∗2 的 池化核,步长为2
CNN主要应用 图像处理领域主要应用
图像分类(物体识别):整幅图像的分类或识别物体检测:检测图像中物体的位置进而识别物体图像分割:对图像中的特定物体按边缘进行分割图像回归:预测图像中物体组成部分的坐标
历史记录艺术画笔工具 Art History Brush Tool可以使用指定历史记录状态或快照中的源数据,以风格化描边进行绘画。
快捷键:Y
注意:
历史记录艺术画笔工具仅能工作在“8 位/通道”模式下。
原图
效果图
工具选项栏说明
工具选项栏前面的一些选项,与画笔工具几乎一样,比如画笔预设选取器、画笔设置面板、混合、不透明度、角度等。同样支持压感设备的操作。
提示 1:专用的笔刷
通过画笔预设选取器的齿轮按钮,可以添加“转换后的旧版工具预设”Converted Legacy Tool Presets。
在“艺术历史记录”文件夹中,可以找到许多可用于历史记录艺术画笔工具的笔刷,如,印象派效果 Impressionist、油画素描 Oil Sketch等。
提示 2:画笔大小
画笔的大小与绘制的效果有密切关系:
笔触越大越抽象,笔触越小越有细节。
改变大小的方式同画笔工具。
样式
Style
包括:绷紧短 Tight Short、绷紧中 Tight Medium、绷紧长 Tight Long、松散中等 Loose Medium、松散长 Loose Long、轻涂 Dab、绷紧弯曲 Tight Curl、绷紧弯曲长 Tight Curl Long、松散弯曲 Loose Curl、松散弯曲长 Loose Curl long等。
区域
Area
设置绘画区直径,决定多大区域受影响。
容差
Tolerance
设置绘画的容差值。
◆ ◆ ◆
使用工具进行创作的建议流程
1、新建白色图层,并将图层不透明度设为 80% 左右,以看清下方的原图。
2、选择合适的笔刷。
比如,印象派效果等,样式:绷紧中,区域:300 px。
3、先用较大的画笔涂抹,以得到底色草图效果。
我只能说,写这篇博客太艰难了……一定要沉住耐心……这个型号的机械臂与官方给的手册里面的参数是有出入的……
感谢《台大机器人学课程》《机器人学之运动学笔记【3】—— 机械臂DH表示法+正向运动学(Forward Kinematics)》以及《机器人工程师进阶之路(二)6轴机械臂D-H法建模》
目录
一、空间中转轴的相对几何关系
1、连杆坐标系
2、DH参数
二、DH参数建立步骤
1、建立模型
(1)确定各关节以及关节轴线Axis i
(2)确定zi轴
(3)确定原点i以及xi轴
(4)添加首尾坐标系
2、确定DH的4个参数
(1)确定αi-1:{大小:zi-1指向zi的角度;符号:右手螺旋定则指向与xi-1相同时为+}
(2)确定ai-1:{大小:zi-1指向zi的距离;符号:沿着xi-1为+,a>0}
(3)确定di:{大小:xi-1指向xi的距离;符号:沿着zi为+,d不一定±}
(4)确定θi:{大小:xi-1指向xi的角度;符号:右手螺旋定则指向与zi相同时为+}
3、offset参数
三、用Python求解正向运动学:计算转换矩阵T
四、回答上文“二/1/(3)”中设置的tips问题)
这里对myCobot Pro机械臂采用改进DH表示法描述机械臂,下面将会详细介绍流程:
一、空间中转轴的相对几何关系 一般机械臂初始位置被认为是整体伸直向上。
如下图所示:(我这里保持官方给的关节刻度相对准,图中→带+的符号表示电机正转方向)
1、连杆坐标系 2、DH参数 在改进DH法中,描述连杆之间的位置关系,需要用到4个量:(这4个量组成DH参数)
连杆长度a:两个关节的轴(旋转关节的旋转轴,平移关节的平移轴)之间的公共法线长度
连杆扭矩α:一个关节的轴相对于另一个关节的轴绕它们的公共法线旋转的角度
连杆偏距d:一个关节与下一个关节的公共法线和它与上一个关节的公共法线沿这个关节轴的距离
关节转角θ:一个关节与下一个关节的公共法线和它与上一个关节的公共法线绕这个关节轴的转角
连杆长度a、连杆扭矩α、连杆偏距d、关节转角θ(旋转关节,θ为变量;移动关节,d为变量)
在myCobot当中,全都是Revolute joint关节,因此,4个量中,只有θ是变量
列表如下: iαi-1(alpha_i-1)ai-1diθioffset123456 二、DH参数建立步骤 1、建立模型 (1)确定各关节以及关节轴线Axis i 每一个关节轴线确定一个坐标系
(2)确定zi轴 z轴的位置为当前轴线,方向任意(此处选择电机正转方向,通过右手螺旋定则判断出z轴的正方向),同时z轴的下标表示第几坐标系。
(3)确定原点i以及xi轴 {i}坐标系的原点与xi轴:
①(情况存在:{1}、{4}、{5})Axis i与Axis i+1如果相交,交点为原点,xi的方向在两轴线所在平面的垂线上,通常取为右手螺旋定则(zi指向zi+1)的正方向;
②(无需考虑)Axis i与Axis i+1如果不相交,两轴线公垂线和当前关节i轴线的交点为原点,x_i为在公垂线上,方向任意(沿着ai的方向,一般指向后一个关节);
③(情况存在:{2}、{3})Axis i与Axis i+1如果平行,公垂线有无数条,此时连杆偏距d明显为0,xi在公垂线上,指向Axis i+1,且指向坐标系{i+1}的原点。
需要注意的是,当坐标系{2}的原点定了以后,那么坐标系{3}的原点就在x2的延长线上
tips:这里关于坐标系{2}为什么和{1}重合,我认为是不一定非要用这种方式的(可以不重合),这里先存下一个疑惑,之后会通过计算进行回答!
(4)添加首尾坐标系 在改进DH坐标系中,已经标注好{6}了,所以在首端添加{0}。
为了简化,通常使 {0} 和 {1} 一致,并且当第一个关节变量θ1为0时,{0} 和 {1} 会重合。
几步教会你螺母拧出螺栓动画 1.首先建立装配体,然后在toolbox中调出螺栓螺母如下图所示。
2.对螺栓和螺母进行配合,点击高级配合下的螺旋配合,配合选择螺栓的螺纹边线,以及螺母的螺纹线即可。
3.完成后点击螺栓头的下面和螺母的上面进行距离配合,配合距离为0.5mm。
4.点击动画在距离配合那一行在4秒处右击放置键码。
5.双击4秒处的键码,配合距离为20mm。然后点击计算即可。如下图所示,动画就完成了。
1、安装 docker 环境 1 2 3 4 5 6 7 8 9 10 11 1)安装 docker curl -sSL https://get.daocloud.io/docker | sh 2)启动服务 systemctl start docker 3)查看服务状态 systemctl status docker 4)设置开机自启动 systemctl enable docker 官方文档:Install Docker Engine on CentOS | Docker Documentation
2、实现 docker 镜像加速 1 curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io 3、安装 docker-compose 1 2 curl -L https://get.daocloud.io/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose 4、开放指定端口 1 2 3 4 5 # 请将 * 修改成需要开放的端口(请自行查看 docker-compose.
目录 C语言中指针传参一、如何改变参数的值1、常见的错误写法:2、解决办法使用指针 二、与return进行比较1、使用return返回值:2、使用指针改变多个参数的值 三、如何改变指针的值?使用指针的指针 C语言中指针传参 一、如何改变参数的值 1、常见的错误写法: 由于变量会随着栈的退出而销毁,所以下面的函数无法改变a的值。
#include<stdio.h> void f(int b){ //参数b初始化为1 b=3;//改变b的值为3 }//随着函数的结束,变量b被销毁,a的值并没有发生改变 int main(void){ int a=1; f(a);//将a的值传入函数 printf("a的值为:%d",a); } 运行结果:
a的值为:1 2、解决办法使用指针 #include<stdio.h> void f(int *ptr){//ptr的值等于变量a的地址 *ptr=3;//对ptr间接访问,相当于变量a,这里把3赋值给变量a } int main(void){ int a=1; f(&a);//将a的地址传入 printf("a的值为:%d",a); } 运行结果:
a的值为:3 二、与return进行比较 1、使用return返回值: #include<stdio.h> int f(){ int a=3; return a; } int main(void){ int a=1; a=f(); printf("a的值为:%d",a); } 运行结果:
a的值为:3 可以看到:使用return也可以改变a的值,但是与指针不同的是,它只能返回一个值
使用指针,可以同时改变多个变量的值,如下:
2、使用指针改变多个参数的值 #include<stdio.h> void f(int *ptr1,int *ptr2){ *ptr1=3; *ptr2=3; } int main(void){ int a=1; int b=1; f(&a,&b); printf("
Ctrl+F 查询 城市名字
http://mobile.weather.com.cn/data/forecast/101010100.html?_=1381891660081
“北京”=>“101010100”,
“海淀”=>“101010200”,
“朝阳”=>“101010300”,
“顺义”=>“101010400”,
“怀柔”=>“101010500”,
“通州”=>“101010600”,
“昌平”=>“101010700”,
“延庆”=>“101010800”,
“丰台”=>“101010900”,
“石景山”=>“101011000”,
“大兴”=>“101011100”,
“房山”=>“101011200”,
“密云”=>“101011300”,
“门头沟”=>“101011400”,
“平谷”=>“101011500”,
“八达岭”=>“101011600”,
“佛爷顶”=>“101011700”,
“汤河口”=>“101011800”,
“密云上甸子”=>“101011900”,
“斋堂”=>“101012000”,
“霞云岭”=>“101012100”,
“上海”=>“101020100”,
“闵行”=>“101020200”,
“宝山”=>“101020300”,
“川沙”=>“101020400”,
“嘉定”=>“101020500”,
“南汇”=>“101020600”,
“金山”=>“101020700”,
“青浦”=>“101020800”,
“松江”=>“101020900”,
“奉贤”=>“101021000”,
“崇明”=>“101021100”,
“陈家镇”=>“101021101”,
“引水船”=>“101021102”,
“徐家汇”=>“101021200”,
“浦东”=>“101021300”,
“天津”=>“101030100”,
“武清”=>“101030200”,
“宝坻”=>“101030300”,
“东丽”=>“101030400”,
“西青”=>“101030500”,
“北辰”=>“101030600”,
“宁河”=>“101030700”,
“汉沽”=>“101030800”,
“静海”=>“101030900”,
“津南”=>“101031000”,
“塘沽”=>“101031100”,
“大港”=>“101031200”,
“平台”=>“101031300”,
“蓟县”=>“101031400”,
“重庆”=>“101040100”,
“永川”=>“101040200”,
“合川”=>“101040300”,
“南川”=>“101040400”,
“江津”=>“101040500”,
“万盛”=>“101040600”,
“渝北”=>“101040700”,
“北碚”=>“101040800”,
“巴南”=>“101040900”,
“长寿”=>“101041000”,
“黔江”=>“101041100”,
“万州天城”=>“101041200”,
“万州龙宝”=>“101041300”,
“涪陵”=>“101041400”,
“开县”=>“101041500”,
目录:
一,引入Deployment
二,Deployment支持的功能
三,Deployment资源清单文件详解
四,滚动更新及回滚实验
五,弹性伸缩实验
一,引入Deployment 对于kubernetes来说Pod是资源调度最小单元,kubernetes主要的功能就是管理多个Pod,Pod中可以包含一个或多个容器,而kubernetes是如可管理多个Pod的呢?对,没错,就是通过控制器,比如Deployment和ReplicaSet(rs)。
kubernetes下有多个Deployment,Deployment下管理RepliceSet,通过RepliceSet管理多个Pod,通过Pod管理容器。
它们之间的关系图如下:
二,Deployment支持的功能 1,动态水平的弹性伸缩
容器对比虚拟机,最大的优势就在于容器可以灵活的弹性伸缩,而这一部分工作由kubernets中的控制器进行调度。
Deployment的弹性伸缩本质指得是RS下Pod的数量增加或减少
在创建Deployment时会相应创建一个RS,通过RS实现弹性伸缩的自动化部署,并在很短的时间内进行数量的变更
弹性伸缩通过修改yaml文件中的replicas参数实现
修改yaml文件后,通过 apply 命令重新应用而实现扩容或缩容
2,支持动态的回滚和滚动更新
定义一个Deployment会创建一个新的RS,通过RS创建Pod,删除Deployment控制器,同时也会删除所对应的RS及RS下控制的Pod资源。
可以说Deployment是建立在RS之上的一种控制器,可以管理多个RS,当每次需要更新Pod的时候,就会自动生成一个新的RS,把旧的RS替换掉,多个RS可以同时存在,但只有一个RS在运行,因为新RS里生成的Pod会依次去替换旧RS里面的Pod,所以需要等待时间,大约十分钟。
Deployment还支持回滚到以前的历史版本。
更新节奏和更新逻辑:
加入Deployment中定义了replicas数量为5(也就是期望的Pod数为5个)但在实际更新时会额外多几个,假如说能多一个,但是不可以少,那么更新的过程就是先增加一个Pod,再删除一个,增一个,删一个,但一般感受不到,这里只是讲一下原理,可以不必太在意。
三,Deployment资源清单文件详解 apiVersion: apps/v1 ##版本 kind: Deployment ##类型 metadata: ##Deployment的元数据 name: httpd ##Deployment的名字 labels: ##标签 app: httpd ##标签app=httpd spec: ##Pod的信息 replicas: 3 ##Pod的副本数 selector: ##标签选择器 matchLabels: ##查找匹配的标签 app: httpd ##app=httpd template: ##Pod的模板信息,根据模板信息来创建Pod metadata: ##Pod的元数据 labels: ##Pod的标签 app: httpd ##标签app=httpd spec: ##容器的信息 containers: ##容器 - name: httpd ##容器名 image: httpd ##容器所需的镜像 ports: ##端口 - containerPort: 80 ##容器暴露的端口 当我们不知道该怎么写时可以通过命令来查看更多详细内容:
1.动态链接与静态链接区别 首先写一个main.c死循环程序
int mian() { while (1); } 进入main.c所在的目录下,打开一个终端,执行动态链接
gcc main.c 在此终端下进行静态链接
gcc -static main.c -o static.out 生成了可执行文件a.out static.out:
比较静态链接和动态链接的时间上的区别:
动态链接花费的时间比静态链接的时间更短。
分别打开两个终端,运行a.out static.out可执行程序,进入死循环状态;新建一个终端输入:top。找到两个程序的进程号
a.out的进程号是8175,在终端中输入pmap 8175(此时不要杀死死循环)
(base) bionic@bionic-DL:~$ pmap 8342 8342: ./static.out 0000000000400000 728K r-x-- static.out 00000000006b6000 24K rw--- static.out 00000000006bc000 4K rw--- [ anon ] 0000000001e23000 140K rw--- [ anon ] 00007ffc0e820000 136K rw--- [ stack ] 00007ffc0e8b8000 12K r---- [ anon ] 00007ffc0e8bb000 4K r-x-- [ anon ] ffffffffff600000 4K --x-- [ anon ] total 1052K (base) bionic@bionic-DL:~$ pmap 8175 8175: .
在设计微服务的时候,我们一般会遵循以下4个原则:
1)AKF拆分原则
2)前后端分离原则
3)无状态服务
4)restful的通信风格
下面我们来详细了解以下AKF拆分原则。
1 AKF拆分原则 业界对可扩展系统架构设计有一个朴素的概念,就是:通过加机器可以解决容量和可用性问题(如果一台不行就两台)
用个段子描述就是:(世界上没有什么事是一顿烧烤解决不了的,如果有,那就两顿)
这一理念在“云计算”概念疯狂流行的今天。得到了广泛的认可。对于一个规模迅速增长的系统而言。容量和性能问题当然是首当其冲的。但是随着时间的向前,系统规模的增长,除了面对性能与容量的问题外,还需要面对功能与模块数量上增长带来的系统复杂性问题。以及业务变化带来的提供差异化服务问题。而许多系统在架构设计时并未充分考虑到这些问题,导致系统的重构成为常态。从而影响业务交付能力,还浪费人力财力。对此《可扩展的艺术》一书提出了一个更加系统的可扩展模型----AKF可扩展立方。这个立方体中沿着三个坐标轴设置分别为X,Y,Z。
2 Y轴功能Y轴扩展会将庞大的整体应用拆分为多个服务。每个服务实现一组相关的功能。如订单管理,客户管理等。在工程上常见的方案是服务化架构(SOA),比如对于一个电子商务平台,我们可以拆分成不同的服务组成下面这样的架构。
但是通过上图容易发现,当服务数量增多时,服务调用关系变得复杂,为系统添加一个新功能。要调用的服务数也变得不可控。由此引发的服务管理上的混乱,一般情况下,需要采用服务注册的机制,形成服务网关来进行服务治理。系统架构将变成如下图所示。
3 X轴(水平扩展)
X轴扩展与我们前面理念是一致的。通过绝对平等的复制服务与数据,以及容量和可用性问题。其实就是将微服务运行多个实例。做集群,负载均衡的模式。
为了提升当个服务的可用性和容量。对每一个服务进行x轴扩展划分。
1.4 Z轴(数据分区)
Z周扩展通常是指基于请求和用户独特的需求,进行系统划分,并使得划分出来的子系统相互隔离,但又是完整的。
1.4.1工程领域常见的这种扩展有以下两种方案。
1.4.1.1 单元化架构
在分布式服务设计领域,一个单元就是满足某个分区所有业务操作的自包含闭环。如上面我们所说的y轴扩展的SOA架构。客户端对服务端节点的选择一般是随机的。但是,如果在此加上这周扩展,那么服务的节点选择将不再是随机的。而是每个单元自成一体。如下图。
1.4.1.2数据分区
为了性能数据安全上的考虑。我们将一个完整的数据集按照一定的维度,划分出不同的子集。一个分区,就是整体数据集的一个子集。比如用尾号来划分用户,那同样尾号的那部分用户,就可以认为是一个分区。数据分析一般包括以下几种数据划分的方式。
数据类型(如:业务类型)
数据范围(如:时间段,用户id)
数据热度(如:用户活跃度,商品热度)
读写分离(如:商品描述,商品库存)
。
public class HttpUtil { /* 该方法使用HttpURLConnection方法访问网络 给sendHttpRequest方法添加一个HttpCallBackListener参数,并在方法内部开启子线程在子线程中去执行具体的网络操作 */ public static void sendHttpRequest(String address,final HttpCallBackListener listener) { new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try { //获取实例,使用HttpURLConnection发出一条http请求,目标地址为传入的address URL url = new URL(address); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); //设置HTTP请求所使用的方法 connection.setReadTimeout(8000); //连接超时时间 connection.setConnectTimeout(8000); //读取超时时间 connection.setDoInput(true); connection.setDoOutput(true); InputStream in = connection.getInputStream(); //获取到服务器返回的输入流 //下面对获取到的输入流进行读取 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.
今天安装了Visual Studio 2022 企业版工具,觉得改进还是有一定的,下面提供下载及序列号:
链接:https://pan.baidu.com/s/1qvzg8WtsgaCxrD3M4Y0QPA 提取码:n6o1
注:请在安装完毕之后,进行更新到最新版本。
作业来自官网
知识点整理
文章目录 总览解答Renderer.cppTriangle.hpp 结果 总览 在光线追踪中最重要的操作之一就是找到光线与物体的交点。一旦找到光线与物体的交点,就可以执行着色并返回像素颜色。在这次作业中,我们需要实现两个部分:光线的
生成和光线与三角的相交。本次代码框架的工作流程为:
从 main 函数开始。我们定义场景的参数,添加物体(球体或三角形)到场景
中,并设置其材质,然后将光源添加到场景中。调用 Render(scene) 函数。在遍历所有像素的循环里,生成对应的光线并将
返回的颜色保存在帧缓冲区(framebuffer)中。在渲染过程结束后,帧缓冲
区中的信息将被保存为图像。在生成像素对应的光线后,我们调用 CastRay 函数,该函数调用 trace 来
查询光线与场景中最近的对象的交点。然后,我们在此交点执行着色。我们设置了三种不同的着色情况,并且已经
为你提供了代码。 解答 Renderer.cpp 先把x和y坐标放缩到[-1,1]空间内。然后在把它转换到lrbt空间中,所以要乘以scale。然而scale是仰角算出来的,是上下的scale,所以水平想放缩的话,还要乘以分辨率。 注意计算xy的时候的精度丢失,别忘了*1.0,要不然可能会没有图像。
void Renderer::Render(const Scene& scene) { std::vector<Vector3f> framebuffer(scene.width * scene.height); //先把x和y坐标放缩到[-1,1]空间内。 //然后在把它转换到lrbt空间中,所以要乘以scale。 //然而scale是仰角算出来的,是上下的scale,所以水平想放缩的话,还要乘以分辨率。 float scale = std::tan(deg2rad(scene.fov * 0.5f)); float imageAspectRatio = scene.width / (float)scene.height; // Use this variable as the eye position to start your rays. Vector3f eye_pos(0); int m = 0; for (int j = 0; j < scene.
混凝土建筑裂缝
介绍
表面裂缝检测是监测混凝土结构健康的一项重要任务。如果裂纹发展并继续扩展,它们会减少有效承载表面积,并且随着时间的推移会导致结构失效。裂纹检测的人工过程费时费力,且受检验人员主观判断的影响。在高层建筑和桥梁的情况下,手动检查也可能难以执行。在这篇文章中,我们使用深度学习来构建一个简单但非常准确的裂缝检测模型。此外,我们在现实世界的数据上测试了模型,发现该模型在检测混凝土和非混凝土结构示例道路中的表面裂缝方面是准确的。该代码在Github上的链接上开源。
数据集
在这篇文章中,我们使用了公开可用的混凝土裂缝图像数据集,该数据集由 20,000 张有裂缝的混凝土结构图像和 20,000 张无裂缝的图像组成。该数据集由 458 张高分辨率图像(4032x3024 像素)生成。数据集中的每个图像都是 227 x 227 像素的 RGB 图像。部分有裂纹和无裂纹的示例图如下所示:
带有裂纹的示例图像
没有裂纹的示例图像
可以看出,数据集有各种各样的图像——不同颜色、不同强度和形状的裂缝。
建立模型
对于这个问题,让我们在 Pytorch 中构建一个卷积神经网络(CNN)。由于我们的图像数量有限,因此我们将使用预训练的网络作为起点,并使用图像增强功能来进一步提高准确性。图像增强使我们能够进行诸如垂直和水平翻转、旋转和亮度变化之类的转换,从而显着增加样本并帮助模型泛化。
对于以下步骤,请参考我在 Github 上的代码。
将输入数据混洗并拆分为 Train 和 Val
下载的数据将有 2 个文件夹,一个用于正样本文件夹,一个用于负样本文件夹,我们需要将其拆分为 train 和 val。下面的代码片段将为 train 和 val 创建新文件夹,并将 85% 的数据随机混洗到 train 中,并将其余数据随机放入 val 中。
拆分为 train 和 val
应用转换
Pytorch 可以轻松应用数据转换,这可以增强训练数据并帮助模型提高泛化性。我们选择的转换是随机旋转、随机水平和垂直翻转以及随机颜色抖动。此外,每个通道除以 255,然后归一化,这有助于神经网络训练。
转变
预训练模型
我们使用在 ImageNet 上经过预训练的 Resnet 50 模型来快速启动模型。如下所示,ResNet50 模型由 5 个阶段组成,每个阶段都有一个卷积和 Identity 块。每个卷积块有 3 个卷积层,每个标识块也有 3 个卷积层。ResNet-50 有超过 2300 万个可训练参数。我们将冻结所有这些权重和 2 个全连接的层——第一层在输出中有 128 个神经元,第二层在输出中有 2 个神经元,这是最终的预测。
这两个命令都是开放性的,需要建立新文件夹。适用于新建情形。但实际工作中明显更多要用到从一个文件夹移动和复制到另一个文件夹,早先没有认真考察,最后决定来解决这个问题,其实非常简单。
以下的模块MKwjcz的内容就是上一篇文章中的内容,实际上就是用到了os.listdir(path)而已。但是我认为文件夹和文件具有完全不同的性质,将它们分开处理是清晰的,虽然可能有点啰嗦。
我个人的经验是,宁可逐步序化,不要眉毛胡子一把抓,因为写代码容易,发现代码的问题却非常难。
# -*- coding:utf-8 -*- import os import MKwjcz import shutil # 16 将一个文件夹的内容移动到另一个文件夹 def ZJmv(pathx,pathy): ''' 直接将一个文件夹里面的内容移动到另一个文件夹 shutil.move主要是针对新建文件夹的,把一个文件夹里的内容复制到新建的文件夹 ''' Lb1 = MKwjcz.DFfl(pathx)[0] Lb2 = MKwjcz.DFfl(pathx)[1] for xi in Lb1: shutil.move(pathx+'/'+str(xi),pathy+'/'+str(xi)) for xi in Lb2: shutil.move(pathx+'/'+str(xi),pathy+'/'+str(xi)) ##ZJmv('D:/ZDCS系统/工作区/测试','D:/ZDCS系统/人机对话区/新建文件夹') # 17 将一个文件夹的内容复制到另一个文件夹 def ZJcp(pathx,pathy): ''' 直接将一个文件夹里面的内容复制到另一个文件夹 shutil.copy主要是针对新建文件夹的,把一个文件夹里的内容复制到新建的文件夹 ''' Lb1 = MKwjcz.DFfl(pathx)[0] Lb2 = MKwjcz.DFfl(pathx)[1] for xi in Lb1: shutil.copytree(pathx+'/'+str(xi),pathy+'/'+str(xi)) for xi in Lb2: shutil.copyfile(pathx+'/'+str(xi),pathy+'/'+str(xi)) ##ZJcp('D:/ZDCS系统/工作区/测试','D:/ZDCS系统/人机对话区/新建文件夹') 测试非常好用,我印象中看过别人的一段改造代码好像很复杂,搞得我以为这个问题很麻烦,没想到2分钟就解决了这个巨大的烦恼。
我们在开展仿真活动通常需要关注时间,然而这些时间的物理含义和相互关系经常又是是是而非的,今天对相关的时间概念进行讲解。
1、仿真周期/节拍(T)
仿真周期是指系统中触发一次仿真计算的物理时间间隔,仿真周期的确定通常受到计算耗时、数据传输耗时的影响,必须要保证在一个仿真周期内完成计算和数据传递,否则仿真系统的推进会出现紊乱。
2、仿真步长(Step)
仿真步长是仿真系统计算推进的逻辑时间长度,这个时间实际是仿真模型对于客观世界连续变量离散化处理的采样时间,仿真步长越小,采样密度越大,模型的逼真度才更有保证。
3、仿真速率/推进比(rate)
rate反映的是仿真的快慢, rate=1 为实时仿真;rate<1为欠实时仿真;rate>1为超实时仿真
通常情况下人们对于仿真的要求既要仿的真,又要仿的快,实际就是Step要尽量小,rate要尽量大,这就要求T要尽量小,而实际情况T是受实际计算能力和通信能力制约的,不可能无限的小。这也就是为什么我们在进行复杂计算的仿真时,需要处理大量数据,在逼真度要求严格的情况下只能进行欠实时仿真的原因。
总结,既要仿的真和又要仿的快的要求,存在一个计算能力、通信能力限制的矛盾,很难同时实现,必须要在一定条件下折中。
几步教会你工程图如何调整等轴侧视图角度 1.打开一张工程图,点击视图下拉菜单选择修改,在右侧点击3D工程图视图。
2.完成后会发现等轴侧视图会有一个蓝色框。点击蓝色框上方的菜单中的旋转后点击鼠标左键拖动调整等轴侧视图的方向。可以调整到如下图所示的角度。
3.等轴侧视图角度调整好后点击确定即可。
vsftpd登录很慢
1.进入容器
docker exec -it 8ca5d499f4fc bash 8ca5d499f4fc 换成自己的容器id
vi /etc/vsftpd/vsftpd.conf 把这一项改成NO reverse_lookup_enable=NO
保存后
source /etc/vsftpd/vsftpd.conf vi /etc/resolv.conf 里面的内容情况,有四项nameserve 全删掉不是删除文件。
source /etc/resolv.conf 退出容器。再连接试试,
速度超快
一、跨域简介 1. 首先简单介绍一下什么是跨域 当我们在浏览器的地址栏中输入一个地址的时候,这个地址通常包含四部分信息内容。这四部分信息包含:①协议、②域名、③端口、④资源位置。
其中前三部分将会决定是否存在跨域,即:协议、域名、端口。如果其中有一个不一样,浏览器就会认为存在跨域的问题。例如:
域名1域名2是否有跨域http://father.moxiao.com/a/a.htmlhttp://father.moxiao.com/b/b.html不存在跨域https://father.moxiao.com/a/a.htmlhttp://father.moxiao.com/b/b.html存在跨域,协议不一样http://father.moxiao.com/a/a.htmlhttp://child.moxiao.com/b/b.html存在跨域,域名不一样http://father.moxiao.com/a/a.htmlhttp://child.moxiao.com:8082/b/b.html存在跨域,端口不一样 2.跨域的种类 一般有两种形式的跨域问题:
①使用XmlHttpRequest(XHR)或者使用AJAX发送的POST或者GET请求。这种形式的跨域是:前端页面与后端进行的跨域请求。这种形式跨域不在本篇文章的讨论范围内。
②父子页面之间进行的DOM操作(父子窗口之间的document操作)。这种形式的跨域是:前端页面与前端页面之间的通信或者相互操作的形成跨域。(本文主要讨论就是这个话题)
3.跨域的提示 如果在页面上出现了上面任何一种形式的跨域,一般会在浏览器的控制台(Chrome中按F12键)打印下面一段类似的描述:(一般包含accessing a cross-origin类似的信息就是跨域了)
二、问题描述 1.父子页面之间的DOM操作 在HTML页面中,我们有时候会使用<iframe>标签打开一个子窗口,又或者使用window.open方法打开一个子窗口,但有时想让父子窗口之间进行通信。例如:根据父窗口的大小,对<iframe>子窗口大小进行设置等问题。
①、如果<iframe>中src属性配置的地址和父窗口在同一个域下,可以在子窗口中通过window.parent.document来获取父窗口的DOM对象。亦或父窗口也可以通过contentWindow属性获取子窗口的DOM对象(Iframe情况下)。例如:document.getElementById('iframe标签的ID').contentWindow。两者之间操作不会出现任何跨域的问题,可以自由的获取任意想要的元素信息内容。也就不在本篇文章的讨论范围内。
②、如果<iframe>中的src属性配置的地址与父窗口不在同一个域下,即:协议、域名、端口任何一个不一样都会造成跨域问题。当使用window.parent.document进行操作的时候,就会提示跨域的问题,就是上面截图的信息内容。又或者使用contentWindow属性也会提示相同的跨域问题。有以下几种解决问题的方法以及这些方法的局限性。
三、解决页面之间跨域问题的方法 着重看第一和第二种方法,在第一种和第二种方法无法使用的时候,可以考虑剩下的方法。
1. 使用document.domain方法(☆☆☆☆☆) 1.1. document.domain的原理 JS在判断页面之间是否有跨域操作,主要根据页面的document.domain属性进行对比来判断是否有跨域。
如果两个页面的document.domain属性值一样的话,就算两个页面实际上不在同一个域下,JS也会认为他们之间没有跨域操作。这样的话,如果我们将两个页面的document.domain属性值设置为一样的。不同域下的页面之间操作就可以像在一个域名下的页面之间的操作。
document.domain的默认值为:当前域名。
1.2. document.domain的局限性 上面说如果将两个页面的document.domain属性设置为一样的话,就算实际上不在同一个域下,他们也可以进行DOM对象之间的操作。但是document.domain也不是你想设置成什么就可以设置成什么的,这个属性的属性值有一定的设置规则,如果不满足设置的规则就不能设置成功。
规则如下:
①document.domain只设置域名或者IP地址。即:没有协议(http/https),没有端口。
②如果访问的地址是域名形式,则document.domain只能设置为当前域名下的同级或者父级域名,并且不能设置为顶级域名,也不可以设置为其他形式的域名(不是当前域名的父级或同级)。
例如:当前访问地址为:https://mp.csdn.net/mp_blog/creation/editor/121540023(当前页面)。可以打开Chrome的控制台(F12)找到console的tab。默认情况下,我们输入document.domain会显示‘csdn.net’。其中csdn.net就是https://mp.csdn.net的父级域名。我们也可以设置为mp.csdn.net。因为mp.csdn.net是mp.csdn.net的同级域名。
但是我们不能设置顶级域名,即document.domain='net',就会提示错误信息。也不能设置其他的域名形式。即document.domain='csdn1.net'或者document.domain='baidu.com'。提示也说得很清楚。必须是mp.csdn.net的一个后缀形式。
③如果访问地址是IP的形式,则document.domain只能设置一样的IP地址。
下图就是在当前页面进行的设置。
注意:根据上面的设置规则,在使用document.domain的方式时,页面之间必须有相同的父级域名。否则这种方式将无法进行操作。
document.domain只配置域名或者IP地址,不需要配置协议、端口。因为document.domain只配置的域名或者IP地址,所以页面之间的协议必须是一样的,要么都是HTTP,要么都是HTTPS。如果是混合的,这种方式也是不行的。但是页面端口可以不一样。 1.3. domian方式的演示示例 https://github.com/1997chang/iframeCrossAccess是一个进行页面操作跨域的显示示例。该项目有两个模块,fathermodule和childmodule。
在static/domain文件夹下显示的为document.domain的解决方案的示例。
启动father以及child模块,在地址栏中输入:father.moxiao.com:8081/domain/fatherDomainMethod.html。就可以进行页面之间的相互操作了。
2. 使用postMessage方式(☆☆☆☆☆) 在H5之后,window对象添加了一个postMessage的方法,使用postMessage方法可以向任何域名发送消息内容(字符串或者对象)。postMessage方法发送的消息将不会受到跨域的影响。
2.1 postMessage不受跨域的影响 在HTML页面中,可以在当前页面中使用window.parent获取父级窗口对象(WIndow),从而向父级窗口发送消息(子->父)。同样也可以使用contentWindow获取Iframe的打开的子窗口对象,从而向子窗口发送消息。(父->子)
在父窗口中获取其子窗口的window对象,又或者在子窗口中获取其父窗口的window对象。但是如果两个父子窗口存在跨域问题,那么将不能对获取到的window对象进行任何操作。即可以在跨域的情况下获取其子窗口或者父窗口的window对象,但是不能对获取到的window对象进行任何操作。如果进行了任何的操作,都会提示跨域的问题。但是有两个是例外。即使在跨域的情况下也可以对其进行设置。
①location属性:设置window准备跳转的页面。后面两种解决方法使用该属性。
②postMessage方法,H5之后添加的。
无论当前域名是什么,获取到的window对象的域名是什么。即使这两个域名之间存在跨域问题,在window对象中有一个属性location的设置和一个方法postMessage的调用不会受到跨域的影响。
2.2. postMessage方法的使用 postMessage和addEventListener方法配合使用。postMessage是用来发送消息的,addEventListener是用来接收消息时候的回调。
postMessage方法有两个参数:
①发送的消息:可以是字符串,也可以是对象。
②接收消息的域名:要么是具体值(协议、域名、端口都要设置,且相同),要么是*。如果设置为*:则表示没有任何限制。如果设置为具体值的话,则必须与发送到的窗口域名相同,包含协议、域名、端口,如果有一个不同的话,就会发送不出去。
例如:parent.window.postMessage('父窗口你好','http://father.moxiao.com'),就会提示错误。因为parent.window窗口的域名为:http://father.moxiao.com:8082,而发送配置的域名是:http://father.moxiao.com。就会提示下面的错误信息:
例如: parent.window.postMessage(content, 'http://father.moxiao.com:8081'); addEventListener方法有两个参数:
①监听的时间类型:对于发送消息而言,固定为message。
②回调函数:在回调函数中一个参数event,event其中包含三个重要的属性:
1.data:表示接受到的消息内容,可能是字符串,可能是对象,取决有发送方。
centos7安装分布式事务框架seata 1.安装包及前置准备2.上传3.解压4.进入seata目录5.修改file.conf配置项6.修改registry.conf配置7.下载资源目录8.进入script\config-center\nacos目录9.执行sh命令10.nacos查看配置项11.启动Seata Server12.最后补充 1.安装包及前置准备 需要先在虚拟机上安装运行nacostar包准备
下载地址 我这里安装的是seata-server-1.4.0.tar.gz 2.上传 rz或者ftp工具上传 3.解压 tar -zxvf seata-server-1.4.0.tar.gz -C /usr/local 4.进入seata目录 目录结构如上图所示 接下来需要修改conf 目录里的配置 5.修改file.conf配置项 cd conf/ vim file.conf 修改如下
store { ## store mode: file、db、redis mode = "db" ## file store property file { ## store location dir dir = "sessionStore" # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions maxBranchSessionSize = 16384 # globe session size , if exceeded throws exceptions maxGlobalSessionSize = 512 # file buffer size , if exceeded allocate new buffer fileWriteBufferCacheSize = 16384 # when recover batch read size sessionReloadReadSize = 100 # async, sync flushDiskMode = async } ## database store property db { ## the implement of javax.
目录 sqlx介绍sqlx安装sqlx的基本使用连接数据库查询插入、修改更新、删除 sqlx.in实现批量插入sqlx.in 查询 sqlx介绍 在项目中我们通常可能会使用database/sql连接MySQL数据库。
sqlx可以认为是Go语言内置database/sql的超集,它在优秀的内置database/sql基础上提供了一组扩展。还有其他一些超级有用的功能。
sqlx安装 go get github.com/jmoiron/sqlx 使用goland工具也可以直接导入依赖的。当依赖出现漏缺的时候可以使用命令来修复 go mod tidy sqlx的基本使用 连接数据库 var db *sqlx.DB func initDB() (err error) { dsn := "root:root@tcp(127.0.0.1:3306)/junmu?charset=utf8mb4&parseTime=True" // 也可以使用MustConnect连接不成功就panic db, err = sqlx.Connect("mysql", dsn) if err != nil { fmt.Printf("connect DB failed, err:%v\n", err) return } db.SetMaxOpenConns(20) db.SetMaxIdleConns(10) return } 设置一个全局变量进行全局的操作,方便一点。 查询 所用结构体:
type User struct { Id uint Name string Age uint } 单行查询
// 单行查询 func find(id int){ sqlStr := "
行列式基本性质 一、行列式求值 说明:第 i 行元素 乘 第 j 列的代数余子式 之和 = 0
二、转置行列式值不变 引申:行有什么性质,列就有什么性质
三、两行互换,行列式值变号 引申:两行相同,行列式值为0
四、某行全0 || 两行成比例,行列式=0 五、行列式可拆 注:不要理解错了,二 三行照抄,拆第一行(本着好算的原则拆)
六、行列倍加,值不变 这条性质用的最多
加出公因数,提出公因数加出0
重要公式 1.
这里“-1”的次数是:n*(n-1)/2
2.拉普拉斯
3.范德蒙
4.行列式乘法公式
例题 1.利用行列式性质计算 思路:通过初等变换使行列式中先出现1,然后用1使行列式中出现0,再用展开公式。
答案
2.利用拉普拉斯公式 答案
进阶
答案
3.利用范德蒙公式 答案
4.求特征值 观察除主对角线以外的元素,两个数加加减减可以得零,的同时,能够出现λ的公因式。
答案
例题
5.有规律行列式—例题 答案法一:
下面每一行都加到第一行,然后提取公因式。然后消零。出现上三角,直接写出答案。
加出公因式来,提出去,再消零。
答案法二:
下面每一行都减去第一行,做出相反数(x和-x),然后就出现下三角。
答案法三:
第三行的-1倍加到第四行,第二行的-1倍加到第三行,第一行的-1倍加到第二行,出相反数,消出零之后,对第一行展开,出下三角。
总结:
行列式有规律:想办法做公因数,相反数,想办法做0。
行列式无规律:消0,降阶。
6.证明题:证明范德蒙公式 解:
假设n = n-1的时候命题正确。
要证n = n的时候命题正确。
所以想到把n = n时的行列式降阶,因为n-1的行列式是正确的,现在要证明n阶,就要利用n-1阶的信息。
所以要用消零的方法来使n阶行列式降阶。
现在的问题是怎样把n阶行列式降阶。
遇到标题这样的权限提醒,改个权限就行了,找到文件文件"***.vmdk"所在的上一级文件夹,右键:授予访问权限-》特定用户 -》权限都改为读取和写入,重新打开虚拟机即可
思路:本章内容包括移动端(ios、isAndroid)、web端;
移动端必须需要后台返回http文件路径,isAndroid可以直接跳转浏览器下载,ios需要用户手动复制链接,然后去浏览器下载,web端文件不管是 流 还是http路径都可以下载
const u = navigator.userAgent; const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; // android终端 const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // ios终端 if (isAndroid) { // 安卓终端使用iframe window.open(item.url); } else if (isiOS) { Dialog.alert({ title: '请复制链接至浏览器下载', message: item.url, confirmButtonText: '复制', }).then(() => { clipBoard(item.url); }); } else { 1.如果是地址 window.open(item.url); 2.如果是文件流 // 浏览器 const aEle = document.createElement('a'); aEle.href = window.URL.createObjectURL(blob); if (!
知识点 与AOV—网相对应的是AOE—网(Activity On Edge)即边表示活动的网。AOE—网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活动,权表示活动持续的时间。通常,AOE—网可用来估算工程的完成时间。
例如,图7.29是一个假想的有11项活动的AOE—网。其中有9个事件 v 1 v_1 v1, v 2 v_2 v2, v 3 v_3 v3, v 4 v_4 v4, ⋯ \cdots ⋯, v 9 v_9 v9,每个事件表示在它之前的活动已经完成,在它之后的活动可以开始。如 v 1 v_1 v1表示整个工程开始, v 9 v_9 v9表示整个工程结束, v 5 v_5 v5表示 a 4 a_4 a4和 a 5 a_5 a5已经完成, a 7 a_7 a7和 a 8 a_8 a8可以开始。与每个活动相联系的数是执行该活动所需的时间。比如,活动 a 1 a_1 a1需要6天, a 2 a_2 a2需要4天等.
由于整个工程只有一个开始点和一个完成点
故在正常的情况(无环)下,网中只有一个人度为零的点(称做源点)和一个出度为零的点(叫做汇点)。
和 AOV-网 不同,对AOE—网有待研究的问题是:(1)完成整项工程至少需要多少时间?(2)哪些活动是影响工程进度的关键?
问题:
给定一个字符串,去除字符串中的重复字符。
演示:
输入:abcdabcd
输出:abcd
代码如下:
//串内无重复字符 #include <stdio.h> #include <string.h> #define max 100 main() { char a[max]; printf("请输入一个字符串:"); scanf("%s",a) ; int length=strlen(a); //计算字符串长度 int i,j; for(i=0;i<length;i++){ for(j=i+1;j<length;j++){ //利用for循环判断第i个字符后面有没有和第i个字符相同的 if(a[i]==a[j]){ //如果有相等的字符 for(int mark=j;mark<length;mark++){ //需要定义一个变量,让后面的每个字符都向前移动一位 a[mark]=a[mark+1]; //将下一个字符赋值给当前字符 (相当于删除字符操作) } length--; //总长度减1 j--; //由于当前字符已删除,需要再次判断当前位置的字符是否和第i个字符相等 } } } printf("新字符串为:%s\n",a); return 0; }
最近在学习PCL点云库相关内容,参考https://www.cnblogs.com/li-yao7758258/p/6437440.html的kdtree代码,发现出现如下bug:
kdtree.cpp:(.text+0x223):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::KdTreeFLANN(bool)’未定义在这里插入代码片的引用
kdtree.cpp:(.text+0x275):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::setInputCloud(boost::shared_ptr<pcl::PointCloudpcl::PointXYZ const> const&, boost::shared_ptr<std::vector<int, std::allocator
const> const&)’未定义的引用 kdtree.cpp:(.text+0x4a9):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::nearestKSearch(pcl::PointXYZ const&, int,
std::vector<int, std::allocator >&, std::vector<float,
std::allocator >&) const’未定义的引用
kdtree.cpp:(.text+0x7cb):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::radiusSearch(pcl::PointXYZ const&, double,
std::vector<int, std::allocator >&, std::vector<float,
std::allocator >&, unsigned int) const’未定义的引用
CMakeFiles/kdtree.dir/kdtree.cpp.o:在函数‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::~KdTreeFLANN()’中:
kdtree.cpp:(.text._ZN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEED2Ev[_ZN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEED5Ev]+0x27):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::cleanup()’未定义的引用
CMakeFiles/kdtree.dir/kdtree.cpp.o:(.data.rel.ro._ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE[_ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE]+0x10):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple
::setInputCloud(boost::shared_ptr<pcl::PointCloudpcl::PointXYZ const> const&, boost::shared_ptr<std::vector<int, std::allocator
const> const&)’未定义的引用 CMakeFiles/kdtree.dir/kdtree.cpp.o:(.data.rel.ro._ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE[_ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE]+0x28):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::nearestKSearch(pcl::PointXYZ const&, int,
std::vector<int, std::allocator >&, std::vector<float,
std::allocator >&) const’未定义的引用
CMakeFiles/kdtree.dir/kdtree.cpp.o:(.data.rel.ro._ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE[_ZTVN3pcl11KdTreeFLANNINS_8PointXYZEN5flann9L2_SimpleIfEEEE]+0x40):对‘pcl::KdTreeFLANN<pcl::PointXYZ,
flann::L2_Simple >::radiusSearch(pcl::PointXYZ const&, double,
本来是想在bypy基础上搞个自动传输系统,都准备最后收拢了,突然bypy就不能使用了。
还是果断放弃靠不住的这个软件了。因为将来终究这个软件是不能适应网络变化的。直接使用云盘同步功能,虽然百度会去掉文件最后修改时间的信息,但是可以先将信息放在文件名字上,下载后再写回来就可以了。这样也大大简化了系统,只要完成自动存档功能和及时运送文件到云同步区就可以了。
不过通过这个练习还是对python有了较扎实的认识。对程序设计也有了更透彻的理解认识。能够操控多个程序同时运行,用txt文件联系不同 的程序。认识到程序设计应先将大思路理清,将目标制定后,就深入研究各个环节所需要的概念和对应的实体,并根据不同的特性设计各个环节,例如为了对抗网络失败,让一个子程序不断去循环,就算子程序死掉还可以再激活,只要网络一通就会去完成任务。根据云文件难以把控的实际情况设计了镜像映射的方案,将复杂的文件树映射成序列以列表和txt文本进行传输。为了确保传递的安全性,建立了各种日志,以便查阅分析。总而言之,为了完成这个ZDCS系统,还是展开了很广泛深入的研究。对程序和人的对话沟通也有了认识。虽然最终将只保留一个简化版本,但是积累了相当多有价值的知识。
文件操作是其中的核心任务之一。之前没注意到正则表达式,对字符串的处理多走了点弯路。文件及文件夹的处理非常繁琐无聊,不过再回首也权当做了一次很深入的练习吧。
# -*- coding:utf-8 -*-
import os
import time
import shutil
# 01 判断是否为汉字,copy网友的
def ischin(uchar):
"""判断一个unicode是否是汉字"""
if uchar >= u'\u4e00' and uchar<=u'\u9fa5':
return True
else:
return False
##str.isalnum() #所有字符都是数字或者字母
##str.isalpha() #所有字符都是字母
##str.isdigit() #所有字符都是数字
##str.islower() #所有字符都是小写
##str.isupper() #所有字符都是大写
##str.istitle() #所有单词都是首字母大写
##str.isspace() #所有字符都是空白字符、\t、\n、\r
# 02 获取一个文件夹里的所有第一级子文件夹和文件
def DFfl(PATH):
XL = os.listdir(PATH )
XL.sort()
DLb = []
FLb = []
for patha in XL:
if os.path.splitext(patha)[1]=='':
DLb.append(patha)
在使用eslint时 我们明明以及使用了枚举但是就是报错 这个是因为Eslint不支持 TypeScript 语法
只需要在eslintrc.js中配置
"@typescript-eslint/no-unused-vars" : [ "error" ] 就可以了
<v-select v-model="identity_claim" :items="identity_claims" item-text="display_name" item-value="name" :readonly="is_readonly" :disabled="is_readonly" required :rules="rules.notNullRules" @change="identityChange(identity_claim)" > </v-select> 之前的错误写法:
export default { data(){ identity_claim: { display_name: "用户ID(默认)" }, identity_claims: [], }, methods:{ identityChange(identity) { this.identity_claim.display_name identity; } } } 正确写法:
export default { data(){ identity_claim: { display_name: "用户ID(默认)" }, identity_claims: [], }, methods:{ identityChange(identity) { this.identity_claim = { display_name: identity }; } } }
combobox组件,当修改值的时候,修改完之后需要点击修改框以外的地方,相当于失去焦点后获取的最终的input框的值,v-combobox组件中的值才能被更新,这样就会存在一个问题,如果用户修改后直接点击提交或保存,提交上的值还是更改前的值。
解决方法:@input.native
<v-combobox v-model="item.claim" :items="allSelectDatas[allDatas.type]" :item-value="item.claim" persistent-hint hint="身份源属性" :rules="rules.notNullRules" @input.native=" item.claim = $event.target.value; hideDropdown = true; " :menu-props="{ ...(hideDropdown && { value: false }) }" @click="hideDropdown = false" > </v-combobox>
✨前言✨ N皇后问题经典的解决方案是暴力递归,其时间复杂度是O(2^n),因此常用来测试计算机的算力。今天我会给大家带来经典方法的详解,也会给大家展示N皇后优化后的大神解法。做一道经典题目,来一场思维旅行。
目录
✨前言✨
💡题目:
🔑传统解法:
代码示例:
大神解法:
💡题目: n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。
力扣题目链接: N皇后问题
🔑传统解法: N皇后的传统解法是暴力递归,在我看来暴力递归的精髓就是尝试,N皇后问题要求任意两个皇后都不共行,不共列,不共斜线。因此在一个N*N的棋盘上放N个皇后,因此可以看成由上到下每一行放一个皇后的尝试模型。
为了更形象的解决这一问题,我们先来看一下图:(来自力扣)
因为我们尝试模型是遍历每一行,每一行尝试放一个皇后,所以所有皇后一定不共行,只需保证在尝试第i个皇后时,第i个皇后与第i-1个皇后不共列,不共斜线,因此我们应该在尝试0-i-1个皇后时,记录下其位置,这样在放第i个皇后时,就可以根据之前所有已经放好的皇后决定第i个皇后应该放哪里。
所以设计的递归函数的参数有三个:
1:变量i表示现在在尝试第i行放第i个皇后
2:变量n表示要放皇后的总数,是一个固定的值,用来标记递归终止条件。
3:数组 result[i] 记录已经放好的皇后在哪一行哪一列,表示第i个皇后所在的列数。
代码示例: //暴力递归:N皇后问题的朴素解法 //1:当你处理第i行时,我们默认[0...i-1]的皇后都有效摆好了 //2:当你摆第i个皇后时,你只需要考虑i个皇后与其它i-1个皇后不共列和不共斜线 //三个参数:record[i] 记录下第i个皇后所在的列数 //int n表示是几阶皇后问题 //int i表示当前处理到了哪一阶 public static int process1(int i,int n,int[] record){ if(i==n){//当i等于n时,说明N个皇后全部摆放完毕,此时应返回一种解法 return 1; } int res=0; //现在轮到摆第i个皇后, //通过遍历第i行的每一列试探每一个位置是否能放皇后 for(int j=0;j<n;j++){ if(isValid(record,i,j)){//通过isValid函数来判断这个位置是否能放皇后 record[i]=j; res+=process1(i+1,n,record); } } return res; } public static boolean isValid(int[] record,int i,int j){ //判断逻辑:如果这个位置与之前的i-1个皇后同列或者共斜线则不能放皇后 for(int k=0;k<i;k++){ //判断共列以及共斜线 if(record[k]==j||(Math.
知识点 Floyd 算法
是用来求任意两个结点之间的最短路的;
复杂度比较高,但是常数小,容易实现。(我会说只有三个 for 吗?)
适用于任何图,不管有向无向,边权正负,但是最短路必须存在。(不能有个负环)
算法实现 我们定义一个数组 f[k][x][y],表示只允许经过结点 1 1 1 到 k k k(也就是说,在子图 V ′ = 1 , 2 , 3 , . . . , k V' = 1,2,3,...,k V′=1,2,3,...,k 中的路径,注意, x x x 与 y y y 不一定在这个子图中),结点 x x x 到结点 y y y 的最短路长度。
很显然,f[n][x][y] 就是结点 x x x 到结点 y y y 的最短路长度(因为 V ′ = 1 , 2 , 3 , .
拓扑排序 (1)在有向图中选一个没有前驱的顶点且输出之;
(2)在图中删除该顶点和所有以它为尾的弧。
重复上述两个步骤,直至全部顶点均已输出,或者当前图中不存在无前驱节点的顶点为止,后一种情况则说明有向图中存在环
最后得到的有向图的拓扑序列为:
算法实现 //算法7.12 Status TopologicalSort(ALGraph G){ int i, k, count, indegree[MAX_VERTEX_NUM]; SqStack S; ArcNode *p; FindInDegree(G, indegree); // 对各顶点求入度indegree[0..vernum-1] InitStack(&S); // 初始化栈 for (i = 0; i < G.vexnum; ++i) // 建零入度顶点栈S if (!indegree[i]) Push(&S, i); // 入度为0者进栈 count = 0; // 对输出顶点计数 while (!StackEmpty(S)){ // 栈不空 Pop(&S, &i); printf("%s ", G.vertices[i].data); // 输出i号顶点并计数 ++count; for (p = G.vertices[i].firstarc; p; p = p->nextarc){ // 对i号顶点的每个邻接点的入度减1 k = p->adjvex; if (!
使用pip 安装:
pip install python-opencv 在网络距离美国较远的情况下,或PIP版本未达到要求的情况下,会install 失败。
解决方法 1. 重试
2.科学方法,这里说明使用科学方法的端口问题,切记不要和本地计算机 使用同一个端口,容易造成Pycharm未知错误。
3.手动去官网下载文件
这里有两种类型的手动安装文件
setup.py
XXXX.whl
以上两种文件都可以通过 pycharm 的命令行工具直接cd 到目录进行直接安装。
方法:1 python setup.py install
pip 安装较为简单。
2 pip install C:windows/system/001/002.whl的
后面的路径为 XXXX.whl 文件的所在地址。
如果地址不知道到,可以通过属性查看。
帮助无法安装的朋友。
参考了博客:html中加号实体,纯css实现加号“+”效果(代码示例)_Paquars的博客-CSDN博客
实际上就是用两个伪元素选择器实现的。
但是在测试过程中,发现::after这个选择器鼠标完全点击到这根线上时,此时选择文件的窗口弹不出来。因此最后选择了 只用::before实现一条杠的效果,然后用一个div实现了另外一条杠的效果。(当然两个杠都可以用div实现,用伪元素选择器只是因为一开始我不会写百度资料所得到的方法,另外是用选择器代码看起来简单些)
附上代码:
h5
<div class="chuans" style="height: 20rem;"> <div class="shu"></div> <img th:src="@{${task.attachmentPath}}" alt="" data-imgsrc="" id="imageA"> <input class="uploadImg file1" type="file" name="file1" id="filePath" accept="image/*"> </div> css
div.chuans { position: relative; width: 240px; height: 20rem; border-radius: 3px; border: 1px dashed #ccc; margin: auto; overflow: hidden; } div.chuans::before{ content: ''; position: absolute; left: 50%; top: 50%; width: 80px; margin-left: -40px; margin-top: -1px; border-top: 2px solid; } div.chuans .shu { content: ''; position: absolute; left: 50%; top: 50%; height: 80px; margin-left: -1px; margin-top: -40px; border-left: 2px solid; } div.
1.通过conda官网下载cv速度极慢
2.通过pip命令下载很快
安装opencv-python: (使用清华镜像安装)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
#include<bits/stdc++.h> using namespace std; int main() { int n,a,i,s; cin>>n; cin>>a; s=a; for(i=2;i<=n;i++) { cin>>a; if (s<a) s=a; } cout<<s; return 0; }
消息转换器 配合注解,实现接口返回 JSON 数据
Spring MVC中使用消息转换器HttpMessageConverter对JSON的转换提供了很好的支持
在Spring Boot中更进一步,对相关配置做了更进一步的简化,添加 Web 依赖 spring-boot-start-web 后,这个依赖中默认加入了jackson-databind作为JSON处理器,此时不需要添加额外的JSON处理器就能返回一段JSON了
com.fasterxml.jackson.annotation.JsonFormat
com.fasterxml.jackson.annotation.JsonFormat
package cn.yto.server.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; /** * <p> * 实现 WebMvcConfigurer 接口,自定义 Spring MVC 配置<br> * 1、添加拦截器<br> * 2、配置消息转换器 MappingJackson2HttpMessageConverter * </p> * * @author yanyg * @date 2021/9/10 11:17 */ @Configuration public class WebConfigurer implements WebMvcConfigurer { @Autowired private AppLoginInterceptor appLoginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 登录拦截器 registry.
这种问题有主要分为两类: 1、代码中将字符转大写或小写,然后使用equals方法进行比较,这类问题一般都比较好处理,字符串不再进行大小写转换,直接使用equalsIgnoreCase()方法替换equals方法即可; 如下为存在漏洞的代码
String srt1 = "http"; String srt2 = "HTTP"; srt1.toUpperCase().equals(srt2);//存在漏洞 修改后的代码
String srt1 = "http"; String srt2 = "HTTP"; srt1.equalsIgnoreCase(srt2);//漏洞解决 2、代码中需要判断字符串是以什么开头或者以什么结尾,此时equalsIgnoreCase()方法没有办法直接使用,所以,可以将字符串先进行截取,然后再使用equalsIgnoreCase()比较; 如下为存在漏洞的代码
String srt1 = "https://www.baidu.com"; String srt2 = "https"; srt1.startsWith(srt2);//存在漏洞 修改后的代码
String srt1 = "https://www.baidu.com"; String srt2 = "https"; if(srt1 != null && srt1.length() > 5) { srt1 = srt1.substring(0, 5); srt1.equalsIgnoreCase(srt2);//漏洞解决 }
知识点 假若在删去顶点v以及和v相关联的各边之后,将图的一个连通分量分割成两个或两个以上的连通分量,则称顶点v为该图的一个关节点(articulation point)。一个没有关节点的连通图称为是重连通图(biconnectedgraph)。在重连通图上,任意一对顶点之间至少存在两条路径则在删去某个顶点以及依附于该顶点的各边时也不破坏图的连通性。若在连通图上至少删去k个顶点才能破坏图的连通性,则称此图的连通度为k。关节点和重连通在实际中有较多应用。
显然,一个表示通信网络的图的连通度越高,其系统越可靠,无论是哪一站点出现故障或遭到外界破坏,都不影响系统的正常工作;又如,一个航空网若是重连通的,则当某条航线因天气等某种原因关闭时,旅客仍可从别的航线绕道而行;再如,若将大规模集成电路的关键线路设计成重连通的话,则在某些元件失效的情况下,整个片子的功能不受影响,反之,在战争中,若要摧毁敌方的运输线,仅需破坏其运输网中的关节点即可。
算法实现 //算法7.10 void FindArticul(ALGraph G) { //连通图G以邻接表作存储结构,查找并输出G上全部关节点。算法7.10 // 全局量count对访问计数。 int i, v; ArcNode *p; int count; count = 1; low[0] = visited[0] = 1; //设定邻接表上0号顶点为生成树的根 for (i = 1; i < G.vexnum; ++i) visited[i] = 0; //其余顶点尚未访问 p = G.vertices[0].firstarc; v = p->adjvex; DFSArticul(G, v); // 从第v顶点出发深度优先查找关节点 if (count < G.vexnum) // 生成树的根有至少两棵子树 { printf("%d %s\n", 0, G.vertices[0].data); // 根是关节点,输出 while (p->nextarc) { p = p->nextarc; v = p->adjvex; if (visited[v] == 0) DFSArticul(G, v); } } } //算法7.
视频转换为图片
from time import gmtime, strftime
import cv2
videoFile = ‘/media/kingstar/kingstardata/safety_eyes/nohatdata/7.mp4’
cap = cv2.VideoCapture(videoFile)
cap.set(3,640)
cap.set(4,480)
while(True):
ret, frame = cap.read()
img = frame
cv2.imshow(‘my’, img)
f = strftime("%Y%m%d%H%M%S.jpg", gmtime())
cv2.imwrite(‘output/’+ f, img)
if cv2.waitKey(1) & 0xFF == ord(‘q’):
break
if img.size == 0:
break
cap.release
cv2.destroyAllWindows()
题目3(二叉排序树)[问题描述] 利用二叉查找树(又称为二叉排序树、二叉搜索树)实现对输入的英文单词进行搜索,同时可给出单词出现的次数。(难易程度:高)
[实验目的] 1、掌握二叉链表的存储结构。
2、掌握搜索和过滤的方法。
3、掌握二叉排序树的插入和删除操作。
[实验内容及要求] 1、构造二叉查找树
(1)从文本文件中读入文本内容,能够分离出单词,过滤掉阿拉伯数字和标点符号,并将英文字母的大写形式全部转换成小写形式。
(2)按照英文字母表的顺序构造英文单词的二叉查找树。当两个英文单词的首字母相同时,按第二个字母进行排序,依次类推。
(3)当待插入的单词已在二叉查找树中,则将该单词的出现次数增1。
2、遍历二叉查找树
(1)搜索:输入一个待检索单词,在二叉查找树中进行查找,如果能找到该单词,则输出该单词及其出现次数;
(2)实现二叉查找树的中序遍历,并将遍历结果输出到屏幕上,包括单词和单词出现的位置。
3、删除结点:
给定一个停用词列表(停用词是指对搜索没有作用的词,如: of , and , a , an , the 等等),将二叉查找树中的属于停用词表中的单词依次删除。
4、可以显示菜单,在菜单中可以进行如下四项操作(但并不局限这些操作):
(1)读入文本内容,包含若干英文单词、标点符号以及阿拉伯数字,用于构建二叉查找树。
(2)输入停用词,每个停用词占一行。对于每个停用词,都需要删除二叉查找树中的相应结点,即:每输入一个停用词,执行一次删除结点的操作。
(3)中序遍历二叉查找树,遍历结果中的每个单词占一行,先输出该单词,然后输出一个空格,再输出该单词出现的次数。
(4)输入查询词。对每个查询词,都需要在二叉查找树中的搜索相应结点,如果找到,则输出该单词及其出现次数;如果未找到,则输出相应的信息。每个查询词的查询结果占一行,先输出该单词,然后输出一个空格,再输出该单词出现的次数。
[测试数据] 1、输入的文本含有大小写字母、阿拉伯数字、标点符号及其它字符。
2、单词的数量应当足够多,并有一定量的相同单词。
#include<iostream> #include<algorithm> #include<vector> #include<cstdlib> using namespace std; typedef struct BST { int cnt; string data; BST* lchild, * rchild; }BSTNode,*BSTree; bool BST_Insert(BSTree& T, string data){ if (T == NULL) { T = new BSTNode; T->data = data; T->cnt = 1; T->lchild = T->rchild = NULL; return true; } else if (data < T->data) { return BST_Insert(T->lchild, data); } else if (data > T->data) { return BST_Insert(T->rchild, data); } else {// 已存在值不插入 T->cnt++; return false; } } bool BST_Dele(BSTree& T, string data){ if (T == NULL) return false; if (T->data == data){ BSTree p, q; // 前驱 后继 //如果左右儿子都有比较难删除 if (T->lchild && T->rchild){ p = T; q = p->lchild; while (q->rchild) { // 寻找左子树最大 p = q; q = q->rchild; } T->data = q->data; T->cnt = 0; if (p !
mysql8.0倒叙索引:ALTER TABLE tableName ADD INDEX IDX_C1_DESC(AA DESC);
实测从20秒降到0.1秒
mysql5.6:mysql> set global optimizer_switch='index_condition_pushdown=off';
实测10W条数据从20秒降到0.5秒
文章目录 顺序查找1. 无序表的顺序查找python代码实现算法分析 2. 有序表的顺序查找python代码实现算法分析 顺序查找 如果数据项保存在如列表这样的集合中,我们会称这些数据项具有线性或者顺序关系。
在Python List中,这些数据项的存储位置称为下标(index),这些下标都是有序的整数,从零开始,到n-1结束(n为数据项的数量)。
通过下标,我们就可以按照顺序来访问和查找数据项,这种技术称为“顺序查找”。
1. 无序表的顺序查找 对于无序表的查找,首先从列表的第1个数据项开始,按照下标增长的顺序,逐个比对数据项,如果到最后一个都未发现要查找的项,那么查找失败。
python代码实现 def sequential_search(a_list, item): """ 无序表的顺序查找 :param a_list: 被查找列表 :param item: 目标元素 :returns: 元素是否在列表中被找到 """ # 从列表中一个个取出元素进行比较 for i in a_list: # 找到值相同的元素,说明查找成功 if i == item: return True # 所有元素都取完还未找到,说明查找失败 return False 算法分析 在查找算法中,基本计算步骤就是进行数据项的比对,对比的次数决定了算法复杂度。
无序表中的数据项并没有按值排列顺序,而是随机放置在列表中的
各个位置。换句话说,数据项在列表中各处出现的概率是相同的:
最好的情况下,目标元素被放在列表的第一个位置,第1次比对就找到。最坏的情况下,目标元素被放在列表末尾或者根本不在列表中,那就需要n次比对。因为数据项在列表中各个位置出现的概率是相同的。所以平均状况下,比对的次数是n/2。 情况最好情况最坏情况平均情况元素存在1nn/2元素不存咋在1nn/2 所以,顺序查找的算法复杂度是 O ( n ) O(n) O(n)。
2. 有序表的顺序查找 当数据项存在时,比对过程与无序表完全相同不同之处在于,如果数据项不存在,比对可以提前结束。
比如,列表从小到大排列,我们要查找31,当我们查找到32(或者更大的数字)的时候还没有找到,那么就没有必要再去后面查找了。
python代码实现 我们以从小到大排序的列表为例。
def ordered_sequential_search(a_list, item): """ 有序表的顺序查找 :param a_list: 被查找列表 :param item: 目标元素 :returns: 元素是否在列表中被找到 "
1、桌面空白处右键选择【在这里打开终端】
2、sudo apt update
更新软件列表时,提示”Hash 校验和不符“,如下图所示。
3、su
解决方法,首先切换到root用户。
4、mkdir /etc/gcrypt
建立gcrypt目录。
5、echo all >>/etc/gcrypt/hwf.deny
输入all到所有hwf.deny文件。
6、apt update
update第一次失败则多尝试update两次就可以了。
正常更新软件包列表了。
这个问题是我在一个模块工程下出现的,使用maven配置环境,多个项目在同一工程下,出现err:找不到XXX包或者符号…
我在网上查找并尝试很多方法,最后得以解决,再次汇总起来,让大家少走弯路!
在idea的命令行中输入命令执行使用mvn idea:ideaj进行重构,这个作用就是:maven依赖更新不完整命令,强制刷新idea缓存,我认为这个一般可以很大几率解决问题!我的问题就是使用该方法解决的。
在项目右键,找到maven --> reimport ,或者在项目右键找到rebuild module尝试,这个不行的话是因为: .maven实际是完整的,本地也有这个jar包.
如果是idea2020.1的bug ,你去么在maven runner里把这个勾上可以解决. 去掉就又不行了,这个作用是将build/run 动作委托给了 maven,但是随着项目的增大或者废需求导致项目启动很慢,因为maven加载了许多废物资源,因此一般建议不勾选。
还有一种说法是 将maven的settings.xml中的localrepository修改成默认(如果你改了仓库地址);这个方法我没试过应该也可以,因为就是为了让他重新在另一个文件夹中下载jar包
在file菜单,invalidateCatch/Restart ,清除idea项目caches,然后重启idea后 ,发现刚刚没报错但又找不到的那个类此时报红了,这时候reimport maven 就可以重新下载jar包了.
或者换一个idea版本(hhh)
这是对于找不到包的解决方法汇总,当然前提必须确认包已经导入!最后,谢谢提供这些问题的xdm,前人的总结,正是为了后人少走弯路!
上一篇我们使用了一个全局Map缓存来所有的Activity类,显然这是非常麻烦的,一旦有所改动,就要手动修改该Map 为此,我们希望将key和Activity类的映射关系,通过一定方式自动导入Map。利用注解解析器(APT)和代码生成器(kotlinpoet)可以根据注解在编译期间就生成相应的代码,业界称之为Router机制 一、Gradle配置及架构分层 在实现Router机制之前,我们还可以对项目的组织架构进行优化,将gradle中公用部分抽出来
有了上一篇的基础,我们初步实现了架构分层,目前有三个module:
其依赖关系为: app << libmodule_a << libase,但是每个module的gradle中都有重复的内容,如版本号、版本名、SDK版本、重复依赖等,我们可以利用groovy和gradle的知识,为它们设计成共用属性 1.创建config.gradle 在工程下新建一个config.gradle文件
将重复的内容设置成全局属性:
ext { isDebug = false kotlinVersion = "1.5.31" // 版本信息 androidVersion = [ compileSdk : 31, minSdk : 21, targetSdk : 31, versionCode: 1, versionName: '1.0' ] applicationId = [ app : "com.aruba.arouterapplication", module_a: "com.aruba.libmodule_a" ] androidxCore = 'androidx.core:core-ktx:1.3.2' androidAppCompat = 'androidx.appcompat:appcompat:1.2.0' androidMaterial = 'com.google.android.material:material:1.3.0' androidConstraintLayout = 'androidx.constraintlayout:constraintlayout:2.0.4' } 2.在主工程Gradle中,引入config.gradle apply from: 'config.gradle' buildscript { repositories { .
报错:could not establish connection to“”,get bad result from install script
试过网上的方案:
修改注册表:https://github.com/microsoft/vscode-remote-release/issues/5693——不行,注册表里没那个值完全卸载后重装:https://github.com/microsoft/vscode-remote-release/issues/5722——不行,还是报一样的错 折腾了一下午,想着换个安装包试试,看到有 insiders 版本
于是按以下步骤:
完全卸载vscode删除 用户目录下.ssh 文件夹里的配置文件
安装 insiders 版本的 vscodessh正常! 顺便想问下各位大佬,vscode remote终端能否自定义关键字(例如error、warning、info等)高亮呢?使用默认的cmd或者bash终端只能高亮用户名和文件夹,代码里打印输出的信息都是黑底白字的,找个error都得找半天。。。
一、什么时候使用重载?
当我们使用一个函数同时兼容多种参数的情况下就可以使用到方法的重载
二、重载需要解决的问题
public class TestDemo { //1、先写一个方法 public static int addNum(int x, int y) { return x + y; } //2、在main函数中调用这个方法 public static void main(String[] args) { int a = 50; int b = 40; int ret1 = addNum(a, b); System.out.println(ret);//这里是正常的求a和b的和 //当我们想再想求不同类型的和的时候就会出现问题 double d1 = 12.3; double d2 = 66.6; double ret2 = addNum(d1,d2);//这里就会出现问题 System.out.println(ret2); } } 报错原因:java: 不兼容的类型: 从double转换到int可能会有损失
结 论:由于参数类型不匹配,addNum方法中是int类型,而这里却是double的
三、如何解决呢?
我们先来了解一下重载的规则:
1.方法名称相同
2.方法的参数不相同(参数个数或参数类型)
2.方法的返回值不作要求
方法名称相同
感知机 单层感知机 1958 年,罗森布拉特( Roseblatt )提出了感知器,与 M-P 模型需 要人为确定参数不同,感知器能够通过训练自动确定参数。训练方式为有监督学习,即需要设定训练样本和期望输出,然后调整实际输出和期望输出之差的方式(误差修正学习)。
下面给出感知器模型的训练过程
多层感知机 单层感知器只能解决线性可分问题,而不能解决线性不可分问题;为了解决线性不可分问题,我们需要使用多层感知器。
多层感知器指的是由多层结构的感知器递阶组成的输入值向前传播的网络,也被称为前馈网络或正向传播网络。
以三层结构的多层感知器为例,它由输入层、中间层及输出层组成
与M-P模型相同,中间层的感知器通过权重与输入层的各单元相连接,通过阈值函数计算中间层各单元的输出值
中间层与输出层之间同样是通过权重相连接
BP算法 BP算法的基本过程 前向传播计算:由输入层经过隐含层向输出层的计算网络输出
误差反向逐层传递:网络的期望输出与实际输出之差的误差信号由输出层经过隐含层逐层向输入层传递
由“前向传播计算”与“误差反向逐层传递”的反复进行的网络训练 过程
BP算法就是通过比较实际输出和期望输出得到误差信号,把误差信 号从输出层逐层向前传播得到各层的误差信号,再通过调整各层的连接权重以减小误差。权重的调整主要使用梯度下降法:
激活函数 通过误差反向传播算法调整多层感知器的连接权重时,一个瓶颈问题就是激活函数:
M-P 模型中使用阶跃函数作为激活函数,只能输出 0或 1,不连续所以 不可导为了使误差能够传播,鲁梅尔哈特等人提出使用可导函数Sigmoid作为激活函数 其他常见的激活函数:ReLU (Rectified Linear Unit,修正线性单元)和tanh等
rosdep update问题解决方案
1.我的rosdep init成功,如果失败执行
sudo mkdir -p /etc/ros/rosdep/sources.list.d cd /etc/ros/rosdep/sources.list.d sudo touch 20-default.list 2.在github下载ros的相关代码下载目录
解压缩后放在任意目录下
3.修改步骤1中的20-default.list文件,主要是改网站为本地目录
# os-specific listings first yaml file:///home/xxx/rosdistro/rosdep/osx-homebrew.yaml osx # generic yaml file:///home/xxx/rosdistro/rosdep/base.yaml yaml file:///home/xxx/rosdistro/rosdep/python.yaml yaml file:///home/xxx/rosdistro/rosdep/ruby.yaml gbpdistro file:///home/xxx/rosdistro/releases/fuerte.yaml fuerte # newer distributions (Groovy, Hydro, ...) must not be listed anymore, they are being fetched from the rosdistro index.yaml instead 4…修改在__init__.py文件中修改index-v4.yaml的位置
在shell下执行命令sudo vim /usr/lib/python3/dist-packages/rosdistro/__init__.py
#DEFAULT_INDEX_URL = 'https://raw.githubusercontent.com/ros/rosdistro/master/index-v4.yaml' DEFAULT_INDEX_URL = 'file:///etc/ros/rosdistro/index-v4.yaml' 再修改sudo vim /usr/lib/python3/dist-packages/rosdep2/rep3.py
# location of targets file for processing gbpdistro files #REP3_TARGETS_URL = 'https://raw.
因为公司发展,计划上管理系统,考察了几个开源的管理软件,感觉针对国内应用环境和小公司的基本需求,做的不是很好,于是转向了国产开发的系统。这样发现了一个我感觉比较满意的,就是标题所示,服务社出的免费协同管理系统OA,软件里面叫企语系统,网上一般说协同管理系统。
虽然在其官网上说在Linux和Windows系统上都可以安装,但是经过我的搜索,其官方给出的仅仅是CentOS系统下的自动安装脚本。网络上也有几个文库里面,还能找到关于10.2,13.8的linux安装的介绍。
因为centos 2021年底就不再是以前的政策了,所以,考虑在我已经熟悉起来的Debian系统上进行安装。
这里介绍的是 Debian11系统,数据库采用MySQL_5.7.35,JDK和Tomcat保持和官方一致的安装过程。
先上个截图:
一、安装过程概述
1.安装Mysql数据库,导入软件解压缩后db/文件夹中的数据库文件;
2.下载jdk1.7.0,解压,并为其配置环境变量;
3. 对从网盘中下载并解压后的官方软件进行配置文档参数的替换;
4.运行 /usr/local/fuwushe/tomcat/bin/ 中的startup.sh文档,启动系统;
5. 输入网址:http://server-ip:8080/cc 进入主控系统,进行系统设置和应用。
二、数据库的安装。
官网提供的数据库还是mysql-5系列的,不过版本号比较旧,这里我们直接采用了5系列里最新版的 mysql.5.7.35 。至于最新版的Mysql.8.0.27,在我的测试中,导入数据库文件时会有3个文件报错,跑不起来!!
经过使用,发现用5.7.35,有可能会导致 系统维护➡数据备份 功能无法使用,右侧的设置项不会显示!!
安装 5.6.51版本即可。参考url: https://blog.csdn.net/lggirls/article/details/121457977 1. 从url:https://downloads.mysql.com/archives/community/ 选择和下载适合Debian系统的数据库安装包。要下载 DEB Bundle 包。
2. 将下载后的 tar 包移动到一个独立的文件夹中,解压,运行如下命令进行集中安装:
apt install ./*.deb 在安装过程中会要求手动输入mysql的root用户的密码。
3. 增加配置文件,设定默认字符编码为 utf-8,如果不设置,部分中文会出现乱码,无法正常显示
cp /etc/mysql/my.cnf /etc/my.cnf vim /etc/my.cnf #在最下方增加如下内容 [mysql] default-character-set=utf8 [mysqld] character-set-server=utf8 [client] default-character-set=utf8 4. 导入官方软件包中db/文件夹内的 .sql 文件。注:先stfoa.sql,最后process.sql,不要mysql.sql
#这里采用的安装路径是和官方保持一致的 /usr/local/fuwushe/ 所以导入命令如下 mysql -uroot -pA123456! </usr/local/fuwushe/db/stfoa.sql mysql -uroot -pA123456!
记录当把本地项目运行在服务器上时出现的一些错误 错误种类一详情解决方法 错误种类二详情解决方法 错误种类三详情1解决方法详情2 错误种类一 详情 昨天在本地刚把后端的一些漏洞补完,今天想着把项目放服务器上试一试。奇怪的是项目根本打不开,提示信息是这样的:
FileNotFoundError: Could not find module
‘C:\Users\biewang\AppData\Local\Programs\Python\Python39\lib\site-packages\pyzbar\libzbar-64.dll’
(or one of its dependencies). Try using the full path with constructor
syntax.
刚开始一直以为是我的pyzbar包出错了,删除重新下载。没用。把本地的pyzbar复制到服务器上,也没用。
解决方法 解决方法是把c:\Windows\System32里面的msvcr120_clr0400.dll复制到pyzbar包里面,重命名为msvcr120.dll .
具体原因以及解决机制如下:
https://blog.csdn.net/qq_34146694/article/details/120003977
错误种类二 详情 嗯,在解决了上面那个困扰了好久的问题之后,满心欢喜的打开了网页。幸好,打开网页是正常的。可是,当我在网站上传我的图片时,它直接提示我服务器错误:
The server encountered an internal error and was unable to complete
your request. Either the server is overloaded or there is an error in
the application.
刚开始我以为是我代码哪里有问题。也是一直找找不到。哈,还是摆脱不了这个毛病,刚开始学出错了总觉得是自己代码写的有毛病(虽然我专业是计算机相关的,但完整的项目开发还真是没什么经验)。服务器本地运行没问题,代码能跑通。这个时候我终于开窍了,开始查看服务器的访问日志,错误日志。
访问日志报错如下:
101.35.170.223 - - [23/Nov/2021:15:12:32 +0800] “POST /file HTTP/1.
文章目录 1 函数调用和汇编1.1 函数的调用约定1.2 堆栈平衡1.3 汇编码1.3.1 寄存器1.3.2 指令 1.4 栈帧1.4.1 开辟栈帧1.4.2 栈帧回退 2 汇编解析2.1 函数调用流程 1 函数调用和汇编 1.1 函数的调用约定 C函数的默认调用约定是__cdeclC++全局函数和静态成员函数的默认调用约定是__stdcall类的成员函数的调用约定是__thiscall 函数生成符号不同
函数参数入栈顺序不同
void __stdcall swap(int a,int b) { int tmp = a; a = b; b = tmp; } 1.2 堆栈平衡 因为函数调用过程中,参数需要压栈,所以在函数调用结束后,用于函数调用的压栈参数也需要退栈。 调用约定堆栈平衡方式__stdcall函数自己平衡__cdecl调用者负责平衡__thiscall调用者负责平衡__fastcall调用者负责平衡__naked编译器不负责平衡,由编写者自己负责 1.3 汇编码 1.3.1 寄存器 寄存器ebp(base pointer ):帧指针或基址指针,栈底指针寄存器esp(stack pointer):栈指针,栈顶指针 1.3.2 指令 lea eax,dword ptr [b]:将b地址的偏移量保存到寄存器eax中mov ebp,esp:将esp指向内存中的数据保存到目的寄存器ebp中call swap():将程序跳转到目标函数处执行。
首先将call指令的下一条指令的地址(当前指令地址寄存器EIP中的地址+偏移量4个字节)压栈;
然后执行jump指令跳转到调用函数的入口,即函数的开始地址。ret:将栈顶保存的地址弹出到EIP中 #include<iostream> using namespace std; int swap(int a,int b) { int tmp = a; a = b; b = tmp; return a; } int main() { int a = 10; int b = 20; swap(a, b); return 0; } 1.
接口的定义 接口泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式。
人类与电脑等信息机器或人类与程序之间的接口称为用户界面。电脑等信息机器硬件组件间的接口叫硬件接口。电脑等信息机器软件组件间的接口叫软件接口。
在计算机中,接口是计算机系统中两个独立的部件进行信息交换的共享边界。这种交换可以发生在计算机软、硬件,外部设备或进行操作的人之间,也可以是它们的结合。
接口的优势 一、规范性 接口就是规范,在整个系统设计中,涉及到很多层,为了使各个层之间调用透明话,你只需要知道接口,按照这个接口做你具体做的事情,就可以融合到整个系统中了。
生活中的例子很多,例如:插头、插座,有标准的规范告诉你插头应该是几个脚,插座是几个孔等等,做插头、插座的公司就是根据这个规范来做插头、插座,而不需要做完一个插头就跑遍全世界去试用一下这个插头做的对不对。
二、扩展性 在项目开发过程中,由于客户的需求经常变化,如果不采用接口,那么我们必须不停改写现有的业务代码。改写代码可能产生新的BUG,而且改写代码还会影响到调用该业务的类,可能全都需要修改,影响系统本身的稳定性。到最后,可能会出现代码凌乱,不易读懂,
后接手的人无法读懂代码,系统的维护工作越来越重,最终可能导致项目失败。
Java接口的定义 接口在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
Java接口的作用 通过接口可以实现不相关类的相同行为,而不需要了解对象所对应的类。通过接口可以指明多个类需要实现的方法。通过接口可以了解对象的交互界面,而不需了解对象所对应的类。 类描述了一个实体,包括实体的状态,也包括实体可能发出的动作。
接口定义了一个实体可能发出的动作。但是只是定义了这些动作的原型,没有实现,也没有任何状态信息。
所以接口有点象一个规范、一个协议,是一个抽象的概念;而类则是实现了这个协议,满足了这个规范的具体实体,是一个具体的概念。
从程序角度,简单理解,接口就是函数声明,类就是函数实现。需要注意的是同一个声明可能有很多种实现。
1、接口中定义类方法的原型,但是不能说是空方法,因为空方法的意思是有实现体,只不过实现体是空操作。实际上接口没有定义任何实现体。具体的实现体都是在实现接口的类中,接口只是定义了这些方法的调用方式。
你当然也可以不用接口,直接在类里面写方法,但是如果你的一组方法需要在很多类里实现,那么把它们抽象出来,做成一个接口规范,不是更好么?
2、一个类描述了一个实体,这个实体可能是一个复杂的对象,它的动作很多,如果把这些动作分类,用接口a定义其中的某一组动作,接口b定义其中的另外一组动作,这样的结构,比较清楚。
这种方式具备了多继承的优点,避免了多继承的缺陷。实际上在历史上,接口在很大程度上,是为了解决多继承带来的种种问题而设计出来的。
3、包中那些已定义的接口,怎么知道那里面定义了什么方法。
接口里定义了方法的输入输出,这些都是协议,具体的实现都在每个类中。对于很多只需要抽象接口的地方,不需要知道具体的类是什么,只要这个类实现了这个接口就可以了。
Java接口的意义 接口会出现,最关键的原因应该是Java中向上转型的出现,因为向上转型,子类中一些父类中不存在的方法(或者说不共用的方法)便不能继续调用了。这样就很麻烦,我们需要子类中的方法,但是这下该怎么办呢?
第一种在父类中加子类的方法。但是,这个方法在父类中其实真的没有必要,方法函数体都不需要。所以会用抽象方法,这样就有了抽象方法的诞生。可是就算这样了,问题还是没有解决,因为真的太麻烦了,如果有其他的子类要继承父类,也难免会有向上转型的时候,那么,这个时候难道要一直往父类中加抽象方法么?显然不合理!
于是就有了第二种方法,接口便诞生了,这也解释了为什么接口中都是抽象的方法!所以有了接口,子类中需要的方法,但是父类中没有的方法可以直接用接口来完成,也就不用再修改父类的方法,在多人合作完成一项工程的时候也更加的方便。
Java接口的使用 两个类中的两个类似的功能,调用他们的类动态的决定一种实现,那他们提供一个抽象父类,子类分别实现父类所定义的方法。
问题的出现:Java是一种单继承的语言,一般情况下,哪个具体类可能已经有了一个超类,解决是给它的父类加父类,或者给它父类的父类加父类,直到移动到类等级结构的最顶端。这样一来,对一个具体类的可插入性的设计,就变成了对整个等级结构中所有类的修改。
1、可插入性 在一个等级结构中的任何一个类都可以实现一个接口,这个接口会影响到此类的所有子类,但不会影响到此类的任何超类。此类将不得不实现这个接口所规定的方法,而其子类可以从此类自动继承这些方法,当然也可以选择置换掉所有的这些方法,或者其中的某一些方法,这时候,这些子类具有了可插入性(并且可以用这个接口类型装载,传递实现了他的所有子类)。
我们关心的不是那一个具体的类,而是这个类是否实现了我们需要的接口。
接口提供了关联以及方法调用上的可插入性,软件系统的规模越大,生命周期越长,接口使得软件系统的灵活性和可扩展性,可插入性方面得到保证。
2、类型 使用Java接口将软件单位与内部和外部耦合起来。使用Java接口不是具体的类进行变量的类型声明,方法的返还类型声明,参量的类型声明,以及数据类型的转换。
在理想的情况下,一个具体的Java类应当只实现Java接口和抽象Java类中声明的方法,而不应当给多余方法。
3、等级结构 Java接口(以及抽象类)一般用来作为一个类型的等级结构的起点。
如果一个类已经有了一个主要的超类型,那么通过实现一个接口,这个类可以拥有另一个次要的超类型,这种次要的超类型叫做混合类型。
Java学习视频: 【Java300集】全新的Java300集来啦!java零基础小白自学Java必备优质教程
花2万多买的Java教程全套,现在分享给大家,入门到精通!Java300集_Java程序开发就业教程
esp32 板已经是16M的flash , 分区表用到8.1 M 理论是没问题的。
Partitions defined in 'mypartition.csv' occupy 8.1MB of flash (8454144 bytes) which does not fit in configured flash size 4MB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu.
然而,使用 pio run -t menconfig ,配置 flash 也为16Mb 无效!
理解:编绎时没接入板,与板的flash大小没关。修改配置无效,是因为编绎程序首先认为板是默认4M大小的。而pio run -t menconfig 只是修改配置项,只能在编绎成功时才能将配置一起并入目标码,可能这个编译顺序错误或提示错误。所以就要了解从哪里读到的是4M大小。plaftfromio 新建项目时,要选择板,其实每种板子都有它的配置文件。plaftfromio 先读取的是配置文件。由与是选的板子是esp32 dev module ,所以 配置文件是 esp32_dev.json。
解决: 修改 板的配置文件,这里是 esp32_dev.json.windows 一般位于{userProfile}\.platformio\platforms\espressif32\boards 目录下。环境重装时记得这里要改过来,否则项目又会报错~。
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
string="郭靖,黄蓉,神雕侠" **方式一:** array=(`echo $string | tr ',' ' '` ) **方式二:** array=(${string//,/ }) **方式三:** array=(`echo $string | sed 's/,//g'`) 遍历数组 for var in ${array[@]} do echo $var done
.cpp程序如下
#include <pcl/io/pcd_io.h> #include <pcl/io/ply_io.h> #include <pcl/point_types.h> // 包含相关头文件 #include <pcl/visualization/pcl_visualizer.h> typedef pcl::PointXYZ PointT; int main() { // 读取点云 pcl::PointCloud<PointT>::Ptr cloud1(new pcl::PointCloud<PointT>); pcl::io::loadPCDFile("read1.pcd", *cloud1); pcl::PointCloud<PointT>::Ptr cloud2(new pcl::PointCloud<PointT>); pcl::io::loadPCDFile("read2.pcd", *cloud2); // 定义对象 pcl::visualization::PCLVisualizer viewer; //设置背景颜色,默认黑色 viewer.setBackgroundColor(100, 100, 100); // rgb // --- 显示点云数据 ---- // "cloud1" 为显示id,默认cloud,显示多个点云时用默认会报警告。 viewer.addPointCloud(cloud1, "cloud1"); pcl::visualization::PointCloudColorHandlerCustom<PointT> red(cloud2, 255, 0, 0); // rgb // 将点云设置颜色,默认白色 viewer.addPointCloud(cloud2, red, "cloud2"); // 将两个点连线 PointT temp1 = cloud1->points[0]; PointT temp2 = cloud1->points[1]; viewer.
学习目标 在并发编程中,阻塞队列在多线程中的场景特别有用,比如在生产和消费者模型中,生产者生产数据到队列,队列满时需要阻塞线程,停止往队列生产。消费者消费队列,对队列为空时阻塞线程停止消费,在Java中有提供不同场景的阻塞队列,那么接下来我们将学习:LinkedBlockingQueue和LinkedBlockingDeque两种阻塞队列。
LinkedBlockingQueue 上次我们学习了基础的有界阻塞队列ArrayBlockingQueue,👉有兴趣可以了解下,明白了有界阻塞队列基本实现原理,而LinkedBlockingQueue与ArrayBlockingQueue比较而言,我们知道ArrayBlockingQueue是通过一个有界的数组对象来存储数据,而LinkedBlockingQueue是用了单链表来实现数据的存储,且相较于ArrayBlockingQueue是用两个锁分别来处理数据的生产和消费。实现类如下:
public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { /** The capacity bound, or Integer.MAX_VALUE if none */ private final int capacity; /** Current number of elements */ private final AtomicInteger count = new AtomicInteger(); /** * Head of linked list. * Invariant: head.item == null */ transient Node<E> head; /** * Tail of linked list. * Invariant: last.next == null */ private transient Node<E> last; /** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.
Mac安装软件时提示已损坏的解决方法
从网上下载的SecureCRT、Principle等设计软件,以及输入法等常用软件,安装时可能会提示“已损坏,移至废纸篓”这类信息,根本无法打开。如下图:
这不是文件的问题,是系统限制的原因。
原因
新系统(macOS Sierra 10.12.X以上)加强了安全机制
默认不允许用户自行下载安装应用程序,只能从Mac App Store里安装应用。
解决方法
▌ 步骤一:打开终端
▌步骤二:输入代码sudo spctl --master-disable
在终端输入以下代码(可复制粘贴)
sudo spctl --master-disable 然后回车,输入自己电脑密码
输完回车即可(密码不会显示出来,如果密码不对会有提示,没有提示就是输入正确了)
▌步骤三:打开系统偏好设置 > 安全性与隐私,若显示任何来源,说明离成功不远了
回到桌面双击安装文件,应该是可以安装了
如果还是无法打开,继续往下看
▌步骤四:(移除这个应用的安全隔离属性)
xattr -r -d com.apple.quarantine path(path换成软件安装路径,一般在/Application下)
现在再回去安装软件,成功!
创建新的 HTML 元素 (节点) - appendChild() 实例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <div id="div1"> <p id="demo">原始节点</p> <button id="add">添加新节点</button> </div> </body> <script> document.getElementById("add").addEventListener('click',add); function add(){ var para = document.createElement('p'); para.className ="p1";//让新增的每个p节点的class名为"p1" var content = document.createTextNode("新的一条节点"); para.appendChild(content); var element = document.getElementById("div1"); element.appendChild(para); } </script> </html> 实例解析:
以下代码是用于创建 <p> 元素:
var para = document.createElement('p'); 为 <p> 元素创建一个新的文本节点:
var content = document.createTextNode("新的一条节点"); 将文本节点添加到 <p> 元素中:
para.appendChild(content); 最后,在一个已存在的元素中添加 p 元素。
1字节(Byte)=8位(Bit)
1KB(KiloByte,千字节)=1024B(Byte)1MB(MegaByte,兆字节)=1024KB1GB(GigaByte,吉字节)=1024MB1TB(TeraByte,太字节)=1024GB1PB(PetaByte,拍字节)=1024TB1EB(ExaByte,艾字节)=1024PB1ZB(ZetaByte,泽字节)=1024EB1YB(YottaByte,尧字节)=1024ZB1BB(BrontoByte,珀字节)=1024YB1NB(NonaByte,诺字节)=1024BB1DB(DoggaByte,刀字节)=1024NB
对torch.multinomial()的理解
Pytorch小抄:multinominal采样函数
127.0.0.1:本地回环地址,代表自己
网关 网关(GateWay):一个网络的出口,一般网关在路由器上
路由器:连接内外网的设备
网关需要IP地址,一般是网段的第一个地址或最后一个地址
一台计算机必须配置IP地址和子网掩码,如需上网还需要配置网关
计算机发包时首先判断目标IP与自己是否在同一网段,如在同一网段,则直接发送,如不同,则直接发送至网关
判断两台电脑是否在同一网段,需要通过子网掩码和IP地址进行与运算,获取网段地址,如相同,表示两台电脑在同一网段
DNS DNS(Domain Name Service):域名服务
找本地解析文件(hosts)–>先找本地DNS缓存->本地DNS服务器–>DNS服务器
本地hosts文件位置 windows[C:\Windows\System32\drivers\etc\hosts]Linux[/etc/hosts] #查看IP地址的详细配置信息 [C:\~]$ ipconfig /all Windows IP 配置 主机名 . . . . . . . . . . . . . : SD-20200427VZZE 主 DNS 后缀 . . . . . . . . . . . : 节点类型 . . . . . . . . . . . . : 混合 IP 路由已启用 .
1、作用
Spring3.0开始,@Configuration用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean注解联合使用
@Configuration注解主要标注在某个类上,相当于xml配置文件中的
@Bean注解主要标注在某个方法上,相当于xml配置文件中的
注意:
@Configuration注解的配置类有如下要求:
@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。
Configuration里面有一个component组件来标识,说明此类也是一个bean,可以被调用,
2、注册bean
1、@Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期
2、@Configuration启动容器+@Component注册Bean
Spring Security简介 Spring Security是一个高度自定义的安全框架。利用Spring IOC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作
spring security 的核心功能主要包括:
认证 (系统认证用户是否登录)授权 (系统判断用户是否有权限去做某些事情)攻击防护 (防止伪造身份) Spring Security项目搭建 一:导入依赖
<!--导入spring security依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.5.2</version> </dependency> 二:访问页面
导入spring-boot-starter-security启动器后,spring security已经生效了,默认拦截全部请求,如果没有登录页面,则回跳转到内置登录页面
默认的username为user password打印在控制台上
UserDetailsService详解 当什么也没有配置的时候,账号和密码是由Spring Security定义生成的。而实际项目中账号和密码都是从数据库中查询出来的,所以我们要通过自定义逻辑控制认证逻辑
如果需要自定义逻辑时,只需要实现UserDetailsService接口即可,如
public interface UserDetailsService { public UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException; } 返回值
返回值UserDetails是一个接口,定义如下:
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();//获取所有权限
String getPassword();//获取密码 String getUsername();//获取用户名 boolean isAccountNonExpired();//账号是否过期 boolean isAccountNonLocked();//账号是否被锁定 boolean isCredentialsNonExpired();//凭证(密码)是否过期 boolean isEnabled(); //是否可用 }
想要返回UserDetails的实例就只能返回接口的实现类。Spring Security中提供了如下实例。对于我们只需要使用里面的User类即可,注意User的权限路径是:
Java中发送Http请求之OkHttpClient 1 OkHttpClient的简介1 OkHttpClient说明2 OkHttpClient使用步骤3 OkHttpClient案例4 OkHttpClient常用工具类: Java中Http请求的方式很多, OkHttpClient因其独特的特性,非常适合在常见的场景中使用.
1 OkHttpClient的简介 1 OkHttpClient说明 OkHttpClient是一个高效的HTTP客户端,其特性包含:
支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接连接池减少请求延时透明的GZIP压缩减少响应数据的大小缓存响应内容,避免一些完全重复的请求 2 OkHttpClient使用步骤 创建OkHttpClient对象创建Request对象将Request 对象封装为Call通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行 3 OkHttpClient案例 @Slf4j public class OkHttpDemo { // 创建OkHttpClient对象, 并设置超时时间 添加拦截器LoginInterceptor private static final OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .addInterceptor(new LoginInterceptor()) .build(); public static void main(String[] args) throws IOException { String url = "http://www.baidu.com"; Request request = new Builder() .url(url) .get() // 不写,默认是GET请求 .build(); Call call = okHttpClient.
在vue中通过element树形控件来实现树形表格的效果
通过缩进来实现近似树形表格的效果
实现效果图 安装依赖 $ npm install element-plus --save
Element官网
自定义树形控件 分析图中控件分布,每个参数都有固定的width,通过width让数值达到对齐的效果
代码主要通过renderContent函数来自定义树形控件
<template> <div class="mytree"> <el-tree :data="tree_data" :props="defaultProps" @node-click="handleNodeClick" indent="0" :render-content="renderContent" ></el-tree> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' export default defineComponent({ components: {}, data() { return { tree_data: [ { // type:1, label: 'notice-id1', children: [ { label: ['卫星名称代号','ZOHREH-2'], }, { label: ['组织机构','IRN'], }, { label: ['频率范围','10950-1450'], }, { label: '[上行]beam名称', children: [ { label:['name','RS49'], }, { label:['freq_min','10950'], }, { label:['freq_max','14500'], }, { label:[]'group('+'3'+')',''] children:[ { label:['10600361','10950','11200','0'] }, { label:['10600361','10950','11200','0'] }, { label:['10600361','10950','11200','0'] } ] } ] }, ], }, ], defaultProps: { children: 'children', label: 'label', }, } }, method:{ // 自定义树形控件函数 node代表每个节点 renderContent(h,{node,data,store}){ // div代表树形控件的一行,div中包含三个span标签 // 判断节点的label数组数量,通过三目运算来选择class // 设置class来控制树形控件进行对齐 return h('div',[ h('span', {class:node.
日常开发时,我们总会遇到需要父子组件双向绑定的问题,但是考虑到组件的可维护性,vue中是不允许子组件改变父组件传的props值的。那么同时,vue中也提供了一种解决方案.sync修饰符。
首先我们知道,父组件通过绑定属性的方式向子组件传值,而在子组件中可以通过$emit向父组件通信,通过这种间接的方式改变父组件的data,从而实现子组件改变props的值。比如向下边这这样:
子组件使用$emit向父组件发送事件:
this.$emit('update:title', newTitle) 父组件监听这个事件并更新一个本地的数据title:
<text-document :title="title" @update:title="val => title = val"></text-document> 为了方便这种写法,vue提供了.sync修饰符,说白了就是一种简写的方式,我们可以将其当作是一种语法糖,比如v-on: click可以简写为@click。而上边父组件的这种写法,换成sync的方式就像下边这样:
<text-document :title.sync="title"></text-document> 有没有发现很清晰,而子组件中我们的写法不变,其实这两种写法是等价的,只是一个语法糖而已。
总结: sync修饰符,与我们平常使用$emit实现父子组件通信没有区别,只不过是写法上方便一些。