题目

利用牛顿-拉夫逊(Newton-Raphson)迭代法求解非线性方程 $f(x) = x^2 - a = 0$ 的正根(即求 $\sqrt{a}$)。给定初值 $x_0 = a/2$,迭代公式为 $x_{k+1} = \frac{1}{2}(x_k + \frac{a}{x_k})$,设定收敛精度 $\epsilon = 10^{-10}$ 与最大迭代次数,循环求解并与内置 <code>sqrt</code> 比较。

输入格式:一行输入一个正数 a。

输出格式:分行输出迭代步数、牛顿法结果、内置 sqrt 结果及绝对误差。

数据范围与约定:a > 0。

思路与算法

1. 牛顿法数学递推
一阶泰勒展开推导迭代式:$x_{k+1} = x_k - \frac{f(x_k)}{f'(x_k)}$。对于 $f(x) = x^2 - a$,导数 $f'(x) = 2x$,化简即为著名的巴比伦平方根迭代式。

2. 双重循环安全防死循环
数值算法中的 while 循环必须同时配备两个终止条件:① 误差收敛 abs(x_new - x) < tol;② 最大迭代次数 iter < max_iter,防止因方程奇异发散引发死循环。

3. 二次收敛速度
牛顿法在根附近具有二次收敛性,通常 5~8 次即可达到机器精度。

完整程序

% Octave / MATLAB 第56题:牛顿迭代法求平方根
[a, count] = scanf("%f", 1);

if count < 1 || a <= 0
    fprintf("错误:请输入大于 0 的正数。\n");
    return;
end

x = a / 2; % 初始猜测
tol = 1e-10;
max_iter = 100;
iter = 0;

while iter < max_iter
    x_new = 0.5 * (x + a / x);
    iter = iter + 1;
    if abs(x_new - x) < tol
        x = x_new;
        break;
    end
    x = x_new;
end

fprintf("求解 sqrt(%.4f):\n", a);
fprintf("迭代次数: %d 步\n", iter);
fprintf("牛顿法求得根: %.10f\n", x);
fprintf("内置 sqrt 结果: %.10f\n", sqrt(a));
fprintf("绝对误差: %.2e\n", abs(x - sqrt(a)));

运行示例

示例 1:

输入:

2

输出:

求解 sqrt(2.0000):
迭代次数: 5 步
牛顿法求得根: 1.4142135624
内置 sqrt 结果: 1.4142135624
绝对误差: 2.22e-16

示例 2:

输入:

100

输出:

求解 sqrt(100.0000):
迭代次数: 8 步
牛顿法求得根: 10.0000000000
内置 sqrt 结果: 10.0000000000
绝对误差: 0.00e+00