手动开平方
话题:#数学# #算术#
小石头/文

大家在小学数学中一定都学过四则运算的计算方法,但是说到平方根计算方法,大家就不一定知道了。
实际上,早在秦朝,我国古代数学家就已经发现了,用算筹开平方的方法,这被记载在 《九章算术》中。后来,魏晋大数学家 刘徽,还在用 一张图(见图1)给出了 开平方的原理。

接下来,就让小石头 把 手动开平方的方法 介绍给大家。

■ 问题:设 A 是一个正整数,求 A的带余数平方根,即,求满足,
A = a² + r (r ≥ 0)
的 整数 a 和 r ,a 取最大值 。
● 当 A较小 时,我们可以从1开始,通过不断尝试,找到满足,
a²≤A<(a+1)²
的正整数 a,就是所求平方根,然后计算出余数,
r = A - a² ①
● 当A较大时,用①方法,效率低下,这时可以考虑将 a 分为 a,b 两部分,设 b 部分的 位数为 n,则有,
a,b = a10ⁿ + b
进而,有,
(a,b)² = (a10ⁿ + b)² = a²10²ⁿ + 2(a10ⁿ)b + b² = a²10²ⁿ + ((2a)10ⁿ + b)b = a²10²ⁿ + ((2a),b)b
于是,可以考虑将 A 也分为 A,B 两部分,B 部分为 2n 位数,即有,
A,B = A10²ⁿ + B
这样,余数为,
r = A,B - (a,b)² = (A10²ⁿ + B) - (a²10²ⁿ + ((2a),b)b) = (A - a²)10²ⁿ + B - ((2a),b)b
其中,可以通过①方法求得 a 以及,
r₁ = A - a²
于是,有,
r = r₁10²ⁿ + B - ((2a),b)b = r₁,B - ((2a),b)b
至此,可以从1开始,通过不断尝试,找到使得,
((2a),b)b ≤r₁,B<((2a),(b+1))(b+1)
的 正整数 b,从而 得到 平方根 a,b,最后计算出 余数,
r = A,B - (a,b)² ②
就可以了。
● 如果 A 还要大,则 可以将 a 分为 a,b,c 三部分,让 b和c 都是 n位,有,
a,b,c = (a,b)10ⁿ + c
同时,将 A 分为 A,B,C 三部分,让 B 和 C 都是 2n 位,有,
A,B,C = (A,B)10²ⁿ + B
然后,与上面类似,可求得,
r = (A,B - (a,b)²)10²ⁿ + C - ((2(a,b))10ⁿ + b)b
其中,可以通过②方法,求得 a,b 以及
r₂ = A,B - (a,b)²
于是有,
r = r₂10²ⁿ + C - ((2(a,b))10ⁿ + c)c = r₂,C - ((2(a,b)),c)c
最后,类似②方法,求得 正整数 c,从而得到 平方根 a,b,c 和 余数,
r = A,B,C - (a,b,c)²
★ 总结: 这样,对于任意大的正整数 A 都可分为 A₁,A₂,...,Aᵩ,其中 除了 A₁(小于等于 2n 位)外,其它 A₂,...,Aᵩ 都是 2n 位,同时 将 a 分为 a₁,a₂,...,aᵩ ,其中 除了 a₁(小于等于 2n 位)外,其它 a₂,...,aᵩ 都是 n 位,然后,
* 通过①方法方法 可以 计算出 a₁ 以及 r₁ = A₁ - a₁²;
* 归纳假设,已经计算出了 a₁,...,aᵢ₋₁ 以及 rᵢ₋₁ = A₁,...,Aᵢ₋₁ - (a₁,...,aᵢ₋₁)²,于是有,
rᵢ = (A₁,...,Aᵢ₋₁ - (a₁,...,aᵢ₋₁)²)10²ⁿ + Aᵢ - ((2a₁,...,aᵢ₋₁),aᵢ)aᵢ = rᵢ₋₁,Aᵣ - ((2(a₁,...,aᵢ₋₁)),aᵢ)aᵢ
用 ② 方法,可求得 aᵢ 以及 rᵢ;
通过归纳的方法,最终这求得,
平方根 a = a₂,...,aᵩ
余数 r = rᵩ
■ 问题:对于任意 正小数A,求平方根a。
☆ 可以将 A 分为 A₁,A₂,...,Aᵩ.Aᵩ₊₁,Aᵩ₊₂, ... 其中除A₁外,其它部分都是 2n 位数(小数位数若不够,可以补零),同时 将 a分为 a₁,a₂,...,aᵩ.aᵩ₊₁,aᵩ₊₂,...,其中除a₁外,其它部分都是 n 位数,然后按照 上面的归纳方法,递归到 需要的精度的 小数位数 e 即可,此时有:
a = a₁,a₂,...,aᵩ.aᵩ₊₁,aᵩ₊₂,...,aₑ

以上,就是手动开平方的原理。
实际运算中 取 n = 1,并使用竖式进行运算(见图2),

具体步骤如下:
⒈ 从小数点起,向两边,将A按照两位一组,分成 A₁,A₂,A₃,...,Aᵩ.Aᵩ₊₁, ...,其中 A₁ 可能不足两位;
⒉ 以 A₁ 为目标, 尝试 1 到 9,找到 满足:
◆ 乘方 小于等于 目标,即, a₁² ≤ A₁;
的 a₁ 最大值 ,并计算出余数 r₁;
⒊ 将 余数 r₁ 与 A₂ 拼在一起得到 r₁,A₂,以其为目标,尝试 1 到 9,找到 满足:
◆ 拼接 2×a₁ 后 乘以 自己 小于等于 目标,即,(2×a₁),a₂ × a₂ ≤ r₁,A₂ ;
的 a₂ 的最大值,并计算出余数 r₂;
⒋ 将 余数 r₂ 与 A₂ 拼在一起得到 r₂,A₂,以其为目标,尝试 1 到 9,找到 满足:
◆ 拼接 2×(a₁,a₂) 后 乘以 自己 小于等于 目标,即,(2×a₁),a₂ × a₂ ≤ r₂,A₂;
的 a₃ 的最大值,并计算出余数 r₃;
⒌ ... ...
...
□

图3 是一个实际的例子。

最后,用类似的原理,还可以 分析出来 手动开立方根 的方法,大家有兴趣可以自己试一试。

附录:
以上手动开平方算法的 JavaScript 代码描述如下,
(原本是法动态的,结果字数超了,所以 文章 和 代码 都写的比较乱,大家凑合看😁)