数学 / 实数 · 从数轴的空位到浮点的间距 待审核 5 页

实数 · 从数轴的空位到浮点的间距

数从数数开始。此后每一次扩充数系都由一件做不成的事推动:自然数里减法可能无解,整数里除法可能无解,有理数里开方与取极限可能无解。前三步补的是某个方程的解,第四步补的是「取极限」这个动作的落点,性质不同,也难写得多。

本系列五页走完这条路。开篇排出 ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ 的嵌套与各层的封闭性,并给出有理数的稠密性:任意两个有理数之间还挤着无穷多个,数轴上却仍有位置空着。第二页把有理数与小数展开对上:长除法的余数只有有限种取值,循环因而必然出现;反向由错位相减还原分数;再往下问循环节有多长,答案落在分母的因数分解与一个模运算的阶上。第三页证 √2 写不成分数,两条证明互不依赖,随后由有理根定理一次覆盖全部非完全平方数,末节交代代数数与超越数的分层。第四页是落点:完备性的四种表述互相等价,且在 ℚ 上同时失效——x² − 2 在有理数上从负变到正却没有根,二分法因此永不终止。第五页换到代码里,double 是一个有限集,实数轴上绝大多数点根本不在其中。

几处实测顺手记在正文里:3.14 与 3.15 之间分母最小的有理数是 22/7,3.141592 与 3.141593 之间是 355/113,而 1.414 与 1.415 之间不是熟脸 99/70 而是 58/41;长除法引擎的 200 步上限比看起来更容易撞上,lab 允许的 9998 个分母里有 5217 个展不完,最长的 1/9967 循环节 9966 位;有理数上的二分跑到第 64 步区间宽 1/2^63,中点分母已是 20 位十进制数,符号判定一次也没给出零;double 那一侧,[0, 1) 内装了 4607182418800017408 个可表示数,是 [1, 2) 内 2^52 个的 1023 倍。

数系的扩张与小数展开

四层嵌套的次序由封闭性决定:减法要负数、除法要分数、开方与取极限要实数。有理数在数轴上稠密,而它们的小数展开只有有限与循环两种形态——循环节的长度由分母里 2 与 5 之外的那部分决定。

ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ

数轴与数系的四层嵌套

沿 ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ 排出四种数系的嵌套关系,说明每一次扩张补上了哪种运算的封闭性。有理数在数轴上稠密,任意两个之间还挤着无穷多个,数轴上却仍有点没被占住。

长除法 · 循环节

有理数与小数展开

长除法的余数只有 q 种取值,鸽巢原理保证它必然重复,故有理数的小数展开必为有限或循环。反向由错位相减还原分数。循环节的长度等于 10 在模 q′ 下的乘法阶。

循环节长度不看分母大小,看 10 的阶

「分母越大循环节越长」只在最好的情形下成立。上限是 q′ − 1(q′ 是分母去掉 2 与 5 的因子后剩下的部分),取到上限要求 10 是模 q′ 的原根,200 以内这样的素数只有 17 个:7, 17, 19, 23, 29, 47, 59, 61, 97, 109, 113, 131, 149, 167, 179, 181, 193。落差可以很大:1/13 的循环节是 6 而不是 12,1/101 只有 4;239 是素数而 238 = 2 × 7 × 17,10 的阶取到了最小的那个因数,1/239 的循环节只有 7 位。阶必整除 φ(q′),具体是哪个因数要算过才知道。 有理数之外

√2 写不成分数,奇偶反证与无穷递降各证一遍,有理根定理把结论推广开去。补上有理数留下的空位就是完备性:确界原理、单调有界、区间套与 Cauchy 列讲的是同一件事,四条在 ℚ 上一起失效。

√2 · 有理根定理

无理数:反证、递降与超越

√2 写不成分数有两条互相独立的证明:最简分数的奇偶矛盾,与整数边长三角形的无穷递降。有理根定理把结论一次性推广到任意非完全平方数,末节交代代数数与超越数的分层。

确界原理 · 区间套

实数的完备性

完备性是实数区别于有理数的那条性质。确界原理、单调有界定理、区间套与 Cauchy 列是它的四种说法,四者互相等价,且在 ℚ 上同时失效:x² − 2 在 ℚ 上从负变到正,却没有根。

同一个量换条算路才量准

√2 的连分数渐近分数的逼近质量是 q²·|p/q − √2|,理论值收敛到 1/(2√2) = 0.353553390593。直接算 p / q - Math.SQRT2 只在前八项可信:第十二项(19601/13860)偏到 0.35355356,第二十一项给出 0.6621(接近真值两倍),到第二十二项 131836323/93222358 时 p / qMath.SQRT2 已是同一个 double,差值恰为 0,整个量塌成零。两个都以 1.41421356 开头的数相减,有效位被抵消掉。改用 Pell 方程给出的等价式 1/(p/q + √2) 之后不再相减,全程稳定,单测把两条算路并列钉住。 落到机器里

双精度浮点是一个有限集,每个元素都是二进制有理数 m · 2^e。0.1 在二进制下是循环小数,于是 0.1 + 0.2 !== 0.3;间距随量级翻倍,判等只能带容差。精确算术要用 BigInt 分数换,代价是开方与超越函数出不来。

binary64 · ulp

浮点数:实数在代码里的残影

双精度浮点是一个有限集,它的每个元素都是二进制有理数 m·2^e。0.1 不在其中,它在二进制下是循环小数。由此得到 0.1 + 0.2 !== 0.3、机器 epsilon 与 ulp,以及判等必须带容差。

Number.EPSILON 不是误差上限

Number.EPSILON 是 1 处相邻两个 double 的间距(2^−52),别处的间距不是这个数:0.1 处是 1.3878 × 10^−17,10^9 处是 1.1920928955078125 × 10^−7,2^53 处已经是 2。把它当成通用误差上限写判等,在大量级处会退化成 ===——绝对容差 10^−9 比 10^9 处的间距还小。可靠的写法是绝对与相对两条容差取较宽者,绝对容差管 0 附近,相对容差管大量级。

相关链接

数系与小数展开

无理性与完备性

浮点