手动计算开根号(长除法)

                     

贡献者: addis; ChatGPT

  1我们举例说明如何用长除法计算开根号

例 1 

图
图 1:手动开根号的例子,计算 $\sqrt{21} = 4.582\dots$

   作为一个例子,我们来计算 $\sqrt{21}$。首先试一个最大的一位数 $x$(红色,范围 0-9),使它的平方小于等于 $21$,易得 $4$。把 $4$ 分别写到根号左边和上方,相乘得 $16$ 写到 $21$ 下方。现在计算 $21-16 = 5$,写到下方并在后面添加两个零得 $500$。接下来把最上方的 $4$ 乘以 $20$ 写到第二个根号左边,并试一个橙色的最大一位数 $x$ 使得 $(80+x) x$ 同样小于等于 $500$,易得 $x = 5$,$85\times 5 = 425$。继续用 $500-425$ 并在后面加两个零得 $7500$。把当前最上方的两位数 $45$ 乘以 $20$ 得 $900$ 写到第三个根号左边,再试一位绿色的数 $x$,使 $(900+ x) x$ 小于等于 $7500$,易得 $x = 8$,$908\times 8 = 7264$。再算 $7500-7264$,添加两个零得 $23600$。把最上方所得三位数 $458$ 乘以 $20$ 写到第四个根号左边,试一位蓝色的数 $x$ 使 $(9160+x)x$ 小于等于 $23600$,得 $x = 2$。以此类推,就可以精确到任意位小数,即 $\sqrt{21} = 4.582\dots$。

   注意该方法也适用于对非整数开根号。另外如果要开根的数大于 $100$ 或小于 $1$,可以先把它乘以 $100^{N}$($N$ 为任意整数)使其落到 $1$ 到 $100$ 之间,开完根后再除以 $10^N$ 即可。这是因为 $\sqrt{100^{N} x}/10^N = \sqrt{x}$。这种做法可以保证上述的第一步中总是可以用一个一位数试根。

   注意该算法适合手动计算,但并不适合用于在计算机中实际使用,计算机一般用效率更高的迭代法等

推导

   若我们要算 $s^2$ 的开根号,并假设 $s$ 的 $n$ 位有效数字(不做四舍五入)为 $s_n$,例如 $s = \sqrt{2} = 1.414213562\dots$,则 $s_1 = 1$,$s_2=1.4$,$s_3=1.41$,……那么显然有

\begin{equation} s^2 = s_1^2 + (s_2+s_1)(s_2-s_1) + (s_3+s_2)(s_3-s_2) + \dots~ \end{equation}
现在,第 $i$ 位有效数字(小数点位置不变)为 $d_i = s_i-s_{i-1}$,且 $d_1 = s_1$,易得
\begin{equation} s^2 = d_1^2 + (2s_1 + d_2)d_2 + (2s_2 + d_3)d_3 + \dots~ \end{equation}
现在,若已知 $s^2$,我们就可以先试出最大的 $d_1$,满足 $d_1^2\leqslant s^2$。然后再试出最大的 $d_2$,满足 $(2s_1 + d_2)d_2 \leqslant s^2 - d_1^2$,以此类推就可以求出任意位的小数。

1. 教学代码

   这里给出上面计算过程的 Matlab 代码 sqrt_hand.m,若有例子不会算可以用它来教学。例如要计算图 1 中的例子 $\sqrt{21}$ 的 6 位小数,可以调用 sqrt_hand(21, 6),输出如下:

4.58257...
-----------------
4, 4, 21, 16
5, 85, 500, 425
8, 908, 7500, 7264
2, 9162, 23600, 18324
5, 91645, 527600, 458225
7, 916507, 6937500, 6415549
sqrt_hand(3, 6)
1.73205...
-----------------
1, 1, 3, 1
7, 27, 200, 189
3, 343, 1100, 1029
2, 3462, 7100, 6924
0, 34640, 17600, 0
5, 346405, 1760000, 1732025
sqrt_hand(0.3, 6)(实际计算 $\sqrt{30}$)
0.54772...
-----------------
5, 5, 30, 25
4, 104, 500, 416
7, 1087, 8400, 7609
7, 10947, 79100, 76629
2, 109542, 247100, 219084
2, 1095442, 2801600, 2190884
sqrt_hand(8, 6)
2.82842...
-----------------
2, 2, 8, 4
8, 48, 400, 384
2, 562, 1600, 1124
8, 5648, 47600, 45184
4, 56564, 241600, 226256
2, 565682, 1534400, 1131364
sqrt_hand(110, 6)(实际计算 $\sqrt{1.1}$)
10.4880...
-----------------
1, 1, 1.1, 1
0, 20, 10, 0
4, 204, 1000, 816
8, 2088, 18400, 16704
8, 20968, 169600, 167744
0, 209760, 185600, 0
代码 1:sqrt_hand.m
function sqrt_hand(x, N)
if x <= 0
    error('x <= 0');
end
if N > 14
    error('too many digits!');
end
order = log10(x); % 0 to 2
scale = round((1-order)/2)*2;
ans_str = num2str(sqrt(x), N+2);
disp([ans_str(1:N+1) '...']);
x1 = x*10^scale;
d = zeros(1, N);
tmp = sqrt(x1);
% get digits (cheating)
for i = 1:N
    d(i) = floor(tmp);
    tmp = (tmp-d(i))*10;
end
rem = x1;
disp('-----------------');
left0 = 0;
for i = 1:N
    left = left0*10 + d(i);
    low = left*d(i);
    disp(d(i) + ", " + left + ", " + rem + ", " + low);
    rem = (rem - low)*100;
    left0 = left0*10 + d(i)*2;
end
end


1. ^ 参考 Wikipedia 相关页面

                     

© 小时科技 保留一切权利