Vim 学习笔记
vim 被称为编辑器之神,学习难度很大,但是熟练掌握后可以更高效地敲代码,因此有必要学一下,但是没必要鼓捣各种插件。主要参考:【Vim】可能是B站最系统的Vim教程 vim 介绍与版本vim 是古董编辑器 vi 的升级版,在现代的 Linux 发行版中通常自带 vim,无需手动安装,虽然版本通常不是最新的,但是也足够使用。在很多发行版中都将 vi 命令链接到 vim 命令,因此 vi 命令和 vim 命令通常是等价的,都是在调用 vim 编辑器。 在 vim 中输入 :version 可以查看版本信息,例如 123VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Nov 22 2021 19:31:05)Included patches: 1-3582Compiled by <https://www.msys2.org/> vim 的各种功能模块化,在编译安装时可以选择精简其中一部分功能,至少有几种安装模式:tiny, small, normal, big, huge,显然 huge 版本的功能最完整。 在 :version ...
K-means 算法
K-means 算法是一种经典的无监督学习算法,用于将数据自动分为 $k$ 个簇,这里的 $k$ 需要提前给定。 K-means 算法假设簇是凸的、大小相近,此时处理效果最好,但是并不能处理复杂形状的簇(如半月形),对维度高的稀疏数据(如文本)不太适用。 算法步骤设数据集为 $X = {x_1, x_2, \dots, x_n}$,$x_i \in \mathbb{R}^d$,希望聚为 $k$ 类,算法流程如下: 初始化:随机选择 $k$ 个数据点作为初始的簇中心。 分配:将每个数据点分配到最近的簇中心,以形成 $k$ 个簇。设当前中心为 $\mu_1, \dots, \mu_k$,对于样本 $x_i$,所属的簇为$$ x_i \in C_s ,, \text{where} ,, s = \arg\min_{j=1,\dots,k} | x_i - \mu_j |^2$$ 更新:重新计算每个簇的中心,记 $C_s$ 是第 $s$ 个簇内的数据点集合,那么中心 $\mu_s$ 为$$ \mu_s = \frac{1}{|C_s|} \sum...
Cpp 练习——命令行参数解析
CmdParser 是一个模仿 cmdline 的轻量级的 C++ 命令行参数解析工具,支持解析标志(flags)和选项(options),并能够处理回调函数、类型转换以及剩余参数。 特点 标志解析 支持定义简单的布尔标志,例如 --help 或 --verbose 标志是可选的,在解析过程中会对标记出现的次数计数 可以通过回调函数来定义标志存在时的触发事件 选项解析 支持带值的选项,例如 --scale=2.0 或 --scale 2.0 选项可以设置为可选或必选,在解析过程中会记录每次出现的选项的值 支持的数据类型包括:int、double、bool、string、char、size_t 支持四种添加方式 提供默认值,提供回调函数检查 提供回调函数检查 提供默认值 都不提供 补充 标志和选项的名称要求: 必须提供一个--开头的,加上若干字母、数字、下划线组成的完整名称,区分大小写,例如--len; 可以额外提供一个-开头的,加上单个字母或数字组成的缩写名称,例如-v; 所有名称互异。 标志和选项都需要提供说明字符串,可以使用空字符串 使用方法创建 ...
Julia 版本管理和环境管理
Julia 的版本管理和环境管理,通常可以分成两部分来看: juliaup:Julia 版本管理 Pkg:项目环境和包管理 和 Python 中常见的 pyenv + venv + pip 组合(以及其他各种替代方案)相比,Julia 直接从语言角度就考虑,设计更加统一优雅: Julia 版本推荐由 juliaup 管理;(如果只使用一个版本,也可以绕过 juliaup) 项目依赖和环境由 Julia 自带的 Pkg 标准库管理; 环境本质上不是一套独立拷贝的运行时,只是两个文本文件,对应依赖声明与解析结果。 Julia 的版本和环境管理机制和 Rust 很相似,可以说是现代编程语言设计的最佳方案。 Julia 运行时和版本Julia 运行时Julia 运行时指的是使 Julia 程序能够执行的一组核心文件,通常包括: julia 可执行文件 Julia 自带标准库(standard libraries) Julia 的系统镜像(system image) 动态库和底层运行时组件 第三方包并不直接属于 Julia 自带运行时,它们通常存放在 depot 中,由当前...
Julia 学习笔记——绘图基础
这篇笔记只关注 Julia 里最基础、最常用的科学计算绘图,不追求复杂可视化能力。 原因也很简单:如果只是画函数曲线、散点图、热图、简单布局,那么 Julia 自己已经够用;但如果进入更复杂的工程化可视化、交互式图形或者生态成熟度要求很高的场景,通常还是更容易回到 Python。 概述Julia 绘图生态里最常见的入口大概有这几种: Plots.jl:接口统一、上手简单,最适合基础笔记 GR:常见默认后端,轻量、够快 PyPlot.jl / PythonPlot.jl:更接近 Matplotlib 习惯 Makie.jl:更强、更现代,但复杂度也明显更高 如果只是“科学计算里顺手画图”,最实用的选择还是: 直接使用 Plots.jl 默认后端先用 GR 这篇笔记也只按这个思路整理。 安装与加载最基本的安装: 12using PkgPkg.add("Plots") 使用时: 1using Plots 如果需要显式指定后端: 1gr() 基础使用里不用太在意后端细节,先能画出来最重要。 最简单的曲线图直接给 y123using Plotsp...
Julia 学习笔记——性能优化与并行计算
Julia 最大的吸引力之一,就是“高层写法”和“高性能”之间的距离没有传统动态语言那么远。 但这并不意味着随便写都能快。Julia 的性能优化有一套非常典型的思路,而并行计算又是另一个常被误解的话题,所以这里把它们放到一篇里做一个够用版整理。 概述先记下面几点: Julia 可以快,但前提是写法利于类型推断和特化编译; 第一次运行慢,往往是编译开销,不一定是算法本身慢; 真正的性能问题,很多时候不是“语法不够底层”,而是分配太多、类型不稳定、全局变量太多; 并行计算不是给代码加个宏就自动变快,任务划分、内存分配和数据传递同样重要。 性能分析基础@time最基本的计时方式: 1@time sum(rand(10^6)) 它一般会显示: 执行时间; 内存分配次数与大小; GC 时间比例等。 但是要特别注意:第一次运行时通常包含编译成本,所以参考意义有限。 更稳妥的做法是至少跑两次: 12@time f(x) # first run: compile + execute@time f(x) # second run: closer to steady-state Be...
Julia 学习笔记——线性代数
数组是 Julia 的核心内容之一,而线性代数则是它真正发力的主场。虽然前面的数组笔记已经涉及了一些矩阵和广播,但如果不单独整理一篇,很多线性代数语义还是容易和“普通数组运算”混在一起。 概述Julia 的线性代数体验和 Python/Numpy、MATLAB 既相似又不同: 和 MATLAB 一样,矩阵乘法直接使用 *; 和 Python/Numpy 一样,元素访问写成 A[i, j]; 但 Julia 的标准库 LinearAlgebra 还引入了很多特殊矩阵类型和分解对象,它们不是简单的“二维数组”。 因此看 Julia 里的线性代数代码时,需要同时区分: 这是普通数组操作; 还是线性代数意义上的操作; 结果是立即物化的数组,还是带语义的特殊对象。 LinearAlgebra 标准库线性代数相关功能主要来自标准库: 1using LinearAlgebra 它不是默认自动导入的,但属于 Julia 自带标准库,不需要额外安装。 向量与矩阵创建12x = [1, 2, 3] # VectorA = [1 2 3; 4 5 6] ...
Julia 学习笔记——补充. 与 Python 和 MATLAB 的差异整理
这一篇把 Julia 与 Python、MATLAB 的主要差异集中整理一下,方便在系统看各个专题之前先有个整体印象。 先说明几点: 下文默认读者已经熟悉 Python 和 MATLAB; 默认以 Julia 1.12 系列为准; 这里只做迁移视角下的差异整理,不追求把所有细节一次性讲完; 真正的语法和行为细节,仍然以后面各专题笔记为主。 概述如果只用一句话概括,Julia 大致可以理解为: 语法观感上吸收了 Python、MATLAB、Fortran 等科学计算语言的很多习惯; 执行模型上又明显更接近带 JIT 的编译型语言; 语言设计中心不是 class,而是数组、数值计算、泛型函数和多重分派。 因此,从 Python 或 MATLAB 迁移到 Julia 时,真正需要适应的往往不是“语法会不会写”,而是下面这些更底层的习惯: 语言默认鼓励什么样的代码组织方式; 哪些直觉来自 Python,哪些来自 MATLAB,而 Julia 恰好都不完全一样; 编译、类型推断和方法分派会如何反过来影响日常写法。 整体定位和 Python 相比,Julia 最明显的差异在于:它...
Julia 学习笔记——10. 输入输出与文件交互
前面的基础笔记里已经零散提到过 print、println、readline 这些最简单的输入输出操作,但如果要真正写脚本或小工具,还需要文件读写和路径处理。 概述Julia 中与 IO 相关的几类操作包括: 控制台输入输出; 文本文件和二进制文件; open do 风格的资源管理; 常见的路径、目录和文件系统操作。 整体上,Julia 的 IO 风格更接近“显式流对象 + open do 管理资源”,而不是 MATLAB 那种偏工作区工具式接口。 控制台输入输出print 和 println最常用的输出函数仍然是: 12print("hello")println("world") 区别很简单: print 不自动换行; println 自动在末尾补一个换行。 也可以连续输出多个对象: 1println("x = ", 1, ", y = ", 2) 字符串插值更顺手的写法通常是字符串插值: 123x = 3y = 4println("x = $x, y = $y, x + y ...
Julia 学习笔记——9. 宏与元编程
宏和元编程是 Julia 里非常有代表性的部分。它们既是语言能力的一部分,也是很多 Julia 代码看起来“很不一样”的原因。 不过宏虽然重要,但绝对不是日常写 Julia 代码的起点。大多数普通逻辑都应该优先写成函数,只有当函数做不到,或者语法层面介入明显更自然时,才值得考虑宏。 概述Julia 的宏并不是 C 语言那种简单文本替换,而是基于语法树(AST)的代码变换工具。 可以先这样理解: 函数操作的是“值”; 宏操作的是“代码表达式”; 宏在代码真正运行前先展开; 展开结果再交给 Julia 去编译和执行。 因此,宏更像是“改写代码的工具”,而不是普通的可调用逻辑。 宏的基本形式最简单的宏定义如下: 123macro sayhello() return :(println("Hello, World!"))end 调用时使用 @: 1@sayhello 输出: 1Hello, World! 这里最值得注意的是: 宏调用通常不需要括号; 宏返回的不是最终结果,而是一段表达式; 这段表达式会继续被 Julia 执行。 当然,带括号的调用也...
