十二种抓龙头妖股的实战方法,每一种方法都非常实用,不过想要实战操作就要知道什么是龙头股,所谓的龙头股就是当前涨幅最大的个股,也是引领一个行业的妖股,所以想要提前介入,就得有很多的实战之后才能总结的秘诀。
一、二板定龙头,一板能看出来个毛;
从资金面讲,没有新题材,老热点就会继续,短期交易,不讲价值,不讲技术,只讲故事;
如果一定要谈技术的话,这个技术就是盘口“人气”,一口气上不来就去见马克思;
有故事,有大量资金活跃的股票,就有肉吃,吃完早点撤退,慢的留下买单;
人生难得机会博,热点来全力以赴,热点没了果断卖出,热点就是股市里面的印钞机;
(个人理解:A股就是资金推动的市场,我就是个短线投机者,对于价值、业绩、技术面,哪有那么多时间去研究);
二、有了新题材,坚决抛弃旧题材;
只有新题材,才能凝聚市场中那股最敏锐,最犀利的资金,这股资金以亿为单位,所到之处,只有涨停;
跟上这股资金,想不赚钱都难,对于别的东西不关系、不关注、不关注自然不会买,不买就没有伤害;
有故事,有大量资金活跃的股票,就有肉吃,吃完早点撤退,慢的留下买单;
(个人理解:能凝聚资金的热点都是好题材,能凝聚资金的股票被很多人反复研究过了,我们找到它就行,不需要研究太详细);
三、市场差不怕,成交量少也不怕,就怕题材多;
市场题材过多,势必会造成资金意见不统一,不断切换,第一时间发现市场的精神领袖,采用龙头战法,第一时间上了她,一直持有下去;
当发现新的市场精神领袖的时候,及时切换过去,没有爆量的股票都不能说是龙头,龙头是要爆量接受群众检验的,先预测、够跟随;
四、大龙头都是多点共振的结果;
题材派、龙头派、技术派都认可,筹码供不应求,越走越轻,直到加速,不少纯打板战法,过重看重分时的质量,打的是分时板而不是日线板;
(个人理解:过分看重分时板的质量,上的并不一定都是牛股,封的早会造成换手率不够,少数人吃肉的行情很难走出来牛股,一定要找那种有足够换手率的人气票才是最安全的,有的席位喜欢吃独食,吃独食往往吃相很难看的,不容易聚集人气);
五、模式不同的人,尽量少交流;
模式不同的人,尽量的少去交流,交流多了容易受到影响,想法越少越好,模式越简单越好,按照自己的模式炒作,跟着市场合力,有吃有喝,有何不好;
六、开盘不接力;
技术面看,分时走稳,换手够了再说,市场大格局看,是不是市场当天的核心热点,确定性远比利润多少重要,非热点不看也不去研究,不研究自然不会去买;
(个人理解:买入股票盈利的确定性远比利润空间多少重要,这就是为何小资金要打板才能快速成长的道理,市场不好,打半路板容易追高大面的道理);
七、只做龙头,只做主升,只做惯性;
不做反抽,不做波动,屌丝才喜欢逆袭,没有主升的龙头,就等候,有就重仓出击;坚持龙头战法,必有厚报,这个是执行力,是不是龙头,看经验,看理解能力;
(个人理解:坚持龙头战法,龙头股票回落后不一定都有二波,不去做反抽,更不去做波动,尤其股价回落的时候,做反抽做差价不光是浪费时间还容易亏钱,确定性比利润更重要);
八、跟风票,不看、不做、更不要去研究;
好的习惯才能保证稳定赚钱,相信复利的力量,心猿意马只能亏钱,这是市场的铁律,炒股不难,难的是没坚持自己的模式;
(个人理解:坚持自己的模式,养成好的习惯,东一榔头西一棒槌不可能赚到钱,不管你炒股多少年);
九、交易一定要纯粹;
做加法容易,做减法难;(个人理解:心无杂念,坚持模式内操作,没机会就休息);
十、对龙头要有一颗尊重的心,必有厚报;
忍一步海阔天空,错误的交易,第二天集合竞价割,效果最好,然后忘掉它,马上进入一个全新的交易状态;
(个人理解:错误的买入,不要抱有任何幻想,第二天集合竞价割,手握现金,反思后进入新的交易状态,记住盈亏同源的道理);
十一、选股、必须是新题材龙头;
关于买卖点,要注意节奏,亏钱都是没有坚持自己的模式;
(个人理解:龙头是需要市场检验的,结果出来以后按照自己的模式及时上车,市场差有换手就打板介入,市场好,可以分批,第一批半路板上,上板回封加仓,这个时候市场的确定性非常高);
十二、每个热点,高潮过后的消退期,都会有一个活口,只有活口,才有交易机会,活口是唯一的,找到活口是个技术活,其余的都没有交易机会;
(个人理解:龙头高潮过后,上方大资金要想完全撤退,必须留一个活口来吸引人气,不然很难出货,这就是大资金经常采取的围魏救赵的技术策略);
经典的龙头战法后期再总结,大师的交易习惯印在脑子里面,反复验证,形成一套自己完整的交易体系,坚持下去必有回报。
本人最喜欢的就是MACD指标(做买点)、均线(做趋势)、换手率(跟庄)。只要有理念懂信念就不会在股市里赚不到钱。
尺取法概念:双指针,算法竞赛中一个常用的优化技巧,操作简单、容易编程。
为什么尺取法能用来优化?
一把两种循环转化为一重循环,从而把复杂度从O(n2)提高到O(n)。
两种写法: for、while
for (int i = 0,j = n - l; i < j; i++, j--) //i从头到尾,j从尾到头 {......} int i = 0,j = n - 1; while (i< j) //i和j在中间相遇。这样做还能防止i、j越界//满足题意的操作 { i++; //i从头扫到尾 j--; //j从尾扫到头 } 例题:回文判定。
给定一个长度为n的字符串S,判断是否回文。
#include <bits/stdc++.h> using namespace std; int main(){ string s; cin >> s; //读字符串 bool ans = true; int i = 0, j = s.size() - l; //双指针 //反向扫描 while(i < j) { if(s[i] !
最近因为工作需要,开始捣鼓web框架! 接下来就带大家做一个小项目,方便企业内部数据统计,调查问卷!
一. 操作页
二.数据填写页
三.查询页
首先我们可以找一个自己喜欢的登录页模板,不怕麻烦的话也可以自己写,我套用的是Bootstrap其中的一个登录模板。有需要可以自己去看一下!
Bootstrap模板
模板有了,下面开始创建一个Django项目,有条件的使用的是专业版可以在直接New Project新建一个。
是社区版的就老老实实在命令行执行命令吧,命令如下:
创建一个项目 django-admin startproject Djangopjt 同级目录下创建app python manage.py startapp app 2.1 把创建好的app添加到setting中
2.2 把templates这个包添加 2.3 配置数据库,我这里用的mysql。
项目配置好之后,根据登录需求,在app下的models配置存储需求
3.1 映射数据库(生成数据表)
python manage.py makemigrations python manage.py migrate 数据库有了,下一步写前端,在templates下新建一个login.html
4.1 这里我是套用的模板,就省了很多事。(博主前端太废)
<!DOCTYPE html> <html lang="en"> <head> <title>登录</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> <meta name="
标题 java中static属性详细介绍类的生命周期代码块静态代码块:静态方法静态属性和非静态属性的区别:使用static的注意事项继承关系中静态和非静态的关系普通代码块和构造代码块区别static的共性:static加上访问修饰符-------privatestatic与多态之间的联系static和finall区别及一块用表示什么finalfinal方法final变量(常量)staticstatic变量静态方法static代码块 构造代码块构造代码块的作用: 构造函数java 中静态代码和非静态代码块的区别! 本来仅仅百度查一下静态代码块,众说纷纭,结果一发不可收拾,不知道的东西太多了,把这块内容汇总整理如下,共勉学习。 java中static属性详细介绍 类的生命周期 我们知道类的生命周期为装载、连接、初始化、使用和卸载,
而静态代码块,构造代码块,普通代码块,静态变量等,
在不同的阶段被创建静态的代码块、方法、变量可以说就是类的一部分,在类加载时就已经加载(不一定执行)
代码块 1.普通代码块: 就是类中方法的方法体
public void xxx(){
//code
}
2.构造块: 用{}裹起来的代码片段,构造块在创建对象时会被调用,每次创建对象时都会被调用,并且优先于类构造函数执行。 构造块中定义的变量是局部变量。
{
//code
}
3.静态块: 用static{}裹起来的代码片段,只会被执行一次(第一次加载此类时执行,比如说用Class.forName("")加载类时就会执行static block),静态块优先于构造块执行。
static{
//code
}
4.同步代码块: 使用synchronized(obj){}裹起来的代码块,在多线程环境下,对共享数据进行读写操作是需要互斥进行的,否则会导致数据的不一致性。常见的是synchronized用来修饰方法,其语义是任何线程进入synchronized需要先取得对象锁如果被占用了,则阻塞,实现了互斥访问共享资源。而synchronized也是有代价的。一个常见的场景是,一个冗长的方法中,其实只有一小段代码需要访问共享资源,这时使用同步块,就只将这小段代码裹在synchronized block,既能够实现同步访问,也能够减少同步引入的开销。 同步代码块须写在方法中。
synchronized(obj){
//code
}
用static修饰符修饰的属性和方法叫作静态属性和静态方法 --用于给类初始化是全局变量和全局方法。
声明为static关键词修饰的变量叫做静态成员变量,也叫作全局变量。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
静态代码块的特点: 随着类的加载而执行,而且只执行一次
(静态代码块,静态变量)>>(非静态代码块,非静态变量)>>构造方法
静态代码块的执行顺序: 静态代码块----->非静态代码块-------->构造函数(注意main方法一定是在非静态代码块的前面 ,继承时在父类静态代码块后面,子类静态代码块前面)
执行顺序是先执行父类的静态代码块,然后执行子类的静态代码块;然后执行父类的非静态代码块,再执行父类的构造方法;之后再执行子类的非静态代码块,再执行子类的构造方法。即:静态代码块》非静态代码块》构造方法。
静态代码块、静态方法 两者的区别就是:静态代码块是自动执行的; 静态方法是被调用的时候才执行的.
静态代码块: 静态代码块不能存在于任何方法体中
执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁,它仅能初始化类变量,即static修饰的数据成员。
静态代码块只能写在类中方法外,不能写在方法中,它会随着类的加载而优先于各种代码块和构造方法的加载,并且只会加载一次,如果出现多个静态代码块,会按照书写顺序加载。
static 代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。在静态方法里面只能直接调用同类中其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。因为对于非静态的方法和变量,需要先创建类的实例对象后方可使用,而静态方法在使用前不用创建任何对象。
静态代码块的作用:
一般情况下,有些代码需要在项目启动的时候就执行,这时候就需要静态代码块,比如一个项目启动需要加载配置文件,或初始化内容等。
对于普通方法: 普通方法是需要加载类new出一个实例化对象,通过运行这个对象才能运行代码块,而静态方法随着类加载就运行了。
对于静态方法: 在类加载时静态方法也加载了,但是必须需要类名或者对象名才可以访问,相比于静态代码块,静态方法是被动运行,而静态代码块是主动运行。
非静态代码块:
执行的时候如果有静态初始化块,先执行静态初始化块再执行非静态初始化块,在每个对象生成时都会被执行一次,它可以初始化类的实例变量。非静态初始化块会在构造函数执行时,在构造函数主体代码执行之前被运行。
非静态代码块的执行顺序在构造方法执行之前,类每new一次都会执行。
但是面试中,面试官可能会连着其他知识点一起问,比如说继承,这边我就写个小列子,
注:只有new对象的时候 才会执行该对象的构造方法,非静态代码块
确认种类 RabbitMQ的消息确认有两种。
环境配置 消息发送确认:这种是用来确认生产者将消息发送给交换器,交换器传递给队列的过程中,消息是否成功投递。发送确认分为两步,一是确认是否到达交换器,二是确认是否到达队列。
消费接收确认。这种是确认消费者是否成功消费了队列中的消息。
为了测试,我们先配置rabbit环境
引入Maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
配置文件
spring.application.name=rabbitmq
server.port=8084
spring.rabbitmq.host=192.168.3.253
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
Rabbit配置RabbitConfig.java
package com.lay.rabbitmqtwo.config; /** * @Description: * @Author: lay * @Date: Created in 13:34 2018/12/20 * @Modified By:IntelliJ IDEA */ @Configuration public class RabbitConfig { public static final String CONFIRM_QUEUE_A = "confirm_queue_A"; public static final String CONFIRM_QUEUE_B = "confirm_queue_B"; public static final String CONFIRM_EXCHANGE = "confirm_topic_exchange"; private static final String CONFIRM_QUEUE_A_RoutingKey="
引言 对于某些项目来说,需要发送邮件来完成,例如,发送验证码,发送附件(文档,压缩包之类的),发送链接。本博客利用163邮箱来实现功能需求。
前期准备 修改163邮箱的POP3配置,并备份授权码,方便项目中使用
代码编写 01、pom文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--邮件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> 02、application.properties文件
# 邮箱配置 spring.mail.host=smtp.163.com # 你的163邮箱 spring.mail.username=liuxing121380110@163.com # 注意这里不是邮箱密码,而是SMTP授权密码 spring.mail.password=xxxxx spring.mail.port=25 spring.mail.protocol=smtp spring.mail.default-encoding=UTF-8 03、邮件工具类
package com.information.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.io.File; /** * Description * Author 流星 * Date 2022/1/13 22:06 **/ @Service public class MailUtil { private final Logger logger = LoggerFactory.
首先,我们要知道哔哩哔哩缓存文件的路径是在:
手机存储 → Android → data → tv.danmaku.bili → download → 缓存文件
缓存的文件主要是下面三种:
我们将它复制到电脑上操作,如图:
接下来我们要借用一款FFmpgeg工具,将m4s的文件转换成mp4格式。我们去官网下载,链接:
下载 FFmpeghttp://www.ffmpeg.org/download.html#build-windows我们打开链接跳转到官网,选择Window的图标:
点击后会出现两个供我们选择的FFmpeg文件,我们选择第一个即可。
点击后会弹出一个新的页面,我们往下滑选择最新版本的FFmpeg文件下载。
下载安装完毕,这款软件需要我配置一下它的环境变量。打开我的电脑,右键选择“属性”
弹出系统界面,我们选择“高级系统设置”
选择“环境变量”,第三在弹出的系统界面中我,我们调整“系统变量”中的Path项
选择“新建”按钮,填写我们FFmpeg文件中的bin路径,如图:
填写好之后,我们按“Window + R” 键,输入cmd,在弹出的页面中,输入“ffmpeg –version”,如果出现类似如图的提示,则安装成功。
好了,前期工作我们已经都做完了。接下来,我们就一起将m4s转成mp4视频。
将我们复制过来的缓存文件中的“video.m4s”和“audio.m4s”文件,放到FFmpeg文件中的bin文件夹:
打开命令窗口cmd,先输入“d:” ,进入d盘
然后输入“cd FFmpeg的bin路径”,如我的是“cd sofaware\6.FFmpeg\ffmpeg\bin”
然后输入命令转换视频,输入
“ffmpeg -i video.m4s -i audio.m4s -c:v copy -strict experimental 文件名.mp4”
一起来看看效果吧:
打开文件夹查看,mp4视频就出来了:
这个时候你会很高兴,终于搞定了。然后一打开可能会出现这么个错误:
视频有声音,但是没画面
如果你和我出现了一样的情况,不如打开“格式工厂”,如果你没有这个软件,那么请下载下面这个我为你们准备好的百度网盘链接:
百度网盘 - 格式工厂https://pan.baidu.com/s/1P13ThXrk9aCsmq6yDhaDPQ?pwd=ev4l
下载好安装之后,里面有一个名称为“FormatPlayer.exe”的文件,打开它就可以播放刚刚转换的mp4视频。
播放成功。
但是大家的需求总是千千万万的,不想用这个播放器打开,所以这样的方式不一定适合所有人。我们打开“格式工厂”,转MP4。
将我们的视频放入进来,即可转换成各个播放器都能播放的视频。 大功告成!任一播放器都能播放。
问题起源 作者通过STM32 adc 引脚测量外部模拟电压发现,引脚悬空的时候ADC引脚电压约为0.7V左右,当接到被测模拟电压的时候,ADC引脚的电压会稍微比被测模拟电压高1.6mV 左右,这是什么原因引起的呢?
问题查找 上图是作者测试的原理图,也就是说在使用的时候R102电阻右端比左端高出1.5mV左右,大概0.15uA的漏电流;
针对这个现象我们去找数据手册,是不是一致的;
结论 此次测试现象符合数据手册描述,通过软件校准算法解决这个问题。
周期性处理 Learning Dynamics and Heterogeneity of Spatial-Temporal Graph Data for Traffic Forecasting(ASTGNN)
考虑:全局周期性和局部周期性 全局周期性:是由于人类活动的规律性产生的,例如,通勤者每周一早上8点离家,因此在一周的同一天的同一时间,交通状况往往是相似的。局部周期性:往往是由气候或天气的变化引起的,如大雪连续三天的交通速度与其他天明显不同。
为了在预测future T p T_p Tp时间步的流量时考虑这两种周期模式,除了引入过去 T h T_h Th时间步的历史记录外,还引入了另外两个历史记录。全局周期张量:为了捕获全局的周期性,将过去 w w w周内同一天的流量记录的 T p T_p Tp片也当作输入。即 X g ∈ R N × C × w ∗ T p X_g \in R^{N \times C \times w * T_p} Xg∈RN×C×w∗Tp局部周期性:为了捕获局部周期性,我们考虑过去连续 d d d中 T p T_p Tp个交通记录片,即 X l ∈ R N × C × d ∗ T p X_l \in R^{N \times C \times d*T_p} Xl∈RN×C×d∗Tp
说明:
(1)为什么要介绍wangEditor?:在【SSM开发书评网2:内容简介;功能演示;】 中,我们演示了书评网;其中,就包括后台管理系统;而后台管理系统,最重要的就是图书资料的管理;然后,在图书资料管理时,如何对图书信息进行有效的图文编辑是重点;为此,引入了一个JavaScript组件:富文本编辑器wangEditor;
(2)声明:本篇博客仅仅介绍了wangEditor的最基本使用;不涉及任何与项目业务相关的内容;
目录
一:wangEditor官网简介;
二:wangEditor最基本使用:演示;
1.把wangEditor的js文件,添加进项目;
2.前置说明:创建test.ftl和TestController;
3.在test.ftl中编写wangEditor:包括【wangEditor初始化】,【如何读取内容】,【如何写入内容】;(重点,核心!)
一:wangEditor官网简介; wangEditor组件是国产的,所以阅读起来,没有语言障碍; 二:wangEditor最基本使用:演示; 1.把wangEditor的js文件,添加进项目; 2.前置说明:创建test.ftl和TestController; 我们创建了test.ftl,我们就在test.ftl中编写wangEditor;然后,又创建了TestController;这样以后,当我们启动项目后,通过访问【localhost/test/t1】的时候,就能访问到test.ftl,看到wangEditor的效果了;
3.在test.ftl中编写wangEditor:包括【wangEditor初始化】,【如何读取内容】,【如何写入内容】;(重点,核心!) test.ftl:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 引入wangEditor --> <script src="/resources/wangEditor.min.js"></script> </head> <body> <button id="btnRead">读取内容</button> <button id="btnWrite">写入方法</button> <div id="divEditor" style="width: 800px;height: 600px" ></div> <script> var E = window.wangEditor; var editor = new E("#divEditor");//完成富文本编辑器的初始化 editor.create();//创建富文本编辑器,显示在页面上 document.getElementById("btnRead").onclick = function () { var content = editor.txt.html();//获取编辑器中,现有的HTML内容; alert(content); }; document.getElementById("btnWrite").onclick = function () { var content = "
log4j在项目中应该是使用的最多的日志框架了,一直没有好好去深入总结下,这篇文章记录下一些常规的用法;
1.集成
引入依赖,如下所示:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- 排除自带的logback依赖 --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency> 之后引入log4j的配置文件,log4j的配置有两种格式,一种是property这种方式,还有一种是yml的方式,这里以property配置方式,在resources目录中创建一个log4j.properties:
#定义根节点 log4j.rootLogger=info,error,CONSOLE,info #设置控制台打印 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender #设置为格式化打印 PatternLayout log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n #设置info级别的日志 #log4j.logger.info=info #输出到日志文件 log4j.appender.info=org.apache.log4j.DailyRollingFileAppender log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n #日期文件名格式化 log4j.appender.info.datePattern='.'yyyy-MM-dd log4j.appender.info.Threshold = info #是否追加 log4j.appender.info.append=true #文件存放位置 log4j.appender.info.File=E:/dance/demo/log/info.log #log4j.logger.error=error log4j.appender.error=org.apache.log4j.DailyRollingFileAppender log4j.appender.error.layout=org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.error.datePattern='.'yyyy-MM-dd log4j.appender.error.Threshold = error log4j.appender.error.append=true log4j.
Meta Graph Transformer: A Novel Framework for Spatial–Temporal Traffic Prediction 作者:Xue Ye, Shen Fang, Fang Sun, Chunxia Zhang, Shiming Xiang(中国科学院)下载链接代码链接:Code
2021.12.12 accepted
Abstract 目前traffic state prediction任务中挑战是如何同时利用时空异质性建模交通的复杂动态行为。( 时空异质性: 不同时间和不同空间的交通行为均不相同。)本文提出了一个 M G T ( m e t a − g r a p h t r a n s f o r m e r ) MGT(meta-graph transformer) MGT(meta−graphtransformer)解决了该问题。MGT是transformer的variant。Encoder部分将历史traffic data编码成intermediate representations,解码器采用auto-regressively方式预测future traffic state。MGT主要包含三个blocks,TSA(temporal self-attention),SSA(spatial self-attention),TEDA(temporal encoder-decoder attention)(都是multi-head 结构)。Encoder和Decoder都包含TSA和SSA,来捕获时间和空间相关性。TEDA只在Decoder部分,让decoder部分的每一个position都试图去参与输入序列的所有position。(输入 X 1 , X 2 , .
1、首先设置好基本的布局和页面设置; 2、建立SQLite数据库创建用户的信息表;完成用户的登录和注册功能; 首先创建一个数据库类继承SQLiteOpenHelper package com.example.myapplication.Database; import android.database.sqlite.SQLiteOpenHelper; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.util.Log; /** * ClassName:DatabaseHelper * Package:com.example.myapplication.Database * Description: meet 985&ta *创建一个数据库的类; * @Data:2021/11/08 16:47 * @Author:灿灿睡醒了 */ public class DatabaseHelper extends SQLiteOpenHelper { private static final int VERSION = 3;//数据库版本号 private static String DB_NAME="user";//数据库名称 private static String TAG="DatabaseHelper";//数据库名称 public DatabaseHelper(Context context) { super(context, DB_NAME, null, VERSION); } //当第一次建库的时候,调用该方法 @Override public void onCreate(SQLiteDatabase db) { //创建数据库的时候把用户表创建好 String sql = "
前言 博客主页:干脆面la的主页
gitte链接:干脆面la的gitee仓库
刚学习完递归函数接触汉诺塔问题的时候,汉诺塔问题困扰了我很久。博主花了很长时间理解这道题目,因此整理出了用递归解决汉诺塔问题的思路,希望对大家有所帮助。
如果认为博主的文章对你有所帮助欢迎三连加关注你们的支持是我最大的动力! 目录
前言
1 汉诺塔的由来
2 图解1~3个圆盘的汉诺塔
2.1 1个圆盘的移动
2.2 2个圆盘的移动 2.3 3个圆盘的移动
3 核心思路 4 代码实现
4.1 模拟移动的过程
4.2 Hanoi的递归代码
4.3 完整代码
4.4 运行结果
5 总结
正文开始... 1 汉诺塔的由来 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
2 图解1~3个圆盘的汉诺塔 2.1 1个圆盘的移动 移动1次:A->C
2.2 2个圆盘的移动 移动3次:A->B A->C B->C
2.3 3个圆盘的移动 移动7次:A->C A->B C->B A->C B->A B->C A->C
3 核心思路 对于三个圆盘以上的汉诺塔游戏便开始愈加困难,但是通过递归的思想我们可以将一个极其复杂的步骤简化为一个简单的步骤。
对比这三幅图,我们发现从2个圆盘开始,它们都必须经历的操作就是:(1)使n-1个圆盘整体移动到B柱(中转位置)上,(2)再使第n个圆盘移动到C柱(目的位置)上,(3)再将n-1个圆盘整体移动到C柱(目的位置)上。
上一操作中的第(1)步又可以细分到:将n-2个圆盘通过 (1)使n-2个圆盘整体移动到C柱(中转位置)上,(2)再使第n-1个圆盘移动到B柱(目的位置)上,(3)再将n-2个圆盘整体移动到B柱(目的位置)上。
上一操作中的第(3)步又可以细分到:将n-2个圆盘通过 (1)使n-2个圆盘整体移动到A柱(中转位置)上,(2)再使第n-1个圆盘移动到C柱(目的位置)上,(3)再将n-2个圆盘整体移动到C柱(目的位置)上。
以此类推......
综上所述:本题应该使用递归的方法,让题目化繁从简,使一个极其复杂的步骤简化为简单的步骤。
4 代码实现 4.1 模拟移动的过程 void move(char pos1, char pos2) { printf("
余弦相似度: c o s ( θ ) = ∑ i = 1 n ( x i × y i ) ∑ i = 1 n ( x i ) 2 × ∑ i = 1 n ( y i ) 2 cos(\theta) = {\sum_{i=1}^{n}{(x_i \times y_i)} \over {\sum_{i=1}^{n}{(x_i)^2} \times \sum_{i=1}^{n}{(y_i)^2}}} cos(θ)=∑i=1n(xi)2×∑i=1n(yi)2∑i=1n(xi×yi)
cos(\theta) = {\sum_{i=1}^{n}{(x_i \times y_i)} \over {\sum_{i=1}{n}{(x_i)2} \times \sum_{i=1}{n}{(y_i)2}}}
均方误差: M S E ( y , y ’ ) = ∑ i = 1 n ( y i − y i ’ ) 2 n MSE(y,y^’) = {\sum_{i=1}^{n}{(y_i-y^’_i)^2} \over n} MSE(y,y’)=n∑i=1n(yi−yi’)2
密码学:主要时在数据信息传输、存储过程中保护信息的机密性、完整性、可用性、抗抵赖性等
机密性:数据在未授权的情况下不可访问,保持信息的机密性
完整性:数据在存储或是传输过程中,可以保证数据不被篡改,删除,新增等。可通过加密,数字签名等技术手段来实现数据的完整性
可用性:数据在授权使用时便可以直接获取
抗抵赖性:即由于某种机制的存在,人们不能否认自己发送信息的行为和信息的内容。如传统方法中通过加盖公章或是签字等,互联网时代,可以通过证书、数字签名等方法
明文:用来传递的最原始的信息,大家都可以理解其内容
密文:通过一些手段在明文上作出了改变,增加了理解难度
加密:将明文变成密文的过程
解密:将密文变成明文的过程
密码算法:一般是指明文/密文之间转变的规则,用来加密和解密的某类函数
密钥:密码算法中的一个可改变的参数,一般是一组满足一定条件的随机序列
密码系统(密码体制)由以下几部分组成
消息空间 M(又称明文空间):存放所有可能的明文 m 的集合
密文空间 C:存放所有可能的密文 c 的集合
密钥空间 K :存放所有可能密钥 k 的集合,其中 k 由加密密钥 k,和解密密钥 kd 组成
加密算法 E: 由加密密钥控制的、从 M 到 C 的加密变换
解密算法 D:由解密密钥控制的、从C 到 M的解密变换
加解密算法:存在一个明文m,经过加密算法E,得到密文c,再通过解密算法D可以反向得到明文
若存在密码分析者拦截到密文c,则通过各种分析、算法破译得到了k或是c,则破译成功
工作需要实现一个rtsp的推流拉流业务流程,对开源项目rtspserver进行学习及理解。
参考系列rtspserver的文章:我的开源项目-RtspServer_JT同学的博客-CSDN博客_rtsp server
建立在个人对rtsp推流流程有一定理解的基础上,本文目的是通过开源库rtspserver实现推流,了解一下这个库,运行该库下相关demo,对理论做实践。
1:搭建环境 # git clone git@github.com:ImSjt/RtspServer.git #这里我是直接在github上下载的源码包解压 hlp@ubuntu:~/rtsp$ cd RtspServer-master/ hlp@ubuntu:~/rtsp/RtspServer-master$ ls example Makefile objs pic README.md src test hlp@ubuntu:~/rtsp/RtspServer-master$ make #执行make进行编译 2:运行example 使用make后,在example目录下会生成一些列的测试可执行程序,直接对可执行程序进行运行测试:
这里的测试方案:
1:使用测试代码,使用rtsp进行推流。
2:使用vlc进行拉流播放,音频/视频/alsa采集/摄像头采集依次测试
2.1:example之测试音频aac文件 2.1.1:rtspserver运行example推流aac文件 (作为服务端使用rtsp推流) hlp@ubuntu:~/rtsp/RtspServer-master/example$ ./aac_rtsp_server test.aac Play the media using the URL "rtsp://192.168.0.110:8554/live" 2.1.2:同时,使用vlc进行拉流测试,分别使用默认udp和tcp进行测试 在偏好设置中,分别测试udp和tcp的逻辑。
选择tcp进行测试,如上图,使用抓包工具分析,简单看看协议,先不关注协议流程(rtsp,sdp,rtp,rtcp)协议的含义.大体分析
2.1.3:使用tcp进行测试,如上图选择: 使用wireshark对tcp流程进行抓包:
简单分析和观察,查看报文细节:
1:观察流程:可以发现在tcp的基础上,是rtsp进行交互,其中有看到sdp协商报文,最后通过rtp进行实际流的传输
2:观察每种报文的端口,发现这里所有的流都用的服务器的8554端口
3:这里本应该还有rtcp流,
2.1.4:使用udp进行测试,取消上图得选项,默认就是udp。 简单分析wireshark报文,会发现
1:rtsp报文进行交互控制,sdp进行媒体协商,最后再通过rtsp确定了rtp和rtcp使用方式是udp并且端口是64164~64165
2:会发现实际数据传输用的udp协议(rtp基于udp进行),rtp用得端口64164
3:发现有rtcp报文,用的64165端口
2.1.5:结果: 使用vlc工具进行拉流测试得,点击媒体==》打开网络串流==》
使用这个开源库进行推流和拉流测试时,明显的发现音频播放是卡断的,简单看源码应该于文件得读取发送定时器方案有关。
2.2:example之测试图像h264文件,无音频 2.2.1:服务端启动推流,推送h264视频文件 hlp@ubuntu:~/rtsp/RtspServer-master/example$ ./h264_rtsp_server test.h264 Play the media using the URL "
这里整理用浏览器窗口查询 URL SEARCH,es数据,对比sql方便直观记录
说明:索引库名称 users ,模拟数据在最下方属性:name、age、sex、birthday、position 查询所有,不指定字段
select * from users; http://127.0.0.1:9200/users/_search?pretty 查询所有,指定字段
select name,age from users; http://127.0.0.1:9200/users/_search?_source=name,age&pretty 单条件查询
如果字段非keyword类型,会查询分词,有类似模糊查询的效果注 term精确匹配查询是代表完全匹配,搜索之前不会对你搜索的关键字进行分词,对你的关键字去文档分词库中去匹配内容 select * from users where age=20 http://127.0.0.1:9200/users/_search?q=age:20&pretty 范围查询
select * from users where age>=20 http://127.0.0.1:9200/users/_search?q=age:>=20&pretty http://127.0.0.1:9200/users/_search?q=birthda:>=1997-01-01&pretty select * from users where birthday BETWEEN '1998-01-01' and '1999-01-01' http://127.0.0.1:9200/users/_search?q=birthday:[1998-01-01 TO 1999-01-01]&pretty 排序查询
select * from users order by age desc http://127.0.0.1:9200/users/_search?sort=age:desc&pretty 查询分词内容
http://127.0.0.1:9200/users/_doc/2/_termvectors?fields=name 这里开始不属于简易URL SEARCH 👇
分组查询(聚会查询)
性别分组,并显示个数 select sex,count(*) from users GROUP BY sex GET /users/_search { "
#############字符串函数######### (1) concat()的使用 select concat("name:",ename,'部门:',deptno) from emp where deptno=10; (2) length()的使用 select * from emp where length(ename)=6; (3) lower() upper() 全部设置为大写小写 select lower(ename)from emp where deptno=10; select upper(ename)from emp where deptno=10; (4)replace(str, oldstr, newstr) select ename,job, replace(job,'clerk',"staff") as newjob from emp where job="clerk" (5)substring(str, index, n)) 获得字符串的子字符串 select ename,job, substring(ename,2,3) as newname from emp where job="clerk" ###############数值函数################# 1 abs() ceil() floor() mod() pi() pow() rand() round() truncate() select abs(-3); # 绝对值 select ceil(2.
安装docker 更新镜像源
apt-get update 安装https协议和CA证书
apt-get install -y apt-transport-https ca-certificates 安装docker
apt install docker.io 查看是否安装成功
docker -v //查看版本 出现docker version即安装成功 启动docker
systemctl start docker 安装pip
apt-get install python3-pip 安装docker-compose
pip3 install docker-compose 查看是否安装成功
docker-compose -v //查看版本 出现docker-compose version即安装成功 搭建upload-labs靶场 获取upload-labs镜像
docker search upload-labs 下载镜像
docker pull c0ny1/upload-labs //下载c0ny1/upload-labs镜像 查看镜像
docker images 运行镜像
docker run -it -d -p 8080:80 aa4fdd1dd211 关闭防火墙
systemctl stop firewalld.service 查看镜像是否运行
docker ps 在浏览器输入环回地址和对应端口号即能看到所搭建的靶场
获取元素中的所有监听事件 在Chrome DevTools命令行API提供了多种方式来观察和检查事件监听器。
比如说 getEventListeners方法,可以获取元素上的所有监听器,但是这些方法只能在chrome调试中使用,不能在js中使用。
如果我们想在js中使用,可以修改addEventListener和removeEventListener。
使用call方法复写方法 const addEventListener = document.addEventListener; document.addEventListener = function () { console.log('rewrite addEventListener') addEventListener.call(document, arguments[0], arguments[1]); }; 可以在调用addEventListener的时候将事件记录在对应的元素上。其实就是在给元素添加一个属性用来记录所有的事件,然后暴露一些方法用来访问这些事件。
添加属性 创建一个对象,用来保存事件及方法。
class BaseEvent { constructor(ele) { this.element = ele; this._events = {}; // 复写方法 this.rewriteAddEventListener(); this.rewriteRemoveEventListener(); // 将方法绑定到元素上,即可以通过document.fn进行访问 ele.getAllEventListeners = this.getAllEventListeners.bind(this); ele.getAllEvents = this.getAllEvents.bind(this); } rewriteAddEventListener() { const addEventListener = this.element.addEventListener; const _ = this; this.element.addEventListener = function () { _.addEvent(arguments[0], arguments[1]); addEventListener.call(_.element, arguments[0], arguments[1]); }; } rewriteRemoveEventListener() { const removeEventlistener = this.
文章目录 操作系统期末考试试卷前言试卷 操作系统期末考试试卷 前言 小张的期末复习计划: 前九天,白天看王道,认真整理笔记,晚上复盘(只看视频,不做题,时间允许可以刷王道课后题),只看了王道的前四章,因为时间紧,I/O设备不重要。基础很重要!一定要认真看视频,对后期刷题很有帮助。后期不会做题或者知识点忘记的时候,通过自己整理的笔记,用目录或者文字检索很快就出来了,笔记放在操作系统专栏了,想要文档的,留言就可以。第十天,把老师强调的名词解释总结写在笔记本,每天反复读。十二、十三天,因为学校没有题库所以从网上找了类型题,一份操作系统试卷,一个B站视频 操作系统期末考试不挂科 大题详解 ,一份复习PPT 八个大题 结果就是让小张把题给猜中了,保守是过了。如果来不及系统的复习,一定要过一遍上面的三个链接,题型主要就这几个。下面这份试卷是我们学校的试卷
祝大家科科过!!! 2022.01.13更新
小张安全下车!操作系统84分哈哈哈哈。
试卷 六道简答(30分) 进程通信的方式?
共享存储器系统、管道通信系统、信息传递系统、客户机-服务器系统。
死锁的必要条件?
互斥条件、循环等待条件、不剥夺条件、请求并保持条件。
简述SPOOLING技术?
SPOOLING技术是对脱机输入输出的模拟,它是一种以空间(硬件空间)换时间技术;它有三部分组成:输入井输出井、输入输出缓冲区、输入和输出进程;外部输入内容先保存在输入井,进程直接从输入井获得数据,同样需要输出时,也是先发送到输出井,然后再从输出井输出至外部设备。
什么是文件目录?什么是目录文件?
文件目录:文件目录块的有序集合。一个文件目录也称作目录文件。
上下文切换的过程?
1.将当前处理器的寄存器上下文保存到当前进程的系统级上下文的现场信息中;
2.将新进程系统级上下文中的现场信息作为新的寄存器上下文恢复到处理器的各个寄存器中;
3.将控制转移到新进程执行。
进程调度算法(先进先出,非抢占式短作业优先,抢占式短作业优先,优先级,最高相应比优先的调度顺序并计算周转时间)(链接里的视频好好看一遍就会了)(15分)
试卷一份操作系统试卷中的第三题(类型题),计算磁盘的文件系统。(15分)
1).最大文件长度?
2).给出逻辑地址,画出索引结构图
3).给出逻辑地址计算位置?访问次数?
已知内存访问时间200,快表访问时间0,命中率85%,计算无快表的平均访问时间,计算有快表的平均访问时间(10分)
无快表的平均访问时间=200+200=400 有快表的平均访问时间=0.85 * (0+200)+0.15 * (0+200+200)=230 附公式:
无快表的平均访问时间=内存访问时间(访问慢表)+内存访问时间(访问磁盘)
有快表的平均访问时间=(快表+内存访问时间) * 快表命中率+(快表访问时间+慢表访问时间+内存访问时间) * (1-快表命中率)
为一段管道通信编写指令,汤小丹的书P213页会写右上角的表格(10分)
PPT第二页,磁盘文件的计算(原题)(10分)
pv操作,PPT第七页(类型题,改为三个进程共用一个缓冲区,其实就是吃水果问题,一个盘子)(10分)
# 创建emp 员工表 create table emp( empno int(4) primary key, ename varchar(10), job varchar(9), mgr int(4), hiredate date, sal decimal(7,2), comm decimal(7,2), deptno int(2) ); insert into emp values (7369, 'Smith', 'clerk', 7902, '1980-12-17', 800, null, 20), (7499, 'Allen', 'salesman', 7698, '1981-02-20', 1600, 300, 30), (7521, 'Ward', 'salesman', 7698, '1981-02-22', 1250, 500, 30), (7566, 'Jones', 'manager', 7839, '1981-04-02', 2975, null, 20), (7654, 'Maritn', 'salesman', 7698, '1981-09-28', 1250, 1400, 30), (7698, 'Blake', 'manager', 7839, '1981-05-01', 2850, null, 30), (7782, 'Clark', 'manager', 7839, '1981-06-09', 2450, null, 10), (7788, 'Scott', 'analyst', 7566, '1987-04-19', 3000, null, 20), (7839, 'King', 'president', null, '1981-11-17', 5000, null, 10), (7844, 'Turner', 'salesman', 7698, '1981-09-08', 1500, 0, 30), (7876, 'Adams', 'clerk', 7788, '1987-05-23', 1100, null, 20), (7900, 'James', 'clerk', 7698, '1981-12-03', 950, null, 30), (7902, 'Ford', 'analyst', 7566, '1981-12-03', 3000, null, 20), (7934, 'Miller', 'clerk', 7782, '1982-01-23', 1300, null, 10); ####################简单查询######################## 1 查询所有字段 使用'*'通配符 select * from emp; 2 指定字段 select empno,ename,job,mgr from emp; 3 指定字段并调整字段顺序 select empno,ename,job,mgr,deptno,hiredate from emp;a 4 去除重复查询 distinct select deptno from emp; select distinct deptno from emp; # 去除单字段重复 select distinct deptno,job from emp; # 在多字段中去除deptno job 都重复的数值 5 使用算术运算符 + - * / % 也可使用as 加入别名查询 select empno, job, sal*12 as yealsal from emp; 5 设置数据显示格式查询 concat select concat('姓名:',ename,'部门:',deptno,'职位:',job ,'年薪:',sal*12) from emp; 6 对查询结果排序 默认升序 desc 降序 需在指定字段后边加上order by select deptno,ename,hiredate,sal from emp order by sal; select deptno,ename,hiredate,sal from emp order by sal desc; 7 对指定的多字段排序 须在order by 后面指定多个字段 若排序字段值为null 则将该值作为最小值来处理 select deptno,ename,hiredate,sal,empno from emp order by empno desc,sal asc ################条件查询################### 1 使用比较运算符查询 > < <= >= = !
Connection timed out: connect. If you are behind an HTTP proxy, please configure the proxy settings either in IDE or Gradle.
项目之前是好的,一段时间没用,今天打开就出现上面的问题.网上尝试了各种方法,比如手动帮AS下载对应zip,比如架VPN,一天过去了,并没有解决.
只能在同事帮忙下进行一个大招的放:
repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' // url 'https://maven.google.com/' // name 'Google' } google() jcenter() } allprojects { repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } google() jcenter() } }
【自控笔记】非线性系统&描述函数法
一、非线性系统概述
一般来说,系统的非线性部分在一定条件下可以线性化处理,并可以应用线性理论研究的系统称为非本质非线性系统;若非线性部分线性化后误差较大,无法用线性理论来分析的系统称为本质非线性系统。
二、非线性系统的特点
首先,非线性系统区别于线性系统的最大特点是不满足叠加定理。
其次,非线性系统的响应受初始条件或外作用影响。
第三,由于非线性系统的响应不是唯一的,故不存在系统是否稳定的笼统概念。
第四,非线性系统在外作用为零的情况下,可能会产生一定频率和振幅的周期运动,并且这种周期运动稳定,称为自激振荡。
三、描述函数法
描述函数,即为非线性环节的近似等效频率特性,记为 N ( A ) N(A) N(A)。
应用描述函数法分析非线性系统应具备三个条件:
1、非线性系统可以简化为一个非线性环节 N ( A ) N(A) N(A)和一个线性部分 G ( s ) G(s) G(s)串联的典型结构。如下图所示:
2、非线性环节 N ( A ) N(A) N(A)满足奇对称性,即y(x)=-y(-x),以保证非线性环节的正弦响应不含有直流分量。
3、系统的线性部分 G ( s ) G(s) G(s)具有良好的低通滤波特性。一般来说 G ( s ) G(s) G(s)的阶次越高,低通滤波性能越好。
根据典型结构图知,系统的闭环特征方程为 1 + N ( A ) G ( j ω ) = 0 1+N(A)G(jω)=0 1+N(A)G(jω)=0
即 G ( j ω ) = − 1 N ( A ) G(jω)=-\frac{1}{N(A)} G(jω)=−N(A)1
一、数据集的基本使用介绍 1.数据集的基本介绍 CIFAR-10dataset数据集
在这个数据集中包括了60000张32*32的彩色图片这个图片会有10种类别
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
每个类别有6000张图像其中有50000张图像训练图片然后10000张是测试图片
这个原始的图片对应的是PIL image我们在这边使用要把这个图片转化为tensor的数据类型
可以通过transform的compose函数对图片进行转化可以进行图片的裁剪,resize等等操作
但是因为这个数据集种的图片是32*32的图片比较小所以现在只进行totensor
然后就可以在这个数据集的操作种加入transform的操作
2.数据集调用的基本使用 root数据集所处的位置这个位置是数据集基础设置的位置 train数据集的状态true训练集 false创建的是测试集 transfrom如果相对数据集产生一定的变化就可以吧transform写在这里 target_transform 对于target进行transform download如果设置为true就会自动从网上下载数据集如果为false的话就不会下载例如我们下载一些数据集要通过晚上搜索比较麻烦但是如果吧torchvision提供的download设置为true的话就会比较方便 2.数据集的下载 1.数据集的下载 import torchvision train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transfrom,download=True) test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transfrom,download=True) 这个root一般写的是相对路径比较好寻找 2.数据集下载出现的问题 如果下载比较慢的话就可以吧下载的链接进行复制把它放到迅雷当中迅雷会自动检测到这个下载链接 迅雷下载的话就不一定会从源地址完全下载下俩有的有p2p加速还有的会有镜像加成通过这些可以在一定成度上加快下载速度 首先的话是一个压缩文件然后会对压缩文件进行解压然后解压形成一定的数据集这个数据集比较小只有100多M所以比较推荐大家平时练习的时候的使用 在文件下载好的情况下就不会在进行下载所以建议在使用torchvision的数据集的时候就一般默认设置为true 迅雷下载过程:
如果没有检测到的话可以:
迅雷下载图像: 下载完成后的结果: 这个因为我设置的root的名称为dataset所以是dataset
3.数据集的基本调用 1.数据集内容的基本调用方式 import torchvision train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transfrom,download=True) test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transfrom,download=True) print(test_set[0]) print(test_set.classes) img,target=test_set[0] print(img) print(target) target对应的数据是这个数据集对应的识别出来的图片属性这个target对应的数字为3则这个数据集对应的第一个是类别里面对应的cat print(test_set.classes[target]) img.show()#展示数据集中的图片 print(test_set[0]) 这个数据集可以和数组一样的方式来调用数据集中的具体内容然后也可以通过直接调用属性的方式来显示数据集中的基本属性十种类型['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog','horse', 'ship', 'truck']可以通过单个赋值的方法把数据集单个属性的两个分类分别赋值输出
今天我们来玩儿ADC。
概述 ESP32 芯片有2 个 12位的SAR(逐次逼近)ADC,最多可以读取18个不同的模拟通道输入,由5个专用转换控制器管理,2个支持高性能多通道扫描,2个支持Deep-sleep低功耗模式下运行,还有一个专门用于功率检测和峰值监测。
主要特性如下:
采用 2 个 SAR ADC,可支持同时采样与转换
采用 5 个专用 ADC 控制器,可支持不同应用场景(比如,高性能、低功耗,或功率检测和峰值检测)
支持 18 个模拟输入管脚
1个内部电压 vdd33 通道、 2 个 pa_pkdet 通道(部分控制器支持)
可配置 12 位、 11 位、 10 位、 9 位多种分辨率
支持 DMA(1 个控制器支持)
支持多通道扫描模式(2 个控制器支持)
支持 Deep-sleep 模式运行(1 个控制器支持)
支持 ULP 协处理器控制(2 个控制器支持)
硬件 ADC1支持8个通道(GPIO32-GPIO39),ADC2支持10个通道(GPIO0、GPIO2、GPIO4、GPIO12-GPIO15、GPIO25-GPIO27),这里有两点需要注意:
ADC2的一些引脚比如GPIO0、GPIO2、GPIO15为芯片的Strapping 管脚,使用的时候要特别注意
ADC2只能在WiFi功能未启动的情况下使用
ADC模拟输入引脚可承受最高3.3V的电压,如果需要测试更高的电压,需要通过分压之类的方式进行降压之后再进行采集。
ESP32 ADC 对噪声敏感,从而导致 ADC 读数出现较大差异。为了尽量减少噪声,可以在使用中的 ADC 输入端连接一个 0.1uF 的电容,多重采样也可用于进一步减轻噪声的影响。
软件 关于ADC的一些概念,比如时钟,分辨率,采样周期,衰减,量程等大家自行了解,下面我们讲一下基础的使用:
模拟电压读取
ADC使用不需要初始化引脚了,直接使用下面的函数读取引脚电压,使用默认的参数进行配置,这个参数配置能满足绝大部分的需求了。这里还有一点注意的是这里是阻塞的,直到采集结束。
analogRead(32); 分辨率设置
有参数无返回值的调用
public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); //输入第一个数 int b = sc.nextInt(); //输入第二个数 arr(a,b); } public static void arr(int a,int b){ 含有两个参数的方法 int d=(a+b)/2; System.out.println("平均数:"+d); //求平均数 } 有参数有返回值的调用
public static void main(String[] args) { Scanner sc = new Scanner(System.in); int a = sc.nextInt(); //输入第一个数 int b = sc.nextInt(); //输入第二个数 int max=Max(a, b); System.out.println( a+"和"+b+"比较,更大的是:" + max); } public static int Max(int a,int b) { int max; if(a > b){ max = a; }else{ max = b; } return max ; }
一、三次握手讲解 客户端发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,服务器由SYN=1知道客户端要求建立联机(客户端:我要连接你)服务器收到请求后要确认联机信息,向A发送ack number=(客户端的seq+1),syn=1,ack=1,随机产生seq=7654321的包(服务器:好的,你来连吧)客户端收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,客户端会再发送ack number=(服务器的seq+1),ack=1,服务器收到后确认seq值与ack=1则连接建立成功。(客户端:好的,我来了) 二、为什么http建立连接需要三次握手,不是两次或四次? 答:三次是最少的安全次数,两次不安全,四次浪费资源;
三、TCP关闭连接过程 Client向Server发送FIN包,表示Client主动要关闭连接,然后进入FIN_WAIT_1状态,等待Server返回ACK包。此后Client不能再向Server发送数据,但能读取数据。
Server收到FIN包后向Client发送ACK包,然后进入CLOSE_WAIT状态,此后Server不能再读取数据,但可以继续向Client发送数据。
Client收到Server返回的ACK包后进入FIN_WAIT_2状态,等待Server发送FIN包。
Server完成数据的发送后,将FIN包发送给Client,然后进入LAST_ACK状态,等待Client返回ACK包,此后Server既不能读取数据,也不能发送数据。
Client收到FIN包后向Server发送ACK包,然后进入TIME_WAIT状态,接着等待足够长的时间(2MSL)以确保Server接收到ACK包,最后回到CLOSED状态,释放网络资源。
Server收到Client返回的ACK包后便回到CLOSED状态,释放网络资源。
四、为什么要四次挥手? TCP是全双工信道,何为全双工就是客户端与服务端建立两条通道,通道1:客户端的输出连接服务端的输入;通道2:客户端的输入连接服务端的输出。两个通道可以同时工作:客户端向服务端发送信号的同时服务端也可以向客户端发送信号。所以关闭双通道的时候就是这样:
客户端:我要关闭输入通道了。
服务端:好的,你关闭吧,我这边也关闭这个通道。
服务端:我也要关闭输入通道了。
客户端:好的你关闭吧,我也把这个通道关闭。
原文地址
作者:猪哥66
链接:https://www.imooc.com/article/287873
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作
前置知识:图的相关术语和图的表示
图的遍历 和树数据结构类似,我们可以访问图的所有节点。由两种算法可以对图进行遍历:广度优先搜索(breadth-first search,BFS)和深度优先搜索(depth-first search,DFS)。图遍历可以用来寻找特定的顶点或寻找两个顶点之间的路径,检查路径是否相同,检查图是否有环,等等。
在实现算法之前,让我们来更好的理解一下图遍历的思想。
图遍历算法的思想是必须追踪每个第一次访问的节点,并且追踪有哪些节点还没有完全被探索,对于两种图遍历算法,都需要明确指出第一个被访问的顶点。
完全探索第一个顶点要求我们查看该顶点的每一条边。对于每一条边所连接的没有被访问过的顶点,将其标注为被发现的,并将其加入待访问的定点列表中。
为了保证算法的效率,务必访问每个顶点至多两次。连通图中每条边和顶点都会被访问到。
广度优先搜索算法和深度优先搜索算法基本上是相同的,只有一点不同,那就是待访问顶点列表的数据结构。如下表所示
算法数据结构描述深度优先搜索栈将顶点存入栈,顶点是沿着路径被探索的,存在新的相邻顶点就去访问广度优先搜索队列将顶点存入队列,最先入队列的顶点先被搜索 当要标注已经访问过的顶点时,我们用三种颜色来反映它们的状态。
白色:表示该顶点还没有被访问。灰色:表示该顶点被访问过,但并未被探索过。黑色:表示该顶点被访问过且被完全探索过。 这就是之前提到的务必访问每个顶点最多两次的原因。
为了有助于在广度优先和深度优先算法中标记定点。我们要使用 Colors 变量(作为一个枚举器),声明如下。
const Colors = { WHITE: 0, GREY: 1, BLACK: 2 }; 两个算法还需要访问一个辅助对象来帮助存储顶点是否被访问过。在每个算法的开头,所有的顶点都会被标记为未访问(白色)。我们要用下面的函数来初始化每个顶点的颜色。
const initColor = vertices => { const color = {}; for(let i = 0; i < vertices.length; i++){ color[vertices[i]] = Colors.WHITE; } return color } 广度优先搜索 广度优先搜索算法会从指定的第一个顶点开始遍历图,先访问其所有邻点(相邻顶点),就像一次访问图的一层。换句话说,就是先宽后深的访问顶点,如下图所示
以下是从顶点v开始的广度优先搜索算法所遵循的步骤。
(1) 创建一个队列 Q。
(2) 标注 v 为被发现的(灰色),并将 v 入队列 Q。
(3) 如果 Q 非空,则运行以下步骤:
# 登录数据库 # mysql -h 192.168.239.1 -uroot -p # 查询数据库类型 help data types #############整数类型############# 创建表 student3 create table student3( id int(2), age int(3) unsigned ); # int为无符号类型 unsigned 为有符合类型不能为负值 # int最大值为4294967296 insert into student3 values (12,13); insert into student3 values (-12,13); insert into student3 values (12,-13); insert into student3 (id) values (42949672967); select * from student3; 创建表 student4 设置显示长度 create table student4( id int(4), age int(6) ); insert into student4 values (132,123) select * from student4; #### zerofill 的使用 create table student5( id int(4) zerofill, age int(6) zerofill ); insert into student5 values (132,123) select * from student5; #############浮点数和定点数类型################# 浮点数为近似值,定点数为准确值 浮点数 float 4字节 double 8字节 create table student6( f1 float(5,2), f2 double(5,2), f3 dec(5,2) ); # 注意 总保留共位数要与小数点后精确值位数匹配 insert into student6 values (123.
文章目录 动态映射定制动态映射策略dynamic 字段日期探测(date_detection)数字探测(numeric_detection) 自定义动态模版 动态映射 ES中提供了一种叫做映射的机制,可以自动或手动为index中的文档建立一种数据结构和相关配置。
在自动建立映射的时候,我们可以通过创建映射的模版或更改设置,以达到我们想要的结果。
定制动态映射策略 dynamic 字段 ES中dynamic提供了三个参数:
true:遇到陌生字段进行动态映射。false:新检测到的字段将被忽略。这些字段将不会被索引,因此将无法搜索,但仍将出现在返回的源字段中。意思就是说返回的字段里有,但是搜索的话无法搜索到。strict:遇到陌生字段进行报错。 例如:
PUT /my_index { "mappings": { //true false strict "dynamic": "strict", "properties": { "title": { "type": "text" }, "address": { "type": "object", "dynamic": "true" } } } } 日期探测(date_detection) 在ES中,自动映射会将像yyyy-MM-dd格式映射为date类型,在某些情况下,当我们把目标的text类型映射为date类型,之后会有很大的麻烦。
ES中有一种叫做日期探测的字段,关闭日期探测即可以避免此情况的发生。
PUT /my_index { "mappings": { //false即关闭日期探测 "date_detection": false, "properties": { "title": { "type": "text" }, "address": { "type": "object", "dynamic": "true" } } } } 数字探测(numeric_detection) 虽然JSON支持本机浮点和整数数据类型,但某些应用程序或语言有时可能将数字呈现为字符串。通常正确的解决方案是显式地映射这些字段,可以启用数字检测(默认情况下禁用)来自动完成这些操作。
文章目录 测试环境QEMULinux KernelBuildrootRun参考 测试环境 最新的配最新的, 坑才是最少的, 环境如下:
Ubuntu 20.04 (focal, 5.11.0-41-generic)QEMU: 6.2.0Linux Kernel: 5.10.90Buildroot: 2021.02.8 构建一个能跑起来的5.10内核的Linux x86_64系统, 主要跑通流程
QEMU QEMU, 一个通用的开源机器仿真器和虚拟机(A generic and open source machine emulator and virtualizer). 可以在 x86_64 PC上运行为另一台机器(如ARM/RISC/MIPS等)设计的OS, 还有其他用途这里不表.
官网 Download QEMU - QEMU 下载
或者 Tags · qemu/qemu (github.com) 下载
# Ninja, google的一个程序员推出的一个专注于速度的构建系统, 被用于构建Google Chrome,Android,LLVM的一部分 # 由于用CMake作为后端, 也被许多项目使用, 比如这里的QEMU # 先装Ninja, 可以 sudo apt-get install -y ninja-build 或者源码方式安装 git clone https://github.com/ninja-build/ninja.git cd ninja git checkout release cmake -Bbuild-cmake cmake --build build-cmake sudo cp build-cmake/ninja /usr/bin ninja --version # 1.
项目场景: 当我们的一个新项目导入进来,往往还没有部署,这个时候运行Tomcat就会报错,下面就来跟大家说说怎么解决这个问题(切记,导入新的项目一定要先部署,踩过的巨坑啊,折磨了一个下午!!!)
问题描述: 当你没有先部署项目,而是直接在Tomcat中导入项目,添加虚拟路径时,会出现一系列错误(注意:真的是一系列,有
Artifact javaweb_springmvc:Web exploded: Artifact is being deployed, please wait...
org.apache.tomcat.util.modeler.BaseModelMBean.invoke
还有什么生存时间什么的异常 emmmm...........)
解决方案: 首先,点击File->Project Structure进入之后按照如下图方式,打开到选择你要导入的项目:进入之后他就会提示,让你把这个添加到列表中,我们点击ok即可到这里还没有结束,我们还需要告诉Tomcat我们要运行哪个项目,跟着下图走,在首页导航栏下面找到Tomcat,进入编辑界面 总结:到此为止,就是全部了,按照这个来的话,解决这个问题估计没有问题,但是也不能以偏概全,有什么问题伙计们在下面留言,咱看到就回复【毕竟因为这个恶心了一下午....】
例如:新建一个 Message 对象,并将读取到的数据存入 Message,然后 mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();换成 mHandler.sendMessage()。
目录
一、编写插件步骤
1.1. 通过插件使应用程序可扩展涉及以下步骤:
1.2. 编写一个实现插件的步骤:
二、编写通过插件使应用程序可扩展
三、编写一个实现插件
一、编写插件步骤 1.1. 通过插件使应用程序可扩展涉及以下步骤: 定义一组用于与插件对话的接口(仅具有纯虚函数的类)。使用Q_DECLARE_INTERFACE ()宏向Qt的元对象系统声明该接口。在应用程序中使用QPluginLoader加载插件。使用qobject_cast()测试插件是否实现了给定的接口。 1.2. 编写一个实现插件的步骤: 声明一个插件类,该类继承自QObject和该插件要提供的接口。使用Q_INTERFACES ()宏告诉Qt的元对象系统有关接口的信息。使用Q_PLUGIN_METADATA ()宏导出插件。使用合适的.pro文件构建插件。 二、编写通过插件使应用程序可扩展 1. 新建一个子项目便于程序管理【文件->新建文件或项目->其它项目->子目录项目】
2. 名称随便命名即可,本次演示项目命名为【PluginProject】,然后指定目录
3. 指定构建套件默认即可
4.完成并添加应用程序项目
5.选择【Application->Qt Widgets Application】
6.本次演示应用程序命名为【MainApp】默认mainwindow窗口类
7.创建完成的项目结构如下,然后【MainApp右键->添加新的C++ Header File】命名为abstractinterface
8.定义一组用于与插件对话的接口(仅具有纯虚函数的类),使用Q_DECLARE_INTERFACE()宏向Qt的元对象系统声明该接口
#ifndef ABSTRACTINTERFACE_H #define ABSTRACTINTERFACE_H #include <QtPlugin> class QWidget; class AbstractInterface{ public: virtual ~AbstractInterface(){} //必须定义虚析构函数 virtual QWidget* createWidgetPlugin(QWidget *parent) const = 0; }; #define AbstarctInterface_IID "qt.org.com.abstactinterface/1.0" //iid随便命名当前项目独一无二即可 Q_DECLARE_INTERFACE(AbstractInterface,AbstarctInterface_IID) //声明接口 #endif // ABSTRACTINTERFACE_H 9.在mainwindow中使用QPluginLoader加载插件。使用qobject_cast()测试插件是否实现了给定的接口。
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class AbstractInterface; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; private: void loadPlugin(); //应用程序装载插件 private: AbstractInterface *mainInterface; //插件类 }; #endif // MAINWINDOW_H #include "
项目里的包不可用,手动导入Libraries库
步骤1:打开File里的Project Structure
步骤2:选择对应模块,添加jar包
步骤3:选择本地lib库jar包,OK
成功导入lib
在学习强化学习之前,应该对强化学习有一个大致的了解,即去分析一下强化学习的结构或者组成元素:
什么是强化学习?所谓强化学习,就是在与环境的互动当中,为了达到某一个目标而精心的学习过程,因此称之为Goal-directed learning from interaction with the environment,这其实就是强化学习的第1层结构。可将其称之为强化学习的基本元素,包括:第一Agent,第二Environment,第三Goal。其中Environment是环境,Goal是目标,与环境进行互动的主体称为Agent玩家。
这个Agent的中文翻译很成问题,有人翻译为代理,比较接近于它字面上的意思,有人翻译为主体,也就比较译义。还有得翻译为智能体,就是比较贴切与人工智能了。那么,我实际上不会去翻译这个字,很多时候就直接称为Agent。不过从中文的理解上来说,我们知道Agent这个词,它有特工的含义。这样理解其实比较有意思。另外,我更倾向于玩家,强化学习的过程,在很大程度上就像是一场游戏。
强化学习现在最为领先的应用于领域也就是棋牌、游戏,包括最开始的Atari-雅达利游戏以及强化学习的封神之战围棋,到之后Dota、星际争霸等等。
那么,从学习的角度上来说,我觉得就把强化学习看成一场游戏,更有意思一些,Agent你就理解为玩家,当然这不是很重要了,重要的是理解强化学习的第1层结构,也就是基本元素Agent玩家,Environment环境以及Goal目标。
强化学习是玩家在与环境的互动当中,为了达成一个目标而进行的学习过程。
有了玩家和环境,环境可以说就是这个游戏本身,那么这个游戏的玩法是什么,玩家的目标又是什么呢?这就是强化学习的第2层结构,称之为主要元素,包括第一State状态,第二Action行动,第三Reward奖励。
为什么称之为主要元素呢?因为整个强化学习的过程就是围绕着这三个元素展开的,具体来说,首先,玩家和环境会处于某种状态State,这个状态的含义很广泛,可以说包括了所有的相关信息。
如果说这个游戏是英雄联盟,那么,状态就应该包括敌方和队友的位置、等级、技能、双方的经济,野区的情况以及玩家自己的情况等等等等。如果说这个游戏是一场篮球,那么状态就应该包括所没有球员的位置,速度,球在谁手上,地板滑不滑等等。也就是说,状态是可以很复杂的。
举一个简单的例子-围棋,围棋的状态非常简单,也就是棋盘上361个落子点的状态的整体,对于每一个落子点来说,可以有黑棋、白棋、空三种状态,那么,整个围棋的状态,在理论上只有3的361次方。虽然这是一个巨大的天文数字,但是总的来说,围棋的状态是怎么样的,是很容易去分析的。
那么,继续以围棋为例,在一个状态之下,玩家需要做出某种行动,也就是Action。比如黑棋先手,当前的状态是棋盘上没有落子,黑棋则可以采取361种可能的行动,可以在任何一个位置落子,当黑棋采取了某一行动之后,比如黑棋走了星位,状态将会发生变化。比如白棋同样走星位,那么这就进入了下一个状态,星位再次做出行动。State和Action,状态和行动的往复就构成了强化学习的主体部分。
什么是Reward奖励呢?Reward是指Agent在一个状态之下采取了特定的行动之后,所得到的及时的反馈。在强化学习中,Reward通常是一个实数,并且可能是0。比如在围棋中玩家的目标是赢得棋局,那么只有在达到赢棋的状态时,才会有一个大于0的奖励,我们可以规定赢棋的奖励为1。输棋或者和棋的奖励为0,而在棋局结束之前,任何一次行动实际上得到的奖励都为0,如果是在一场篮球比赛中,当然玩家的目标仍然是赢得比赛,不过获胜的条件变成了得分数大于对手。那么我们可以规定奖励为己方投篮得分数以及对方投篮得分的相反数。
总的来说,奖励应该是由最终的目标所决定的。如果在围棋中对吃掉对方的子进行奖励,那么强化学习的结果就会倾向于吃掉对方的子,而围棋获胜的条件是围地,而不是吃子,一味的吃子可能适得其反,所以根据最终的目标,合理的设置奖励对于强化学习来说是很重要的。
反正强化学习的目的则是最大化总的奖励,也就是整个游戏过程中所获得的奖励之和。奖励是一个即时的反馈,而目标是一个长远的结果。这两者之间的关系是需要理解清楚的,那么以上就是强迫学习的第2层结构,我称之为主要元素,包括第一State状态,第二Action行动,第三Reword奖励。
最后则是强化学习的第3层结构,我称之为核心元素,一共有两个:policy策略以及Value价值。策略很好理解,就是指在某一个状态下应该采取什么样的行动?那么简单的说,在数学上策略,其实就是一个函数,他的自变量,或者说输入是一个状态,而因变量或者说输出则是一个行动,在围棋中将当前棋盘的状态告诉这个策略函数,它则会告诉你下一步应该在哪里落子。很显然,强化学习想要达到的最终效果就是一个好的策略。
所以说Policy策略是强化学习的核心元素之一。那么,什么是Value价值呢?价值同样是一个函数,并且策略函数就取决于价值函数,所以毫无疑问,价值也是强化学习的核心元素。价值函数通常有两种,第一种称为State Value状态价值函数。顾名思义,它的输入是一个状态,而输出则是一个实数,这个实数就称为这个状态的价值。价值的含义很关键,它指的是预期将来会得到的所有奖励之和,也就是说处于当前这一状态的情况下,玩家在将来能够得到的所有奖励的一个期望值。注意玩家的目标就是得到了奖励之和尽可能大,因此,通过状态价值函数,玩家应该选择进入价值尽可能大的状态,而这是通过特定的行动来实现的,这就是状态价值函数决定了玩家的策略,另一种价值函数称为State-Action Value状态行动价值函数。顾名思义,它指的不单单是一个状态所对应的价值,而是在特定状态下采取某种行动所具有的价值,同样,价值指的是在将来能够得到的所有奖励的一个期望值,那么,显然在一个特定的状态下,根据状态行动价值函数,玩家应该选择价值最大的那一个行动,这就是状态行动价值函数决定了玩家的策略。
综上,大家应该理解了,为什么Policy策略和Value价值是强化学习的核心元素。强化学习所要学习的东西,实际上就是一个好的价值函数,而一个好的价值函数决定一个好的策略。当然有一部分算法可以不依赖于价值直接学习策略,不过主流的,或者说,核心的强化学习算法通常都是基于价值的。
本节主要分析了强化学习的结构,首先,什么是强化学习?强化学习是Agent在于环境的互动当中,为了达成一个目标而进行的学习过程,我把这称之为强化学习的第1层结构,也就是基本元素,包括第一Agent玩家、第二environment环境、第三Goal目标。强化学习的第2层结构称之为主要元素,包括第一state状态、第二Action行动、第三Reword奖励。最后则是强化学习的第3层结构,称之为核心元素policy策略和Value价值。
【自控笔记】6.5 离散系统的稳定性分析
一、离散系统稳定的充要条件
线性连续系统的稳定的充要条件是特征方程的根全部位于左半s平面。在离散系统中,根据s平面与z平面之间的映射关系: s = j ω , z = e j ω T s=jω,z=e^{jωT} s=jω,z=ejωT, 可以知道离散系统中的稳定域为以原点为圆心的单位原内。
二、劳斯稳定判据
在离散中,系统的稳定边界是单位圆边缘,而不是虚轴。因此,要使用劳斯判据进行系统稳定性判定,需要引入一种映射 z = w + 1 w − 1 z=\frac{w+1}{w-1} z=w−1w+1,将单位圆内的区域映射到w平面的左半平面,这种变换称为双线性变换。
将特征式 D ( z ) D(z) D(z)变换成 D ( w ) D(w) D(w)就可以使用劳斯判据了。
三、离散系统的稳态误差分析
不同类型系统在不同输入下的稳态误差如下表所示:
其中,
K p = lim z → 1 [ 1 + G ( z ) ] K_p=\underset{z\rightarrow 1}{\lim}\left[ 1+G\left( z \right) \right] Kp=z→1lim[1+G(z)]
text-align:center设置为文本或img标签等一些内联对象(或与之类似的元素)的居中。
margin:0 auto是设置块元素(或与之类似的元素)的居中。
像表格元素的文字居中用text-align:center,表格整体居中用margin:0 auto,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>magin和text-align居中的区别</title> <style> .text { width: 600px; height: 400px; text-align: center;/*文本居中 */ margin: 0 auto;/* 表格居中 */ } </style> </head> <body> <table border="1" class="text"> <caption ><strong>宠物信息表</strong></caption> <thead> <tr> <th>年纪</th> <th>宠物名</th> <th>所属宠物公司</th> <th>公母</th> </tr> </thead> <tbody> <tr> <td rowspan="4">四岁</td> <td>cat</td> <td>CAT</td> <td rowspan="2">公</td> </tr> <tr> <td>dog</td> <td>DOG</td> </tr> <tr> <td>pig</td> <td>PIG</td> <td rowspan="
大家好,我是程序员老王。
年薪百万老码农,待过一线大厂创过业,带过团队,目前专注于一线技术。
分享程序员进阶路上的点滴,帮助大家提升认知,升职加薪。
所有文章首发于我的公众号【程序员云课堂】,喜欢文章的可以微信关注,也可以扫码加我的个人微信交流~ 之前跟大家分享了一位google大佬辞职创业后的“美好生活”,今天聊聊个人创业的那些“一地鸡毛”的事儿。
学会管理
创业给人最大的帮助之一,是让人快速学会管理。管理人和事。
自己当老板,和给别人干活,不止心态要调整,做事方法也要变。
很多事情不会身体力行,而是做好安排,让专业的人在合适的岗位上,物尽其用,人尽其责,才是可持续的。
老哥意识到,一个创始人,不该每天花这么多时间在“回复问题”这件事上...反而忽略了更重要的技术项目。
回复大家的问题只是一个缩影,现实情况是,日常有大量工作相关的事情需要找你讨论或确认,这时候你的时间肯定是不够用的。
如果事无巨细都要插手管理,用不了几天就能把你累垮。
干掉焦虑
自己创业百般好,唯一焦虑的一点就是怎么活下去...
从google离职前,老哥也了解过很多创业公司倒闭的故事。
不过在离职前一刻,老哥都始终认为自己是个例外,自己要创业的项目是与众不同的,前景很好,而且自己也不用很忙碌就能完成很多事情,能焦虑到哪去?
事实证明,焦虑来得很快。自己创业的焦虑感,比在Google遇到的任何工作都让人不安。
而且对于时间更敏感,因为机会不等人,公司因为太大,会有缓冲期,但是个人创业,任何反馈都来的非常快。
老哥觉得主要问题是自己负责了太多项目。他在Google工作时,每天固定的8小时工作很规律。
所以想当然地认为,没了公司的工作,自己应该会有更多的时间才对,而现实却是自己根本忙不过来。
创过业的人都知道,一到自己的事情上,恨不得每天24小时都工作,时间就是金钱。
机会很多,但不是每个项目都有足够的时间和人力同时开展,所以只能选择更重要的项目,核心突破。很少有创业公司在一开始就能把业务做得很广的。
失败与重来
创业初期,确实会经历了不少失败的项目,因为会快速探索和试错。
有的是因为方向错误,有的是发现公司的资源和人力跟不上,有的是执行不到位错过了机会...
不过好在创业公司做事情没那么多层级,处理问题也比较迅速,所以调整也比较快。
但快也同时意味着多变,项目的推翻和重建,甚至员工的批量更换,都是常有的事。
但一般的创业公司等不起。
现代管理学之父彼得·德鲁克曾说过:“管理者,就是把事情做得正确的人;企业家,就是做正确的事情的人。”
所以那些在大厂做高管的,和创业做老板的,看起来都是做管理,但背后的责任和风险是完全不一样的。
今天先分享这些,老王后续会就这个话题再跟大家分享几点~喜欢的可以点个关注,或者加老王微信一起聊聊!
所有文章首发于我的公众号【程序员云课堂】,喜欢文章的可以微信关注,也可以扫码加我的个人微信交流~ 大家好,我是程序员老王。
年薪百万老码农,待过一线大厂创过业,带过团队,目前专注于一线技术。
分享程序员进阶路上的点滴,帮助大家提升认知,升职加薪。
大家好,我是程序员老王。 年薪百万老码农,待过一线大厂创过业,带过团队,目前专注于一线技术。
分享程序员进阶路上的点滴,帮助大家提升认知,升职加薪。
所有文章首发于我的公众号【程序员云课堂】,喜欢文章的可以微信关注,也可以扫码加我的个人微信交流~ 之前分享过一位前google工程师晋升失败选择辞职的故事,后面他去创业了,跟大家分享一个辞职创业的程序员日常都做些啥。
没有工作感觉咋样
刚开始脱离工作的那几天,别提多爽,感受到了极度的自由!
就像被压榨了很久,突然要放一个长假,而且假期会无限延长,会让人非常期待。
与此同时,这位老哥还戒烟了,之前抽烟可能是工作压力太大。
不过辞职后给人最大的感受就是时间可以自由把控了,一天中想干啥干啥,不受其他人影响,而且想做什么,当下就能开始。
尝试更多可能性
既然时间都是自己可控的,那就会更愿意尝试和发现新的机会。
而当你的身份是一名员工时,很多机会对你来说可能并不起眼。
我见过很多辞职创业的技术大佬,做的最多的事情之一就是去演讲或者参会,因为只有露脸多,多去接触其他创业者或者企业高管,才会有更多的机会。
这位老哥也不例外,辞职后做了人生第一次峰会演讲。他把自己写的一篇技术文章改了改就去峰会上开始介绍他的观点了。
第一次演讲结束没几天,他马上又收到了一个很有名的播客的录制邀请,这也是他之前想都没想过的,整个过程也很有趣。
发现没?拥有更多自己的时间,就能更强掌控你的人生发展。
还在工作的程序员,只能尽量多挤时间,拓宽自己的眼界和能力边界。
认识更多新朋友
老哥分享自己从google离职的感想,引起了广大程序员共鸣,评论留言非常多,这种感觉就好像自己一下子变成了名人。
分享的第二天,还是继续回复网友评论;第三天,老哥有点郁闷了,评论的粉丝越来越多,自己可能要花好几周才能回复完现有的评论,而且很多读者都在问自己离开Google后的创业项目。
不过老哥不想透露太多自己在做的东西,于是分享的事告一段落...
看到这里,大家是不是觉得,辞职创业也太爽了!恨不得明天就跟领导爽快提离职?
但这只是辞职后生活的一部分,一地鸡毛的事还没讲呢。真正开始创业,你会发现可能还不如在大厂当个螺丝钉稳定和舒适。
今天先分享这些,下一篇接着跟大家讲讲辞职创业会面临什么问题。老王后续会就这个话题再跟大家分享几点~喜欢的可以点个关注,或者加老王微信一起聊聊!
所有文章首发于我的公众号【程序员云课堂】,喜欢文章的可以微信关注,也可以扫码加我的个人微信交流~ 大家好,我是程序员老王。
年薪百万老码农,待过一线大厂创过业,带过团队,目前专注于一线技术。
分享程序员进阶路上的点滴,帮助大家提升认知,升职加薪。
1、峰值及终值求取 [Y,t] = max(y); 求取峰值及其时间点
C = dcgain(G); 求取系统终值
2、峰值时间 3、超调量 4、上升时间 【第一次到达终值的时间】 5、调节时间 【调节到5% or 2% 以内的时间】
文章目录 前言一、安装nodemon二、使用nodemon 前言 编写调试Node的时候,项目代码做了修改,需要频繁手动停止,在重新启动,非常繁琐
提使用nodemon能够监听项目文件的变动,当代码被修改后,nodemon会自动重启项目,极大方便了开发和调试
一、安装nodemon 在终端中,运行如下命令,即可将nodemon安装为全局可用的工具:
npm install -g nodemon 二、使用nodemon 传统的方式是运行node app.js命令启动项目,需要手动重启
现在将node命令替换为nodemon命令,使用nodemon app.js启动项目,会自动重启
如果遇到以下错误:nodemon : 无法加载文件 C:\Program Files\nodejs\nodemon.ps1,因为在此系统上禁止运行脚本。
win+r 输入powerShell
.输入set-ExecutionPolicy RemoteSigned 选择Y回车即可解决
Linux后台任务运行的方法 最近在远程服务器跑算法模型,远程服务器的工具我用的是MobaXterm,推荐推荐,很好用~
言归正传,跑算法模型要好久,因为服务器性能不是很好,我跑一次要好几天,那就难免远程连接服务器工具会断开,这时候跑了几天的这个模型进程就无了…,也差点把我气的送走~~
最后,自己知道了如何后台运行,恩,真香,自己也就调研学习了一下Linux后台运行任务的方法,在现在跑模型的时候也使用了其中的一种,余下几种自己玩了玩,来记录一下,方便下次看~,学到的方法写在总结里哦!!
1、原理知识剖析(问题引出) 问题:
为什么远程工具断了,进程就没了呢?为什么我们平时用ctrl+c,那进程也就断了呢? 为了来探究这两个问题,我们首先要了解一下Linux的一些信号,我们可以在终端输入以下命令来查看:
kill -l 可以看到总共有64个信号,我们一般称1 ~ 31的信号为不可靠信号,传统UNIX支持的非实时的信号;32 ~ 64为可靠信号,即后来扩充的可靠信号,两者的区别是不可靠信号不支持排队,从而可能会造成信号丢失,而可靠信号则不会。下面介绍几个终端常见到的几个(大家可以试试,看看都是什么效果):
1) SIGHUP:本信号在用户终端连接(正常或非正常)结束时发出 2) SIGINT:程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。 3) SIGQUIT:与SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制 9) SIGKILL:用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果某个进程终止不了,发送这个信号 20) SIGTSTP:停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号 而上面两个问题背后的主要原因会涉及到SIGHUP 、SIGINT信号,下面说明原因:
原因:在我们登录Linux服务器的时候,系统会分配给我们一个终端,也就是一个Session。在我们登录成功之后,我们运行的所有程序,无论是前台进程还是后台进程一般都属于这个Session,那如果我们关闭了终端或者用了ctrl+c,shell默认会发送中断信号给该终端Session关联的进程,从而导致进程终止。
sighup: signal hang up,用户退出Linux登录时或者关闭终端时候,若有对终端输出的进程,其将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此该向终端输出的进程就会中止。不过可以对这个信号进行捕获,比如wget能捕获SIGHUP信号并忽略它,这就是为什么就算退出了Linux登录,wget也能继续下载的原因sigint: signal interrupt,ctrl+c 会发送此信号,主动关闭程序 2、问题处理 在上面我们知道了:
远程工具断了,发送了sighup信号,进程没了Ctrl+c发送 sigint ,那进程也没了 那首先想到的就是,我执行上面的操作,我不让其发送信号不就好了?或者说,你发送信号,我采取机制忽略你?这就对应有两个东西的出现:
2.1 忽略sigint信号(& 符号) 第一种,我们让启动的程序忽略sigint信号,从而让导致进程关闭的sigint信号无效,那就用到了 & 符号
例如:(是不是real简单,哈哈哈哈哈)
tail -f logs.log & 2.2 忽略sigup信号(nohup) 介绍一种命令:nohup ,英文全称 no hang up(不挂起),我们可以用这个命令来使任务不挂断一直在系统后台运行
原理:nohup捕获了SIGHUP信号,对其进行了忽略,从而让发送能让进程关闭sigup信号的操作无效
nohup的命令语法:
nohup Command [ Arg … ] [ & ] Command:要执行的命令。Arg:可选,一些参数,可以指定输出文件。&:可选,让命令在后台执行 在默认情况下(没有指定输出文件的时候)会输出一个名叫 nohup.
GraphPad Prism的数据表格式将决定可以制作何种图表以及可以执行何种分析。选择数据表格式可以让GraphPad Prism创建一张适合于您数据的数据表,并且可以轻松创建您想要的图表类型并执行适当的分析。您总是可以更改数据表的格式。
八种数据表
XY表-XY表是一种其中每个点均由X和Y值定义的图表。此类数据通常适合于线性或非线性回归。
列表-如果您的数据组由某一方案定义(可能是对照与治疗,或者安慰剂与低剂量与高剂量),则请使用条带图。每一列定义一个组。
分组表-“双因素变量”这一概念最好通过示例进行理解。一个分组变量(以下示例中的男性与女性)由行定义;另一分组变量(对照与治疗)则由列定义。
列联表-列联表用于将实际的受试者(或观察)数量制成表格,这些受试者分属于由表格的行和列定义的类别。
生存表-生存表用于输入每名受试者的信息。然后,GraphPad Prism计算每次生存率的百分比,并绘制出Kaplan-Meier生存率图(此外还采用对数秩检验和Gehan-Wilcoxon检验来比较生存率)。
整体部分表格-提出以下问题有意义时,使用整体部分表格:每个数值占总数的比例为多少?该表格经常用于制作饼形图。以下示例显示了获得A、B、C等等级的学生人数。表格(61)中的五个数值总和是学生总人数。
多变量表。多变量表的排列方式与大多数统计程序组织数据的排列方式相同。每行为一个“案例”(实验、动物等)。每列代表一个不同的变量。多变量表格中无子列。
嵌套表。存在两级嵌套或分层复制时,使用嵌套表。在本示例中,对三只大鼠分别进行两次处理,对每只大鼠的结果变量进行四次测量。
简介 ELK由Elasticsearch、Logstash、Kibana三个优秀的开源项目组成,取首字母简写命名为ELK,主要提供对数据的加载、处理、查询等功能。其中:
Elasticsearch:对数据进行搜集、分析、存储。
Logstash:对数据的搜集、分析、过滤。
Kibana:为 Logstash 和 ElasticSearch 提供的数据分析友好的 Web 界面。
一、安装 1、Elasticsearch安装 1.1、到官网下载Elasticsearch安装。下载地址:Download Elasticsearch | Elastic
1.2、上传安装包到服务器。
1.3、解压安装包,如(注意版本区别): tar -zxvf elasticsearch-6.8.6.tar.gz
1.4、添加启动用户
注意:Elasticsearch不能使用root用户进行启动。
groupadd elastic
useradd -g elastic elastic
1.5、为启动用户添加权限
chmod 755 elasticsearch-6.8.6 chown -R elastic:elastic elasticsearch-6.8.6 usermod -g root elastic 编辑 /etc/sudoers文件 ,如:vim /etc/sudoers 添加: elastic ALL=(ALL) ALL 去掉:%wheel ALL=(ALL) ALL 1.6、设置elasticsearch参数
cd elasticsearch-6.8.6/
a)、设置内存:vim config/jvm.options #根据自己机器的配置设置内存大小 -Xms2g -Xmx2g b)、设置内核参数: sysctl -w vm.max_map_count=262144 vim /etc/sysctl.conf 增加以下内容: fs.file-max = 65536 vm.
ForkJoinPool是用于执行ForkJoinTask任务的ExecutorService。 ForkJoinPool不仅提供了来自非ForkJoinTask任务提交的入口,另外还提供相关的管理和监控。
ForkJoinPool与其他类型的ExecutorService的不同之处主要在于,它采用了工作窃取算法:池中的所有线程都会尝试查找并执行池中的任务或由其他活动任务所创建的任务(如果不存在,则需要阻塞等待) 。当大量任务产生其他子任务时(大多数ForkJoinTask就是如此)及外部提交者向池中提交大量小任务时,这可以实现高效处理。特别是在构造函数中将asyncMode设置为true时,ForkJoinPools可能更适用于未汇总的event-style任务。
静态方法commonPool()返回一个通用的ForkJoinPool对象common,它适用于大多数情况。任何未显式提交到指定pool池的ForkJoinTask任务都将使用此方法返回的common 池,使用common池通常会减少资源使用(它在不使用期间缓慢回收线程,并在后续使用时将这些线程恢复)。
对于需要单独或自定义pool池的程序,可以使用构造方法的parallelism参数设定并行度,默认情况下,并行度等于可用的处理器数。ForkJoinPool通过动态添加、挂起、恢复内部的工作线程来维护足够数量的活动(可用)线程,即使某些任务因等待其他任务的join汇总而停滞拖延。但是,面对阻塞的I / O或其他非托管的同步,无法保证此类的自适应调整。内部类接口ForkJoinPool.ManagedBlocker扩展了可容纳的同步类型。
除了执行任务和对生命周期控制的方法之外,此类还提供状态监控方法(例如getStealCount),旨在帮助开发,调整和监视fork / join应用程序。同样,方法toString以一种方便的形式返回池状态的指示,以进行非正式监视。
与其他ExecutorService一样,下表总结了三种主要的任务执行方法。这些方法的主要形式接受ForkJoinTask的实例,但是重载形式还允许执行基于普通的Runnable或Callable任务。
非fork/join端调用(Call from non-fork/join clients)fork/join内部调用(Call from within fork/join computations)安排异步执行(Arrange async execution)ForkJoinPool.execute(ForkJoinTask)ForkJoinTask.fork()等待并获取结果(Arrange async execution)ForkJoinPool.invoke(ForkJoinTask)ForkJoinTask.invoke()安排执行并获取Future(Arrange exec and obtain Future)ForkJoinPool.submit(ForkJoinTask)ForkJoinTask.fork() (ForkJoinTasks are Futures) 字段 FokJoinPool的字段 常量 // Bounds 控制线程池相关边界的常量 // 二进制形式0b00000000_00000000_11111111_11111111 线程池索引掩码 static final int SMASK = 0xffff; // short bits == max index // 二进制形式0b00000000_000000000_1111111_11111111 工作者线程数的最大值 static final int MAX_CAP = 0x7fff; // max #workers - 1 //二进制形式0b00000000_00000000_11111111_11111110 // 用来取workQueues偶数槽下标,(二进制最低位强置为0,当最低位为0时,表示偶数) static final int EVENMASK = 0xfffe; // even short bits //二进制形式0b00000000_00000000_00000000_01111110 最大的槽位值(限制最多只有64们偶数槽位) static final int SQMASK = 0x007e; // max 64 (even) slots // Masks and units for WorkQueue.
序言
今天是2021年12月31日,也是2021年的最后一天,时间过得很快,也很慢,回想年初在江边玩耍的时候定下学习目标,仿佛就是昨天的事,细想来从定下目标的那一天至今我已完成了很多课程的学习,复盘今年,好像我走哪都只有学习的那种感觉给我留下的印象最深刻,我都怀疑如果不是学习,也许我现在根本想不起今年都去到了哪里,干了些什么。今年出了两趟远门,去了趟上海出差,在酒店的桌子上学习链表。去了趟河南的丈母娘家,在书桌上学习动静态库的引用和作用域、链接属性等。年初时周末为了不被家里小孩打扰,在弟弟的新房里学习,那段时间学的是裸机,再后来周末带娃去恒大售房部的游乐元园玩,我在旁边的会客桌学的是uboot移植。再后来,孩子放暑假送回了老家,开始过二人世界,炎热的夏天,二人在卧式开着空调,学习到12点,那段时间学了linux驱动,再后来每个周末都在公司学习,开始过上了全年无休的生活,还是公司呆的时间比较长,学的知识也比较多,多到我没办法把它们都一一列出来。
有理想且为自己的理想奋斗的过程是幸福的,这一年我虽然有过迷茫,有过工作低谷,即使现在的我也没有完全从迷茫和低谷中走出来,但是我心里也有些许的踏实,这种踏实是学习给我带来的。今年部门人员变动很大,该走的不该走的都走了,我再次夯实了老油条这个称号,看着别人的离开我的内心也很动荡,要不是我有自己的计划,我现在也应该已经离职了。
很庆幸我年初为自己制定了学习目标,很感激一路坚持学习的自己,至少学习让我内心动荡的期间,有一个精神支柱,使我内心的桥梁没有崩塌,没有在迷茫的时候愁白头。
学完linux核心课程,紧接着从11月1日踏上了这条注定只有开始没有结束的c++征途,为期2个月的时间把c++学了个七七八八,学习过程中,越学越发现c++的博大精深,以前觉得c语言是门大学问,现在想来比起c++它简直是容易死了,到现在所使用的c还是98版的标准,而c++去年才更新了,而且后续还会有更新,所以不敢说把c++学完了,只是把现有的课程学习完了,也不敢说精通c++,只能说c++略知一二吧。至此c++的学习暂告于段落,接下来要做的就是通过学习qt去应用c++,在应用中去领悟c++。
今日写下这篇总结目的,一是借此将这2个月以来的c++课程进行一个回顾。二是对所学知识进行梳理将零散的知识进行串联,也算是对2021年的一个总结吧。
不忘初心
截止2021年10月31日,完成了嵌入式核心课程的学习,我本应该多做些项目去巩固课程所学,但是我厌倦了工作中的各种开发流程,所以要快刀斩乱麻,快速的学完c++和qt后转向做软件开发,因为软件开发的流程简单很多,我不必花很多的时间来应付那些看似合规实则没有意义的事情。这一遍的学习我并没有准备去和每一个知识点死磕到底,通过之前学习c语言的过程中我发现,技能这个东西需要循序渐进,先有一个知识架构,再在使用中去慢慢研究,必要时还会再回来重复看一看视频教程。好了废话不多说,开始我的主题。
c++概述
c++的由来
c++由c发展而来,早期有一种叫法叫做带类的c,后来随着要解决的问题越来越复杂,c++增加了很多新的语法和特性,导致今天的c++已看不到太多当初c的身影,虽然变复杂了,但是还是完全兼容c的,所以他们还是好兄弟。c++应该这么来看,它并不是一门更好c,而另外的一门语言,c有少量的库,而c++的库多了很多,特别是强大的STL库,c之所以成功,是因为他有指针,c++之所以成功,我想他除了面向对象外,还有很多可以高效率的完成工作有关,c之所以没被淘汰,是因为c的用户多,c的效率比c++更高,所以在linux底层都是使用的c或效率更高的汇编,只是汇编有点费人。到目前为止c在单片机领域仍然处于霸主地位,因为单片机业务相对简单些,所以对语言的要求也简单些,c适合用来做小规模的程序,适用处理性能一般的cpu,而c++则是凌驾于系统之上,有着更高级的语法特性,来解决更复杂业务逻辑。
c++到底是什么
c++是一门半面向对象的语言,之所以说是半,是因为他为了完全兼容c,也多了很多的包袱。c++中的面向对象的语法特性的权重相当于指针在c中的地位,c和c++都是编译型语言,最终的可执行文件的运行,与运行平台有关,c++文件的扩展名典型的是.cpp。记得课程上老师用了一个难度守恒定律来描述c++,就是说语言简单了,那么程序员需要考虑更多,语言难度增加了,那么解决业务问题的编程就变简单了。因为c++难,所以更适合编写大程序,编写一些架构等。
从高处看c++
c++是面向对象语言之一,面向对象并不是c++独有的,很多高级语言都有面向对象,况且c++并非纯面向对象,他有很多非面向对象语言,c++能够经久不衰,是因为他是面向对象语言中效率最高的语言,他的效率高主要归功于他的多态、封装、继承、面向对象的设计模式。使用c也能实现面向对象只是要实现面向对象要程序员做很多额外工作,额在面向对象的语言中,这些额外的工作已经被语言本身实现,程序员的工作就变少了。
非面向对象、面向对象、框架设计、设计模式是一件顺利成章的事。
要学习面向对象应该先学习面向过程。明白实现过程的步骤再去体会面向对象的解决问题的思路这样的学习来得更结实,更透彻。
面向对象是相对面向过程来说的,编程由面向过程转向关注对象,面向对象其实是一种编程的架构组织方式,实际上干活的还是那些代码,干的还是那些活,只是编写思路发生了变化。面向对象是一种分装数据和看待问题的更高层次和视角。面向对象是应对复杂问题更有效的方法,语言由面向过程到面向对象,是一个自然的成长之路。和人的成长之路一样。
面向对象编程的工作主要分我两大块,一个是编写类库,另一个是使用类库来完成具体的业务,这两大块通常由两拨人来分工完成,大部分人通常是应用类库实现业务。
c++该怎么学
c++相较于c来说要无论是关键字还是其内容的抽象度和语法细节都要复杂很多,关系不止2倍,面向对象是其核心,有了面向对象的思维,也就会了c++,模板和泛型是精髓,只是刚入门一般用得很少,只有大神在结构、框架编写中才会遍地使用,老师曾不止一次提到,不要出去吹自己精通c++,这门学问太大,精通容易被打脸。
c++的学习不要试图去记住所有,根本不现实,要以理解为主,通过写代码去吸收语法的特性,形成自己的理解,达到在解决问题时大概知道用声明语法,即使你连关键字都不会拼写,语法细节也记不住了,完全可以通过查阅资料,来编程。写多了自然也就记住了。
c++基本保持在3-5年更新一次,每次更新都是增加一些关键字,其实这些增加,也有很多是借鉴了其它类型的编程语言的一些优秀特性。
c++的学习分为4重境界,
第一层:语法层面,对语法比较熟悉,会使用c++的语法来建模编程。
第二层:能使用c++解决具体业务问题,大部分人停留在这一步。
第三层:编写类库供别人使用,出了问题能快速解决,具有一定的框架思维。
第四层:理解c++设计背后的原因,有自己独立思考的能力,能品出c++的魅力,思考问题的方式和c++的设计者具有一定的同步思想,把c++上升到哲学境界。
c++的应用场景
c++就是用来干业务复杂的开发的,类似于qt、opencv等软件虽然应用编程是使用c++实际上这些软件本身也是使用c++开发而来,c++更适合用来做后台业务逻辑,而前台的开发并不是c++的强项,在当下c++最大的优势就是在视觉领域做AI开发,游戏和图像引擎、网络服务引擎等开发。
c++程序员的发展前景
c++的学习难度大,通过率低,只要是使用c++编程的人无论是做什么方向,待遇都不会差,相较于其他语言,c++的程序员的辉煌周期更长,天花板也更高。c++对内功的要求比较高,很多人根本都入不了门就被淘汰,当然c++的岗位需求也比java、python要少,但整个行业的c++的大神非常稀缺。
总的来说,语言没有好坏之分,只有适合与不适合。c适合资源拮据的平台,如单片机,而c++适合资源中产的平台,如手机、中控屏等,像java、python就适合资源富裕云端,只在乎开发效率,不在乎资源的平台。
c++的语言特性
语言特性来源于实际需求,因为需求变的得越来越复杂,所以语言必须跟着变复杂,每一种语法都是为了解决实际需求,都对程序员有帮助,语法特性越多,某种程度上也可以说明这门语言也更厉害,同时学习难度也更大,本质上语法特性是靠编译工具链的支持,我们使用的各种语法,其实都是在按照规则,调用编译器的各种功能,所以高级语言的背后真正强大的是编译器。语言的本身变迁无非是关键字新增或变更一些语法特性,学习过程中的重点就是掌握这些语法,而真正解决问题还是要靠编程思想。
c的源文件扩展名.c 头文件扩展名.h。c++的源文件扩展名有.cpp、.cxx、.cc、.c、.c++ 头文件扩展名有.hpp、hxx、.h
在c++中完全兼容c,在c++中包含头文件一般没有扩展名,如”#include<iostream>” 当然也支持c中的.h的写法,其实c++为了支持c的.h写法,c++的编译器为了兼容c在背后做了很多工作,这些工作是对高效的一种破坏,所以我们在c++的程序中应尽可能的避免c中的一些特殊语法。
__cplusplus__
cpluspluse前后双下划线,是c++编译器提供的一个环境变量,在程序中我们无需定义可以直接使用,该变量内部记录了c++的版本,而这个变量在c的编译环境下木有,利用这个特点,很多时候我们使用一个宏来判断该变量是否存在,如果不存在就按照c的方法来处理,存在就按c++的方法来处理。
c与c++混合编程
c有很多优秀的代码和库在c++中重写没有必要,丢了也可惜,另外就是一些底层实现时比较注重效率,所以通常会出现在c++中引用c的静态库或者c++的静态库在c源码中引用。c和c++的程序最终都是被编译成.o文件,所以在.o文件将不同类型的源代码链接在一起理论上完全是可行的,然鹅还是有一些细节的东西有区别,如c++支持函数重载,所谓函数重载就是允许函数名相同参数类型不同的函数存在,编译器可以通过对参数对别仍然可识别程序员的意图,编译器底层其实是对重载函数的名称做了更改,添加了一些关于传参类型的标识,来实现函数名重载,然而c不支持函数重载,自然也不会修改名称,所以如果在c涉及调用c++的函数,就无法找到函数,因为编译器已经把函数名进行了修改。导致无法链接成功。解决方法就是让c++安装c的方式来命名。实现方法就是extern “C” { },括号内的元素使用c规则编译,extern是c++中才有的关键字,在c编译器下无法编译,为了通用,我们又添加了#ifdef _cpluspuls,来对extern“c”进行选择编译,__cpluspulus是c++编译器自带的环境变量,用来存储c++的版本,利用对该变量的判断我们即可知道当前编译器是c还是c++。
#ifdef __cplusplus
c++源码引用c静态库混编
这种情况通常出现在供应商给我的文件时.a库,由于编译器编译时会把源文件中的函数名进行修改,所以我们调用的函数名肯定是错误的,处理办法就是加上extern “C”,按照c规则不改变函数名称。
c源码与c++静态库混编
该混编的问题也出在我们不知道c++编译的函数名,解决思路就是我们另外建立一个c++的函数,函数中去引用原来 .hpp中给出的函数,而我们自己写的函数再添加extern”c”来实现名称不改变,编译成另外一个库,其原理就是内部调用名称被改变的函数,对外的封装函数名称没有改变。
反编译
gcc 1xxx -c -o 2xxx.o //将1xxx只编译不链接,命名为2xxx.o
objdump -d 2xxx.o > 3xxx.i //将2xxx.o文件反编译成.i文件。
目录
0、问题
1、缓冲区
2、问题原因
3、scanf特点
4、解决办法
5、正确的代码
0、问题 先从问题代码说起:
#include<stdio.h> int main() { char a; int b; printf("输入小写字母,输出大写,输入其他字符,输出原输入字符\n"); for (b = 0; b < 5;b++) { scanf_s("%c", &a,1); if (97 <= a && a <= 122) { printf("%c", a - 32); } else printf("%c", a); continue; } return 0; } 这段代码看着貌似没啥问题,但是运行起来,应该循环5次,但是只循环3次,问题原因就在scanf这个函数上,原因如下:
1、缓冲区 输入输出都是有缓冲区的,没有将缓冲区里的内容读写完会残留在里面
2、问题原因 对于scanf来说接受%c一个字符后,回车就留在缓冲区里,等下次循环回来,就直接给了scanf一个值,所以貌似看着循环一次,但实际上已经循环了两次,露出了原形:
3、scanf特点 实际上针对%c的输入而言:%c遇到空格、回车、跳格等结束符都是会读取的。
4、解决办法 在scanf后面再加一个getchar()函数,把回车吃掉
在%c前面加个空格 如:scanf(" %c", &a);
5、正确的代码 #include<stdio.h> int main(void) { char a = 0; int b = 0; printf("
目录 ==常见题目类型:====基本原理:==计算RSA算法的安全性 常见题目类型: 基本原理: 素数 模运算 定理
a+b mod n = (a mod n+b mod n) mod n a-b mod n = (a mod n-b mod n) mod n ==a×b mod n = (a mod n×b mod n) mod n==(这个求模的结合律经常用于解密时简化大指数计算) RSA数学原理
欧拉函数: 素数的欧拉函数值为该数本身减1 两个素数的积的欧拉函数结果是这两个数各自的欧拉函数值的积。 解密的证明: 已知:c = me mod n,则me=k*n+c 所以:c=me-k*n 同时:ed=k* Φ(n) +1 则解密过程为: cd =(me-k*n)d mod n =(med-#*k*n+…+ (k*n)d)mod n =mkφ(n)+1mod n =mkφ(n) m mod n =1×m=m 注意理解m,c都是小于n的 计算 举例:p=5,q=3,明文M=2,写出RSA加密过程(公钥:(e,n)、私钥:(d,n))