牛顿迭代法(Newton's method),又称为牛顿-拉夫逊(Newton-Raphson)方法,是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。牛顿迭代法作为一种数值计算方法,具有收敛速度快、快速求解复杂方程、简单易用等优点,但也存在初始点选择问题、局限于单根问题、迭代公式的推导等缺点。在实际应用中,需要根据问题的复杂度、求解精度等因素,选择合适的数值计算方法,并进行多组试验和分析,以求得较为精确的结果。
1. 牛顿迭代法简介
1.1 牛顿迭代法背景
由于多数方程不存在求根公式,求精确根非常困难,甚至不可解,因此寻找方程的近似根就显得特别重要。牛顿迭代法就是为解决这一问题而提出的。
1.2 牛顿迭代法原理
牛顿迭代法基于函数的导数和函数值的信息,通过不断迭代逼近方程的根。假设要求解方程f(x) = 0的根,首先选取一个初始值x0。通过计算函数f(x)在x0处的导数,得到切线的斜率。然后,找到切线与x轴的交点,将该交点作为新的近似解x1。重复这一过程,不断迭代,直至达到所需精度。
1.3 牛顿迭代法公式
牛顿迭代格式为
牛顿迭代格式的误差为
1.4 牛顿迭代法的优点
- 快速求解复杂方程:牛顿迭代法基于泰勒公式展开函数,在一定条件下可以保证收敛性,并且当迭代次数足够多时,可以达到非常高的精度。
- 收敛速度快:与其他数值计算方法相比,牛顿迭代法的收敛速度非常快。因为牛顿迭代法的每一次迭代都会朝着方程根的方向进行逼近,而且逼近速度越来越快。
- 简单易用:牛顿迭代法的求解过程相对简单,只需要根据泰勒公式展开函数,并进行一定的变量代换,就可以得到逐步逼近方程根的迭代公式。
1.5 牛顿迭代法的缺点
- 初始点的选择问题:牛顿迭代法的收敛性与初始点的选取有关。如果初始点选择不当,可能会导致无法收敛或者收敛速度特别慢。
- 局限于单根问题:牛顿迭代法只适用于求解单根问题,即方程只有一个解的情况。如果方程有多个解,牛顿迭代法可能会收敛到错误的解或者无法收敛。
- 迭代公式的推导:牛顿迭代法的迭代公式需要推导,并且推导过程比较复杂。需要进行泰勒公式展开、变量代换等计算,而且还需要保证公式的收敛性和稳定性。
1.6 牛顿迭代法的应用
牛顿迭代法在实际应用中广泛存在,如在计算机图形学中精确计算圆的周长、面积等参数,实现快速的路径追踪和光线追踪;在金融领域中计算隐含波动率;在机器学习、神经网络中进行梯度下降等。
2 用C#编写牛顿迭代法求解一元高阶方程
2.1 一元高阶方程
我们以五次的一元方程为例,设该方程为,注意等式右边必须为0,其中a1~a5为x高阶系数,a0表示常数
设置为函数形式可以得到
方程问题转换为了函数f(x)零点问题,即f(x)=0时,x的值。
2.2 牛顿迭代法代码
由1.3章节可知,我们需要求解函数f(x)的值和其导数值,代码如下,函数返回值为double数组, double[0]表示f(x)的值,double[1]表示f(x)的导数值。
/// <summary>
/// 求解函数的值
/// </summary>
/// <param name="a5">x的五次方 的系数</param>
/// <param name="a4">x的4次方 系数</param>
/// <param name="a3">x的3次方 系数</param>
/// <param name="a2">x的2次方 系数</param>
/// <param name="a1">x的1次方 系数</param>
/// <param name="a0">常数</param>
/// <param name="x">x的值</param>
/// <returns>返回值double[]数组 double[0]表示函数的值 double[1]表示导数的值</returns>
static double[] fxAnd_diff_fx(double a5,double a4,double a3,double a2,double a1,double a0,double x)
{
// 函数fx的值
double[] result= { a5* Math.Pow(x, 5) + a4 * Math.Pow(x, 4) + a3 * Math.Pow(x, 3) + a2 * Math.Pow(x, 2) + a1 * x + a0,
5*a5* Math.Pow(x, 4) + 4*a4 * Math.Pow(x, 3) + 3*a3 * Math.Pow(x, 2) + 2*a2 * Math.Pow(x, 1) + a1};
return result;
}
整体代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace 牛顿迭代法求解一元高次方程
{
class Program
{
/// <summary>
/// 求解函数的值
/// </summary>
/// <param name="a5">x的五次方 的系数</param>
/// <param name="a4">x的4次方 系数</param>
/// <param name="a3">x的3次方 系数</param>
/// <param name="a2">x的2次方 系数</param>
/// <param name="a1">x的1次方 系数</param>
/// <param name="a0">常数</param>
/// <param name="x">x的值</param>
/// <returns>返回值double[]数组 double[0]表示函数的值 double[1]表示导数的值</returns>
static double[] fxAnd_diff_fx(double a5,double a4,double a3,double a2,double a1,double a0,double x)
{
// 函数fx的值
double[] result= { a5* Math.Pow(x, 5) + a4 * Math.Pow(x, 4) + a3 * Math.Pow(x, 3) + a2 * Math.Pow(x, 2) + a1 * x + a0,
5*a5* Math.Pow(x, 4) + 4*a4 * Math.Pow(x, 3) + 3*a3 * Math.Pow(x, 2) + 2*a2 * Math.Pow(x, 1) + a1};
return result;
}
/// <summary>
/// 求解的方程根
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
// x的五次方 的系数
double a5 = 5;
// x的4次方 的系数
double a4 = -4;
// x的3次方 的系数
double a3 = -3;
// x的2次方 的系数
double a2 = -2;
// x的1次方 的系数
double a1 = -1;
// 方程的常数
double a0 = -4;
// 迭代第k次x的值
double xk = 0;
// 迭代第k+1次x的值
double xk_1 = 0;
// 设置迭代次数
int iter = 1000;
// 求解方程组的值
for(int i=0;i<iter;i++)
{
double[] result = fxAnd_diff_fx(a5, a4, a3, a2, a1, a0, xk);
xk_1 = xk - result[0] / result[1];
Console.WriteLine("迭代第{0}次,迭代结果为{1}",i+1,xk_1);
Thread.Sleep(10);
xk= xk_1;
}
Console.ReadKey();
}
}
}
2.3 代码运行演示结果
我们取 a5=5, a4=-4, a3=-3 ,a2=-2, a1=-1, a0=-4 (大家可以根据需要自行改,若是最高项为x的3次方,设置a5=0, a4=0 即可) 迭代初值为xk=0;代码运行结果如下,运算结果约为1.5478