[计算机数值分析]牛顿下山法求方程的根
Posted Spring-_-Bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[计算机数值分析]牛顿下山法求方程的根相关的知识,希望对你有一定的参考价值。
问题描述
一般来说,牛顿法的收敛性依赖于初值 x₀ 的选取,如果 x₀ 偏离方程的正解根 x* 较远,则牛顿法可能发散。
例:用牛顿法求方程 x³ - x - 1 = 0在 x = 1.5 附近的一个根。
取迭代初值 x₀=1.5,应用牛顿公式 x′ = x₀ - (x₀³ - x₀ - 1) / (3x² - 1), 计算结果如下:x₁ = 1.34783, x₂ = 1.32520, x₃ = 1.32472,其中 x₃ 的每一位数字都是有效数字。
但是,如果改用 x₀ = 0.6 作为初值,则按照牛顿公式迭代一次得 x₁ = 17.9,这个结果反而比 x₀ 更偏离了所求得根。
为了防止迭代发散,通常对迭代过程再附加一项要求,即保证函数值单调下降,满足这项要求的算法称为下山法。
将牛顿法与下山法结合起来使用,即在下山法保证函数值稳定下降的前提下,用牛顿法加快收敛速度。
为此,将牛顿法的上一次迭代初值与本次迭代值进行适当加权平均后作为新的改进值,我们有理由相信,加权后的改进值是比未改进前的近似根更好的的根,它更好地逼近了真实解。即使新的改进值 x₁′ = λx₁ + (1 - λ)x₀。
其中λ称为下山因子,适当选择下山因子可以使函数满足单调下降条件。下山因子的选取是一个逐步探索的过程,从 λ = 1 开始反复将因子 λ 的值减半进行试算,一旦单调性条件成立,则 “下山成功”,否则 “下山失败”。若 “下山失败”,这时则需另选初值 x₀ 重算。
如前有例子描述,当选取初值 x₀ = 0. 6时,如果取下山因子 λ = 1 / 32,则可求出 x₁ = 1.140625,这个结果纠正了原有的严重偏差。
运行示例
源码
#include<iostream>
#include<cmath>
using namespace std;
double f(double x); //f(x)为需要求解方程的对应函数
double f1(double x); //f1(x)为f(x)的一阶导数
int main(void)
double accuracy, N; //accuracy为精度;N为最大迭代次数;
double x0, x1; //x0为运用牛顿法时选取的初值;x1为迭代初值的下一次迭代值
int count; //count为当前迭代次数
cout << "请输入迭代初值:";
cin >> x0;
cout << "请输入精度:";
cin >> accuracy;
cout << "请输入最大迭代次数:";
cin >> N;
count = 0;
do
count++; //迭代次数自增1
if (count > N) //迭代次数达到限制
cout << "达到允许的最大迭代次数!迭代结束!" << endl;
break;
if (f1(x0) == 0) //不符合牛顿法求根条件,无法求根
cout << "在x0附近f(x)的一阶导数值为0!不适用牛顿法求方程的根!" << endl;;
break;
else
double L = 1;
x1 = x0 - L * f(x0) / f1(x0); //迭代一次
while (abs(f(x1)) >= abs(f(x0))) //函数值未单调下降,控制下山因子的大小使得单调性条件得到满足,若不满足,则换初值重算
L /= 2;
x1 = x0 - L * f(x0) / f1(x0); //应用下山因子对迭代值进行改进
cout << "\\n下山因子L = " << L << endl;
cout << "第" << count << "次迭代,方程的近似根为:" << x1 << endl;
//交换x0与1的值,便于进行下一次迭代
double temp;
temp = x1;
x1 = x0;
x0 = temp;
while ((abs(x1 - x0) > accuracy));
return 0;
double f(double x) //原函数
double result = pow(x, 3) - x - 1;
return result;
double f1(double x) //导函数
double result = 3 * pow(x, 2) - 1;
return result;
以上是关于[计算机数值分析]牛顿下山法求方程的根的主要内容,如果未能解决你的问题,请参考以下文章