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

                     

贡献者: 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 相关页面


致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

                     

友情链接: 超理论坛 | ©小时科技 保留一切权利