qwt使用
近期需要做一个调试小工具,用于可视化调试LUT,可以使用Qt的Qwt库,全称是Qt Widgets for Technical Applications,用于生成各种统计图。
安装
官网介绍Qwt User’s Guide
MSVC-2015 64bit的完整安装教程,Installing Qwt with MSVC-2015 64bit compiler on Windows (complete instructions))。我使用的是Qt 5.12.0。源码路径和安装路径最好分离开,便于重新再来。
完整以上安装后,为了方便VS使用还需要做一些简单lib、bin和include的配置。参考QWT6.1.3编译、配置和使用(Vs2010+Qwt6.1.3+Qt5.5.1编译)。
安装后的文件
- 对Qt的安装路径配置环境变量
- 拷贝include目录到Qt的include目录,最好新建个Qwt的子目录
- 拷贝lib\qwt.lib和qwtd.lib到Qt的lib目录下
- 拷贝lib\qwt.dll和qwtd.dll到Qt的bin目录下
- 拷贝plugins\designer\qwt_designer_plugin.dll到plugins\designer目录下,用于qt designer。
- 配置VS(有些不是必须的,但最好配置上)
- 配置头文件:
$(QTDIR)\include\Qwt
- 配置可执行文件:
qwtd.lib
(如果是Release版本用qwt.lib
) - 配置预处理器:QWT_DLL
- 配置头文件:
- 跑提供的测试代码Installing Qwt with MSVC-2015 64bit compiler on Windows (complete instructions))
基本效果如下
MSVC-2017应该也有类似的教程。
qwt demo
网络上的资源参差不齐,最好还是从官方提供的example入手,之前就是因为没有完整编译好工程导致有些demo没看到,苦苦看源码搜资料查了好久。
- animation
- barchart:柱状图、导出按钮combox
- bode:picker数据拾取器
- controls:多个tab
- cpuplot:legend选择可隐藏
- curvdemo1
- dials:多个tab
- distrowatch
- event_filter:曲线上鼠标拖动点
- friedberg
- itemeditor:editor
- legends:layout设计、多个按钮控制显示
- oscilloscope
- radio
- rasterview:放大缩小
- realtime:组合控制
- refreshtest
- scatterplot:平移放大缩小
- simpleplot:简单曲线显示
- sinusplot:always picker
- spectrogram
- stockchart:checkbox
- sysinfo
- tvplot
这里列几个典型的
使用过程中一些小细节
- 按钮出现中文乱码
// 源码文件的字符集不是UTF8 ? |
- pushbutton的简单使用
- Qt QPushButton
Qt的MVC设计模式
网络上关于Qt的介绍还是相对不多的,这里记录下Qt相关的东西,便于回溯。
架构、框架和设计模式
ref:
架构、框架和设计模式
软件架构
软件架构是系统的一个草图,阐述了各个组件之间的通信,层次划分,一旦系统开始详细设计,架构蓝图就很难甚至无法改变。
例如:三层架构:一种设计软件架构的思想。
通常意义上的三层架构就是将整个业务应用划分为表示层(User Interface Layer)、业务逻辑层(Buesiness Logic Layer)、数据访问层(Data Access Layer)。区分层次的目的是为了体现“高内聚,低耦合”的思想。
- 表示层
表示层位于最外层(最上层),最接近于用户。用于显示数据和接收用户输入的数据为用户提供一种交互式的操作界面。 - 业务逻辑层
业务逻辑层无疑是系统架构中体现核心价值的部分。他的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求相关的系统设计上,也就是说,他与系统所对应的领域(Domain)逻辑有关,很多时候,也将业务逻辑层称为领域层。
业务逻辑层在体系架构中的位置很关键,他处于数据访问层与表示层中间起到了数据交换中承上启下的作用。对于数据访问层而言,他是调用者;对于表示层而言,他却是被调用者。 - 数据访问层
数据访问层有时候也称为持久层,其功能主要是负责数据库的访问,可以访问数据库系统、二进制文件、文本文档、或是XML文档。简单的说法就是实现对数据表的Select、Insert、Update和Delete操作。
框架
软件框架是(Framework)是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架的作用在于:由于提取了特定领域软件的共性部分,因此在此领域内新项目开发过程中代码不需要从头编写,只需要编写在框架的基础上进行一些开发和调整便可满足要求:对于开发过程而言,这样做会提高软件的质量减低成本,缩短开发时间,是的开发越做越轻松,效益越做越好,形成一种良性循环。
框架不是现成可用的应用系统,他是一个半成品,需要后来的开发人员进行二次开发,实现具体功能的应用系统。框架也不是平台,平台的概念比较模糊,他可以是一种操作系统、一种应用服务器、一种数据库软件或一种通信软件等,因此平台在应用方面主要指提供特定服务的系统软件;而框架更侧重于设计和开发过程,或者可以说,框架通过调用平台提供的服务而起作用。
框架也不是工具包或者类库。望文生义,类库就是一些类的集合,只要我们将一些可以复用的类集中放到一个Library中,就可以称其为一个类库。类库中的许多元素(如:类、结构、接口、枚举等)之间可能有一些关联,但这些关联通常用于支持一个类概念或接口概念的完整表达。如果从一个更高的视角来审视类库,可以发现类库中的一个个“完整的概念”之间是无关的或是关系松散的,框架和类库有着相似的形式,即框架往往也是类的集合;但不同之处在于,框架中的各个类并不是孤立的,框架中的业务逻辑代码是将不同的类连在一起在他们之间建立协作关系,例如:Spring-一个开源的Web设计规范。
设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是对某种环境下反复出现的问题以及解决该问题的方案描述,比框架更加抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。
比较
- 框架与设计模式
框架通常是代码重用,而设计模式是设计重用,架构介于两者之间,部分代码重用部分设计重用。
设计模式研究的是针对单一问题的设计思路和解决方法,一个模式可以应用于不同的框架和被不同的语言所实现;而框架则是一个应用的体系结构,是一种或多种设计模式和代码的混合体,虽然他们有所不同,但却共同致力于使人们的设计可以被重用,在思想上存在着统一性的特点,因而设计模式的思想可以在框架设计中进行应用。 - 框架与架构
框架不是架构,框架比架构更具体,更偏重于技术,而架构偏重于设计。一个架构可以通过多种框架来实现. - 架构与设计模式
设计模式主要是针对单一问题的解决方法,范畴比较小,而架构是高层次的针对体系结构的一种设计思路,范畴比较大。可以说一个架构中可能会出现多个设计模式类解决架构中的多种问题。
通过上面的分析,可以看出这三者之间得区别还有很多,首先架构是一个范畴最大的概念,是最高层次的设计,一个架构设计中可能会用到多个框架和多个设计模式;而框架是针对共性抽象出来的半成品,这里面可能包含着多个设计模式;而设计模式就是解决单一问题的设计思路和解决方法。
要做好一个项目,架构设计、框架设计和使用、设计模式都是非常重要的。我们在做一个项目的时候首先设计出来的应该是架构,是对整个问题的一个总体上的设计,之后再会考虑运用什么样的框架和设计模式来实现我们的框架;当然,只使用框架和设计模式中的一种也是经常遇到的。
这三者的共同点都是为解决现实生活中的问题而出现的,都为了使我们的设计更面向对象化。
MVC
MVC设计模式起源于SmallTalk的一种与用户界面相关的设计模式,可以有效分离数据和用户界面。
MVC设计模式包含三个元素:
表示数据的模型(Model),表示用户界面的识图(View),定义了用户在界面上的操作控制(Control)。这和典型的三层架构不同。MVC是设计模式,属于微观的解决方案;三层架构是系统架构,属于宏观的解决方案。
Qt的MVC——InterView框架(MVD)
与MVC设计模式类似,Qt引入了模型/视图结构用于完成数据与界面的分离,即InterView框架。但不同的是,Qt的InterView框架中把视图和控制部件结合在一起,使得框架更为简洁。
为了灵活地处理用户输入,InterView框架引入了代理(Delegate)。通过使用代理,能够自定义数据条目(item)的显示和编辑方式。
Qt的模型/视图结构分为了三种部分:
- 模型(Model)
- 视图(View)
- 代理(Delegate)
如下图,模型与数据通信,并为了其它部件提供接口;
而视图从模型中获得用来引用数据条目的模型索引(Model Index);
在视图中,代理负责绘制数据条目,当编辑条目时,代理和模型直接进行通信。
模型/视图/代理之间通过信号和槽进行通信。
它们之间的关系如下:
数据发生改变时,模型发出信号通知视图;
用户对界面进行操作,视图发生信号;
代理发出信号告知模型和视图编辑器目前的状态。
基本概念
- 模型(Model)
抽象基类QAbstractItemModel
列表的抽象基类QAbstractListModel、表格的抽象基类QAbstractTableModel、QAbstractProxyModel
QProxyModel
QDirModel
QFileSystemModel
QHelpContentModel
QStandardItemModel类继承 - 视图(View)
抽象基类QAbstractItemView
QListView—QListWidget\QUndoView
QTableView—QTableWidget
QTreeView—QTreeWidget
QColumnView
QHeaderView
实际上:QListWidget、QTableWidget、QTreeWidget已经包含数据,是模型与视图集成的。 - 代理(Delegate)
抽象基类QAbstractItemDelegate
QItemDelegate
QStyleItemDelegate
类QItemDelegate由类QSqlRelationDelegate继承
快捷键
仅仅记录实际使用到的或者高频使用的,可能的不记录。
VSCode
快捷键 | 作用 |
---|---|
Alt + Click | 插入多个光标 |
Alt + Shift + Click | 列选(等价中键) |
Ctrl + Alt + Down/Up | 键盘列选 |
Alt + Shift + F | 格式化 |
Ctrl + [ / ] | 缩进 |
Ctrl + 左键文件名 | vsplit一个新的编辑器 |
Ctrl + \ | vsplit一个新的编辑器 |
Alt + Up/Down | 上下移动一行 |
Alt + Shift + Up/Down | 上下复制一行 |
Ctrl + U | 删除光标左侧 |
Alt + Shift + Right | 会选中匹配括号中的内容,并可以扩大选中区域 |
Ctrl + Shift + ` | 新建终端 |
bash
快捷键 | 作用 |
---|---|
Ctrl + U | 删除光标到行首的所有字符,在某些设置下,删除全行 |
Crl + Delete | 删除光标右侧 |
Ctrl + W | 删除当前光标到前边的最近一个空格之间的字符 |
Ctrl + A | 相当于Home |
snipaste
最好进行修改
快捷键 | 作用 |
---|---|
Alt + F1 | snip |
Alt + F2 | paste |
Qt Creator
- Qt高级——QtCreator常用快捷键
- Qt Creator使用技巧 应该是翻译自官网的文档[]
快捷键 | 作用 |
---|---|
Ctrl + R | 运行 |
F4 | QtDesigner进入信号槽的设置, 源文件和头文件之间切换 |
F2 | 转到定义 |
Ctrl + I | 格式化代码(需先全选) |
Ctrl + Space | 代码补全 |
Shift + F2 | 声明和定义之间的跳转 |
Ctrl + B | 编译工程 |
Alt + Enter | 将光标移动到h文件中方法声明,添加方法实体 |
Ctrl+/ | 注释行,取消注释行 |
Alt + ← | 后退 |
Alt + → | 前进 |
Ctrl+Shift+R | Refactor\Rename Symbol Under Cursor |
F1 | 查看帮助 |
VS
| 快捷键 | 作用 |
| —————— | ————————————————————- |
| Ctrl + k, Ctrl + O| 切换头文件和源文件|
Linux使用小记
近期需要回顾一些基础知识,需要相对系统地学习一下。
ref
- Linux工具快速教程 主要参考的文档
帮助
- 在只记得部分命令关键字的场合,我们可通过
man -k
来搜索; - 需要知道某个命令的简要说明,可以使用
whatis
;用`whatis -w “loca*”实现正则匹配; - 而更详细的介绍,则可用
info
命令; - 查看命令在哪个位置,我们需要使用
which
;当系统中安装了同一软件的多个版本时,不确定使用的是哪个版本时,这个命令就能派上用场; - 而对于命令的具体参数及使用方法,我们需要用到强大的
man
;
在man的帮助手册中,将帮助文档分为了9个类别,对于有的关键字可能存在多个类别中, 我们就需要指定特定的类别来查看;(一般我们查询bash命令,归类在1类中);
- 用户可以操作的命令或者是可执行文件
- 系统核心可调用的函数与工具等
- 一些常用的函数与数据库
- 设备文件的说明
- 设置文件或者某些文件的格式
- 游戏
- 惯例与协议等。例如Linux标准文件系统、网络协议、ASCⅡ,码等说明内容
- 系统管理员可用的管理条令
- 与内核有关的文件
我们看到printf在分类1和分类3中都有;分类1中的页面是命令操作及可执行文件的帮助;而3是常用函数库说明;如果我们想看的是C语言中printf的用法,可以指定查看分类3的帮助:
man 3 printf |
文件及目录
# 查看当前目录下文件个数 |
find是实时查找,如果需要更快的查询,可试试locate;locate会为文件系统建立索引数据库,如果有文件更新,需要定期执行更新命令来更新索引库
cat vi head tail more
# 显示时同时显示行号 |
批处理命令连接执行,使用 |
串联: 使用分号 ;
前面成功,则执行后面一条,否则,不执行:&&
前面失败,则后一条执行: ||
ls /proc && echo suss! || echo failed. |
查看文件夹大小
# -h:以人类可读的方式显示 |
环境变量
Linux中环境变量包括系统级和用户级,系统级的环境变量是每个登录到系统的用户都要读取的系统变量,而用户级的环境变量则是该用户使用系统时加载的环境变量。所以管理环境变量的文件也分为系统级和用户级的。
- 系统级
/etc/environment
: 是系统在登录时读取的第一个文件,用于为所有进程设置环境变量。/etc/profile
:是系统登录时执行的第二个文件,可以用于设定针对全系统所有用户的环境变量。该文件一般是调用/etc/bash.bashrc
文件。/etc/bash.bashrc
:系统级的bashrc
文件,为每一个运行bash shell的用户执行此文件。此文件会在用户每次打开shell时执行一次。
- 用户级
~/.profile
: 是对应当前登录用户的profile文件,用于定制当前用户的个人工作环境。 每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件。~/.bashrc
: 是对应当前登录用户的bash初始化文件,当用户每次打开shell时,系统都会执行此文件一次。平时设置这个文件就可以了。
那么根据以上描述,这几个文件的执行先后顺序应当是:/etc/enviroment –>/etc/profile –>~/.profile –>/etc/bash.bashrc–> ~/.bashrc
配置环境变量
临时生效
直接运行export命令定义变量【只对当前shell(BASH)有效(临时的)】export PATH=/usr/local/webserver/php/bin:$PATH
对当前用户有效
编辑~/.bashrc
并添加export PATH=$PATH:/usr/local/webserver/php/bin
;用source ~/.bashrc
让修改马上生效- 对所有用户生效
在/etc/profile
文件中添加变量,并执行source /etc/profile
文件与目录权限修改
chown # 改变文件的拥有者 |
chmod
的语法为
chmod [who] [+ | - | =] [mode] 文件名 |
- u 表示“用户(user)”,即文件或目录的所有者。
- g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。
- o 表示“其他(others)用户”。
- a 表示“所有(all)用户”。它是系统默认值。
# 在一个命令行中可给出多个权限方式,其间用逗号隔开 |
文本处理
find 文件查找
# 查找txt和pdf文件: |
grep 文本搜索
常用参数
- -o 只输出匹配的文本行 VS -v 只输出没有匹配的文本行
- -c 统计文件中包含文本的次数
grep -c “text” filename
- -n 打印匹配的行号
- -i 搜索时忽略大小写
- -l 只打印文件名
# 在多级目录中对文本递归搜索(程序员搜代码的最爱): |
关机
# 立刻关机 |
A Tutorial Introduction to the Lambda Calculus
参考文献
- 我的最爱Lambda演算——开篇
- A Tutorial Introduction to the Lambda Calculus 很不错的一篇入门参考
- The Lambda Calculus for Absolute Dummies (like myself) 基本是上一篇文章的理解和翻译,不过加入了很多理解,从我看过第一篇文章后,再看这篇会很容易接受
- 认知科学家写给小白的Lambda演算 这是上一篇文章的中文翻译
- Programming languages and lambda calculi 参考书
- Lambda calculus引论(三): 不可判定 这是更为简洁的笔记介绍
- 神奇的λ演算 另一个不错的入门介绍
这里以第二篇开始lambda演算的学习
λ演算是一种形式系统(formal system),什么是形式系统呢?大家都知道,数学语言是可以脱离现实而存在的——大家把数学想成了一种符号游戏,脱离生活常识,从公理开始,进行大量的推导和证明——最终产生了一个系统,在这个系统中有公理、定理、推论、猜想……这种自成系统,有公理又承认推理证明方法的体系,成为形式系统。而用于描述形式系统的语言就是形式语言(formal language)
图灵完备
首先先理解一下什么是图灵完备,参考知乎的答案# 什么是图灵完备?
什么是图灵机
图灵机是图灵在1936年发表的paper中提出的数学模型,是一个架空概念,他在文中描述了什么是图灵机,并且证明,只要图灵机可以被实现,就可以用来解决任何可计算问题。
图灵机的结构包括:
- 一个无限长的纸带
- 一个字符表
- 一个读写头
- 一个状态寄存器
- 一个有限的指令集
图灵机可以解决什么问题
图灵证明,假设上述模型所说的功能都可以被某种形式物理实现,那么任何可计算问题都可以被解决。
所谓可计算问题,涉及到计算理论(即泛指一切与计算相关的问题),可以理解为,是否存在一个算法,能解决在任何输入下的此计算问题,比如著名的停机问题,就是一个不可计算的计算问题。
简单所,图灵证明了对于一个问题,对于任何输入,只要人类可以保证算出结果,那么图灵机就可以保证计算结果。
什么是图灵完备性
图灵完备性,是针对一套数据操作规则而言的概念,数据操作规则可以是一门编程语言,也可以是计算机里的实现的指令集。当这套规则可以实现图灵机模型里的全部功能时,就称为具备图灵完备性。
直观理解图灵完备——Brainfuck语言
1993年,有人发明了Brainfuck语言,只有8个有效字符,每个字符都是一个指令,但这却是一门图形完备的编程语言。
BF的工作机制与图灵机基本一致,他存储数据的方式是一个无限长的一位整数数组,里面的数值全部初始化为0,还有一个数据指针,每个时刻都指向数组的某一元素,指针可以左右移动,也可以读取、修改数组当前元素的值。
BF中8个有效字符分别是:- >
指针向右移动一格
- <
指针向左移动一格
- +
使指针当前格数值加一
- -
使指针当前格数值减一
- .
把当前格数值按 ASCII 表输出到终端
- ,
从终端接受一 byte 的数据,存储其 ASCII 数值到当前格
- [
当指针当前值为 0 时,程序跳转至与之对应的 ] 之后;否则程序正常执行
- ]
程序跳转回与之对应的 [ 处
+++++ |
对于上述代码段,通过完成5X13输出了字符A
,
这里讲一下我的理解,+
进行五次,因此当前指针初始化的格子cell 0的值被递增了5次[
指令读取到当前值各自值为5(因此将[]中的部分执行了5次,[]中的程序会递减该值,直到0),来看[]中的行为>
右移指针,随后将当前指针的各自cell 1递增了13次,再左移一个到cell 0,将cell 0的值递减一次
随后>.
右移指针并将当前值格子cell 1的值打印出来,得到A
图灵停机问题
不存在有这样一个程序,能够计算任何程序在给定的输入上是否会结束(停机)。
用反证法,假设有这样一个程序,叫做GodAlg,给定一个程序,并且给定这个程序的输入,就能够判定这个程序在这个输入上是否会停机。
bool GodAlg(char *program, char *input) { |
我们假设一个新的程序
bool SatanAlg(char *program) { |
当这个算法调用自身时,SatanAlg(SatanAlg)会产生的结果如何?
从代码片段来看,这个程序要么能够结束运行停机,要不不能返回。
- 假设能够停机,则if判断成立,程序进入循环,于是这个调用永远不会返回,说明SatanAlg(SatanAlg)不能停机。
- 假设不能够停机,则返回true,说明SatanAlg(SatanAlg)能停机。
这说明假设不成立,不存在这样的一个程序GodAlg
λ演算
定义
λ演算被称为最小通用编程语言,1930年由Church引入,用于公式化有效计算中的一些问题,它也是图灵完备的,但更强调变换规则的使用,而不是具体的实现,并且其约束的规则非常简单,易于演算。
λ演算中只有三种表达式,分别如下。在λ演算中,只有λ和.是关键字。
- <expression> := <name> | <function> | <application> |
注意表达式可以是name,function和application,对于,在λ演算中,只有λ和.是关键字!
记住最后一个表达式,两个expression表示application。对于表达式,默认是从左到右进行分析或者应用应用的。
最简单的恒等函数为
函数可以应用于表达式,例如下式表示将函数应用到$y$上
关于function application可以通过替换规则替换body中的argument实现求值,例如
这里$[y/x]$表示将所有的$x$替换为$y$
λ演算中有α transform和β reduction,在λ演算中,变量是没有任何含义的,不代表任何东西,只是用先相同的名字表示两个相同的东西。而函数也什么都不计算,就是一个表达式,唯一能做的就是β规约(β reduction),直到没有任何东西可以再替换为为止。
- α transform
对于λ演算中的任何表达式,可以修改函数参数的名称,只要同时修改函数体的内所有的引用。(替换有约束变量的名字) - β reduction
指的是,对于一个application,可以将函数体中和对应函数标识符相关的部分做替换来实现application,方法就是使用标识符作为参数值替换,也就是下面的substituions部分。(将实参应用到函数体中)
约束变量(bound variable)和自由变量(free variable variable)
在头部(head)中提及的变量被成为约束变量,没有提到的成为自由变量,因为函数可以是其他函数的一部分,所以一个变量可以同时是约束变量,又是自由变量。
substitutions
由于在λ演算中当要使用一个函数时,都需要完整写出完整的定义,这里可以使用其他字符来代替定义,例如恒等function
当恒等function应用于本身时,可以表示为
注意前后的$x$是互相独立的,上式可以写作
对上式作变量替换,将所有$x$用$\lambda z.z$替换
算术
λ演算最早就是应用于算术运算的,但在λ演算中只有函数,并没有所谓的数字,这里用丘齐数来表示,首先定义zero,然后one用suc(zero)表示,two用suc(suc(zero))表示。
zero表示为,需要接受两个参数s和z
可以简写为(λ演算中只定义了单个参数的函数,但是多个参数的函数无非就是单个函数的多次调用,其实就是柯里化)
简化后的式子可以接受两个参数,第一个可替换s,第二个可替换z。这个表达式被应用时,会把第一个表达式丢掉,然后第二个原封不动。
利用这个记号法,其他自然数可以定义为
以上的计数法其实就是在z之上嵌套表达式s,数字多大就嵌套多少次,就是对z应用了n次s。这其实就是自然数的本质,不断加1。
我们定义后继函数(successor function)如下
后继函数可以应用于0得到
同理可以得到2等等,由此即可得到加法的定义,例如2+3就表示2S3,即2 suc 3次。注意以下推导中,2接受两个参数S和3,分别将S和3作为s和z替换,同时也要注意到$S3=4$
柯里化(currying)
这一块可以参考wiki的解释。柯里化就是把接受多个参数的函数变成接受一个单一函数(最初函数的第一个参数)的函数,并返回接受剩余参数的函数的新函数的技术。
举个例子很典型
add(3, 5) -> add(3)(5) |
0的定义为$\lambda sz.z$,这个其实是$\lambda s.(\lambda z.z)$是完全等价的。
乘法(multiplication)
例如2x2的结果为如下,注意2是可以接受两个参数的,所以$2s(z)$实际上是2接受了$s$和$z$作为输入,得到s(s(z))
时刻要记住每个应用函数时,接受了几个参数,并且是左结合的。
条件(conditionals)
定义以下两个函数为真和加,分别接受两个参数返回其中的一个,真就返回第一个,假就返回第二个
逻辑运算(logical operations)
例如
条件测试(a conditional test)
定义一个函数,如果参数是数字0则返回T,否则返回F
验证如下,注意0表示接受两个参数,然后用第一个参数对第二个参数作用0次
注意到,F对任何参数的应用都是返回恒等函数
因此,上式继续展开为
另外可以换一种方式理解,$\mathrm N \mathrm F \lnot \mathrm F $同时也表示对对$\lnot $应用n次$\mathrm F$,然后结果再应用于$\mathrm F $。注意到$\mathrm F $的定义,接受两个参数,仅仅返回第二个参数。第一个$\mathrm F $实际接受了两个参数,一个是对$\lnot$应用了n-1次F的返回值,另一个是后面的一个$\mathrm F $,因此抹掉第一个参数返回第二个参数,也就是返回最后面的那个$\mathrm F $,也就是最后就返回$\mathrm F $。
前继函数(predecessor function)
对于n的前继,通用的做法是创建一个序对(pair),(n,n-1)然后返回需对的第二个参数作为结果。序对用λ演算可以表示为
将该函数应用于$\mathrm T$就可以返回序对的第一个数
同理,应用于$\mathrm F$就可以返回需对的第二个数
利用下面这个函数就可以由序对(n,n-1)生成(n+1,n-1)
这里感觉应该是由序对(n,n-1)生成(n+1,n)才对啊!
注意一下对上式的理解,在函数体z(S(pT))(pT))中,如果没有对z进行规约,则该式子不会进行任何计算;如果用数字n对z进行规约,变成n(S(pT))(pT),此时才可以进一步进行参数替换S(pT)作为n的第一个参数,pT作为第二个参数。
其中,子表达式$pT$从序对p中提取第一个元素。上式会构造一个新的序对,第一个元素是原序对第一个元素的后继——S(pT),第二个元素就是第原序对的第一个元素——pT。
简单来说,应该是由序对(a,b)生成(a+1,a)。
因此n的前继就是应用n次$\Theta$到序对$\lambda z.z00$(得到(n,n-1))然后返回第二个参数得到n-1:
可以我们可以进行推导
以此类推。同时要注意到$P0=0$,该性质对其他函数的定义很有用,验证如下
相等与不等
定义如下函数判断数字$x$是否大于等于$y$
这里的$xPy$表示对y应用x次的前继,也就是y-x,如果该式等于0,说明$y \le x$。
利用$x \ge y$与$y \ge x$同时成立表示$x=y$,可以得到下面这个关于相等的定义
用同样的方式我们也可以定义$x
递归
在λ演算中,递归函数可以定义为调用函数y并且返回自身
注意这里其实是加括号了,完整表示如下
这里第二个$(\lambda x.y(xx))$是规约到第一个约束变量x中去的还是不会减少表达式的个数,
该函数应用于R时
考虑从0到n的求和函数R
该函数对n进行了测试,如果n为0的话,就返回0;如果n不为0则返回n+(r(n-1)),这里r其实是对自身函数的调用。这里我们怎么知道r是对自身的递归调用呢?在λ演算中我们没有对函数定义名字的。这就是给出递归操作Y的原因,例如求和到3
这就是Y组合子(Y combinator)!
ffmpeg常用命令
记录下工作中常用的ffmpeg命令,有些网络上不好查找到,需要总结。用md不知道怎么排版比较合适
1. 编码
u_p444_b10的YUV→100M的YUV420的24fps的HDR10码流(单帧,每帧YUV重复2秒)
# u_p444_b10的YUV→100M的YUV420的24fps的HDR10码流(单帧,每帧YUV重复2秒) |
2. 解码
# 直接解码出YUV444的码流 |
3. 拼接
# 将多段ts流拼接 |
4. 截取
# 从指定时间开始截取一段码流 |
5. 转码/scaler
# 将码流转码成420p10 |
6. 其他
|
7. 备注
- 在编码的时候如果指定-preset ultrafast则速度会比-preset medium快不少,大约只要1/3的时间(单帧编码测试结果)。官方文档表示图像质量是一致的,文件大小有差异,但实测文件大小差异不大
8. ffprobe
# 获取帧数(速度很慢,需要解出来才能获取) |
9. mediainfo
# 获取帧数(速度比ffprobbe快很多) |
10. ref
git使用小记
记录git使用过程的一些问题和方法。
集中式VS分布式版本控制系统
集中式版本管理系统,版本库是集中在中央服务器的,需要先从中央服务器同步下来,然后再推送回去,因此必须联网才能工作。而分布式版本控制系统则没有中央服务器,每个人的电脑上都是一个完整的版本库,因此工作的时候不需要联网,需要协作的时候只需要将相互的修改推动给对方,互相就可以看到修改了。
因此两者之间的历史版本维护位置不同,Git本地库包含了代码库还有历史库,在本地就可以记录历史,而SVN的历史库位于中央仓库,每次对比和提交代码都必须链接到中央库。
由于每个人的电脑都有完整的版本库,因此其安全性很高,某一个人的电脑坏了无关紧要。当然实际使用的时候,很少是是两个人之间的进行版本库的推送,一般也有一台机器充当中央服务器,该服务器的作用仅仅是用来方便大家之间的交流。
本地和远程同步
本地库要推送到远端,但这两个git库不相关,例如已有本地库,然后github上又新建了项目
方法一
可以先将远程库拉下来,然后再将本地的代码拷贝到远端库下载到本地库,然后在提交,这样相当于一次update。不过这样子不能记录原有的git记录
方法二
强制关联推送
# 本地先正常init、add和commit |
git push
用git remote
查看配置的远程库名字,一般origin
是Git克隆的远程仓库服务器的默认名字。
$ git remote # 查看配置的远程库名字 |
git push
的用法为,冒号后面直接加远程分支名:
git push <远程主机名> <本地分支名>:<远程分支名> |
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。下面命令表示删除origin主机的master分支。
git push origin :master |
如果当前分支与多个主机存在追踪关系,则可以使用-u
选项指定一个默认主机,这样后面就可以不加任何参数使用git push
。下面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push
了。
git push -u origin master |
工作区、暂存区和版本库
工作区:在电脑里能看到的目录; 版本库:在工作区有一个隐藏目录.git,是Git的版本库。 Git的版本库中存了很多东西,其中最重要的就是称为stage(或者称为index)的暂存区,还有Git自动创建的master,以及指向master的指针HEAD。
进一步解释一些命令:git add
实际上是把文件添加到暂存区git commit
实际上是把暂存区的所有内容提交到当前分支
git diff
查看修改内容
git diff # 可以查看工作区(work dict)和暂存区(stage)的区别 |
git log
查看提交日志
git log |
git reflog
查看命令历史
git reflog |
git reset
版本回退
返回上一个版本,在Git中,用HEAD
表示当前版本,上一个版本就是HEAD^
,上上一个版本是HEAD^^,往上100个版本写成HEAD~100
。commit_id是版本号,是一个用SHA1计算出的序列
git reset --hard HEAD^ |
git reset --soft HEAD^
:将最近一次提交节点的提交记录回退到暂存区git reset --mixed HEAD^
:将最近一次提交节点的提交记录回退到工作区git reset --hard HEAD^
:将最近一次提交节点的提交记录全部清除
eg:
在Master分支中,首先通过git add test.txt
将test.txt文件添加到暂存区,再通过git commit -m "add file test.txt "
将暂存区的内容作为一次提交记录添加到提交区,最后如果没问题的话就可以通过git push origin master
将这次提交push到远端仓库。
使用
修改commit的message,有点类似
amend
操作
如果此时发现提交记录的comment写错了,如将git commit -m "add file test.txt"
写成了git commit -m "ad file test.txt"
,那么就可以使用git reset --soft HEAD^
将本次提交回退到暂存区,再重新把comment补全,进行一次提交。修改commit的文件
如果此时发现提交记录里有一个文件多提交了,或者有一个文件漏添加到暂存区而没有在此次提交内,则可以通过git reset --mixed HEAD^
将本次提交都回退到没有添加到暂存区之前,然后再重新add需要提交的文件后,再重新add完全撤销此次commit
如果此时发现修复一个BUG完全错了,希望取消这次提交,并且把代码回退到没有改动的话,则需要使用git reset --hard HEAD^
,来将这次提交全部回退。
撤销修改
丢弃工作区的修改
该命令是指将文件在工作区的修改全部撤销,这里有两种情况:
- file自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- file已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。也就是将工作区的状态回退到暂存区或者版本库。
git checkout -- <file> |
丢弃暂存区的修改
git reset HEAD <file> # 第一步,把暂存区的修改撤销掉(unstage),重新放回工作区: |
小结:
- 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- <file>
。 - 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD <file>
,就回到了第一步,第二步按第一步操作。 - 已经提交了不合适的修改到版本库时,想要撤销本次提交,进行版本回退,前提是没有推送到远程库。
git rm
删除文件
git rm <file> |
进一步的解释
Q: 比如执行了rm text.txt 误删了怎么恢复?
A: 执行git checkout -- text.txt
把版本库的东西重新写回工作区就行了
Q: 如果执行了git rm text.txt
我们会发现工作区的text.txt也删除了,怎么恢复?
A: 先撤销暂存区修改,重新放回工作区,然后再从版本库写回到工作区
git reset head text.txt |
远程库
ssh-keygen -t rsa -C "youremail@example.com" # 创建SSH Key |
git pull
git pull命令用于从另一个存储库或本地分支获取并集成(整合)。git pull命令的作用是:取回远程主机某个分支的更新,再与本地的指定分支合并,它的完整格式稍稍有点复杂。
语法的位置和push有点不同,远程主机名在最前,然后push是本地→到远端,pull是远端→本地。
git pull <远程主机名> <远程分支名>:<本地分支名> |
如要要取回origin主机的next分支,与本地的master分支合并,需要写成下面这样:
git pull origin next:master |
如果远程分支(next)要与当前分支合并,则冒号后面的部分可以省略。上面命令可以简写为:
git pull origin next |
上面命令表示,取回origin/next分支,再与当前分支合并。实质上,这等同于先做git fetch,再执行git merge。
git fetch origin |
fetch和 pull的区别
一般使用pull会简单些,不过可能要解决冲突
git pull # 相当于是从远程获取最新版本并merge到本地 |
分支
git branch <branchname> # 创建分支 |
reflog
git log 命令可以显示所有提交过的版本信息;git log 命令可以显示所有提交过的版本信息
现场
git stash # 保存工作现场 |
标签
tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
git tag <tagname> # 用于新建一个标签,默认为HEAD,也可以指定一个commit id。 |
.gitignore
# 忽略.vscode目录 |
常用插件和小工具
1. 常用的chrome插件
- Context Menus/右键搜索
- One Tab 基本必备的插件
- IE tab 还没有试验过,不过有些网站确实只支持IE
- Google Scholar Button
- LastPass: Free Password Manager 以前还挺经常用的,不过现在直接用google账号就可以存好多密码了
- WizClipper/为知笔记
- Octotree 用于github阅读
- IDM IDM配合chrome使用
- TickTick - Todo & Task List 有时候需要同步手机上的清单
- 谷歌访问助手 没有VPN时候就靠这个活着了
- I’m Feeling Lucky How to add Google’s I’m Feeling Lucky Option to Your Chrome Search Engines
2. vscode常用插件及相关配置
2.1. 插件
- vscode-icons
文件格式一目了然,左侧文件目录的文件夹和文件都会显示相应的图标 - Bracket Pair Colorizer
括号用不同颜色标识 - Git History
在vscode中添加git log - LaTex language support
- LeetCode
Markdown All in One
可以使用github flavored markdown渲染标准"markdown.styles": ["D:\\Documents\\01.Github\\01.markdown-css\\github-markdown.css"],
Markdown Math
在markdown中支持数学公式- Markdown Preview Enhance
用于预览markdown - Markdown Shortcuts
添加一些快捷键,写作时比较方便 Markdown TOC
添加目录功能注意,并且可以在header中添加序号。
根据markdownlint的语法要求,一级标题应该仅有一个座位文章的标题,所以需要在二级标题中启动编号。"markdown-toc.depthFrom": 2,
markdownlint
对md文件做语法检查Paste Image
方便在.md文件中复制图片,可以配置在当前同文件名的文件夹下,便于分类"pasteImage.path": "${currentFileDir}/${currentFileNameWithoutExt}/",
Setting Sync
TODO Highlight
高亮TODO并扩展OneDark-Pro
Atom’s ionic主题(首选项-颜色主题修改主题- T
2.2. 配置
"editor.mouseWheelZoom": true, |
ref
3. 实用的软件
3.1. 实际使用
- SumatraPDF/福昕阅读器 小巧的PDF阅读器,不过不能编辑
- Total Commander/Q-Dir/Clover 多窗口多标签的资源管理器,文件整理工具
- Launchy/Wox 快速启动
- Eeverthing 快速搜索
- MediaInfo 强大的视频参数检测工具
- MathType Word中插入公式
- calibre 电子书管理器
- KMSpico 用于注册Microsoft Office
- Potplayer 好用的视频播放器
- Ditto 剪切板管理工具,可以记录多个剪切板,写代码很实用
- 火绒安全软件
- Internet Download Manager 下载工具
- Listary Pro 还没用起来,文件浏览工具,TODO
- MobaXterm/cmder XShell的替代品,全能终端神器
- ShadowsocksR-dotnet4.0 VPN工具
- 搜狗壁纸 桌面管理工具
- 欧路词典 可以自由搭配词典,自由性比较高
- Thunder5 使用专门版本的迅雷,不会被限速,简单速度高
- Beyond Compare 比对工具
- Quicker 效率神器,启动、复制、查找等重复性工作的自动化工具
- TeamViewer 功能强大的远程控制软件
- WinSCP SCP文件传输软件,有点类似Total Commander的界面,同步很方便
- 每日英语听力 练习英语
- 软媒魔方 系统优化工具
- Snipaste 简单强大的截图工具,很实用
- Mathpix Snip 数学公式的OCR工具,用于Latex等
- Xmind/幕布 思维导图工具,TODO
- 为知笔记 笔记工具
- unlocker 强力解除工具,用于解决文件占用问题
- Geek Uninstaller 还未使用,TODO
- DesktopCal 桌面日历
- Seer、QuickLook windows查看工具,TODO
- Screen to GIF/Ocam fit录制/剪辑工具
- 冰点下载 百度文库的免费下载器
- Collagelt 拼图,TODO
- 7-Zip
- SpaceSniffer
- Duplicate Cleaner TODD
- SyncToy 文件夾同步工具 TODO
- Icaros 让资源管理器能够显示所有视频格式缩略图,缩略图拓展增强插件 Icaros TODO
- Smallpdf
- you-get 下载视频神器
3.2. ref
4. 实用的网站
- 极简大纲笔记 | 一键生成思维导图
- UZER.ME云端超级应用空间
- AI人工智能图片放大
- Background Burner: Remove Image Backgrounds Free & Fast 抠图
- wolframalpha
- 脚本之家