告别 Wercker

2015 年的时候,我设置了 Wercker 工作流。每次本站的源代码仓库更新时,Wercker 的工作流会自动做两件事:1) 由 Markdown 源码构建静态网站;2) 发布到 github.io 上去。

时过境迁,Wercker 从某一年开始被 Oracle 收购了,直到去年的某个时候,我的工作流似乎不再工作了。wercker.com 现在会自动重定向到 Oracle Cloud 的网站;我甚至没法登录原来的 Wercker 账号。因此我需要找新的方法。

Github 在这些年也改变了很多,新增加的 Github Actions 功能在我看来就是一个抄袭了 Wercker 的功能。由于跟 Github 整合的更好,想必拉拢到了不少的用户群(拥有用户群的平台就是可以占便宜推广自家产品)。我也把自动构建的工作流迁移到了 Github Actions。

继续阅读 →

Go语言的泛型

长期以来, Go 语言缺乏泛型 (Generics) 的支持。曾经有人认为在 Go 2.0 问世前都不会支持泛型。我很久没有关注 Go 语言的动态了(最后一次写的 Go 项目还没有用 module 机制),今天才发现一年前的 Go 1.18 就已经增加了泛型。

简单地说,泛型可以将同一段代码作用在多种数据类型上。C++ 里的模板 (template) 就是一种泛型编程的方式。下面的 max 函数返回两个参数中较大的那个。不论 a b 是什么类型,只要支持 < 运算符,就可以用这个函数。

template <typename T>
T max(T a, T b) {
    return a < b ? b : a;
}
// max(1, 2) == 2
// max(2.5, 3.1) == 3.1

在 Go 中,一直没有比较好的方法实现这个效果。像 max 这种简单的函数,一般可以用的时候现场写一个,只是不太方便。

现在,可以在 Go 写一个泛型函数来实现:

import "golang.org/x/exp/constraints"

func max[T constraints.Ordered] (a, b T) T {
    if a < b {
        return b
    }
    return a
}
// max(1, 2) == 2
// max(2.5, 3.1) == 3.1
// max("abc", "def") == "def"

constraints.Ordered 包括有能比大小的类型(数值类型和字符串)。目前为止,constraints 还没有正式加入标准库中,只能从 golang.org/x/exp 这个实验性质的 module 中获取。

继续阅读 →

8位微控制器实践(0) - 绪论

微控制器 (MCU) 也叫单片机,指把处理器、内存、各种外设集成在一块芯片内的计算机。现在的个人计算机的数据总线宽度已经达到64位,而微控制器一般还停留在8/16/32位。可见,微控制器的功能相对有限,但对于一些简单的控制系统来说已经足够。由于微控制器价格低廉、简单易用,它也常常被用在一些业余硬件项目中。

这个系列将要讨论的是8位微控制器,属于微控制器中的底层。常见的8位微控制器有:

继续阅读 →

高等算术习题(6) – 二次型

《高等算术》第六章主要研究二元二次型 ax²+bxy+cy² 的理论。这一章主要研究了等价二次型、正定二次型的约化等价形式,以及二次型的表示问题(这是二平方和问题的推广)。

继续阅读 →

高等算术习题(5) – 平方和

《高等算术》第五章研究将自然数表示为平方和的方法,讨论了三种情况:

  • 二平方和:所有形如 4k+3 的质因子的次数必须为偶数(可以是 0);
  • 四平方和:任意自然数都可以表示为四平方和;
  • 三平方和:除了形如 4l(8k+7) 外的自然数都可以表示为三平方和(未给出证明)。

对于二平方和问题,书中给出了若干构造方法。

继续阅读 →

高等算术习题(4) – 连分式

《高等算术》第四章讲了连分式。有理数(无理数)总可以表示为有限(无限)长的连分式。满足一定限制条件的情况下,这种表示是唯一的。截取连分式的前若干个数,得到的分数称为渐进 (convergent),渐进总是交替地大于和小于目标数,并最终收敛到目标数。

一个有趣的现象是:二次代数数1的连分式总是循环的。这个性质进一步可以用于求解 Pell 方程 \[x^2-Ny^2=1\] 它的解是 \(\sqrt N\) 的(循环)连分式的某些渐进的分子和分母。

一点题外话:连分式在初等数论之外也有应用。例如可以证明 π 和 e 的连分式是无限长的,因此它们是无理数。

继续阅读 →

高等算术习题(3) – 二次剩余

继续阅读 Davenport 的《高等算术》的第三章。这一章讲了原根、二次剩余和二次互反律。这些内容在 Pinter 的《抽象代数》第二十三章也略有涉及。本章提到了欧拉准则、高斯引理,并给出了二次互反律的证明。

继续阅读 →

抽象代数习题(33) – 方程的根式解

这是《抽象代数》的最终章。至此,终于能够解答第一章提出的问题:五次方程是否存在求根公式? 使用 Galois 理论可以一般地回答代数方程的根式可解性问题。

设多项式 p(x) ∈ F[x],那么代数方程 p(x) = 0 根式可解意味着 x 可以由 F 中的元素经过有限次加、减、乘、除和开方运算表示。这等于说方程的根在 F 经过有限次根式扩张 (radical extension) 得到的数域中,通过 Galois 对应可以得到相应的 Galois 群是可解群 (solvable group)。通过证明存在五次方程具有不可解的 Galois 群,就证明了它不存在根式解;于是,五次方程一般的求根公式也就不存在。

继续阅读 →

抽象代数习题(32) – Galois 理论II

《抽象代数》第三十二章讲的是 Galois 理论的核心内容。设 K 是 F 的分裂域,Galois 群是所有 K→K 且固定 F 的同构构成的群(群的运算为映射的复合),记作 Gal(K:F)。Galois 理论的关键内容是,K 和 F 的所有中间域 I (即 K⊆I⊆F) 和 Gal(K:F) 中的子群有着一一对应的关系。

继续阅读 →