大家好,我是慢慢努力的小刘,时隔七天终于更新了。今天分享的内容是:用代码实现二分法/牛顿迭代法求一元非线性方程求根。如果对大家有帮助,请大家动动小手点个赞或关注吧。

问题描述:

选择合适的初始有根区间或者初值,分别用二分法和牛顿迭代法求出一元非线性方程 的全部实根,其中精度ε=10-4

理论基础:

拿二分法/牛顿迭代法的思想是什么呢?二分法的基本思想是:通过逐步缩小隔根区间的长度,求出根的近似值。二分法只能求实根,不能求复根及偶重根。迭代法的基本思想是:建立一个迭代序列来逼近根。迭代效果(指迭代的敛散性、收敛的速度)与迭代初值、迭代公式的收敛性有关。迭代初始值一般根据高等数学的知识或作图的方法来确定;迭代公式通过对已知方程的某种变换得到。

解决问题:

数值法求非线性方程的跟一般分三步:

  • 判定根的存在性;
  • 确定根的分布范围,找出隔根区间;
  • 根的精确化,在隔根区间内找出满足精度要求的根的近似值。

确定根的范围:

利用Visual Studio 2010(2019版本都一样)中的MFC或者MATLAB来画出方程图,我这里是用 Visual Studio 2010中的MFC画图的,下面是详细步骤:

步骤①〔创建项目〕:打开Visual Studio 2010,选择“文件”-“新建”-“项目”-“Visual C++”-“MFC”-“MFC应用程序”;输入项目名称“Exp1”。

点击“确定”按钮,得到:

点击左边的“应用程序类型”,在右边的应用程序类型选择“单个文档”

点击“完成”,得到一个项目“Exp1”。

步骤②〔创建自定义函数〕:选择“类试图”面板,如下图(左)所示。右键点击“CExp1View”结点,选择“添加”,如下图(右)所示。

在“添加”窗口选择“添加函数”,输入返回类型“void”,函数名“drawCure”。在参数定义部分,输入参数类型“int”,参数名“N”,点击“添件”按钮;再输入参数类型“CDC*”,参数名“pDC”,点击“添加”,完成函数定义。

上述操作将在项目中添件函数“drawCure”的声明与定义。

注意在类的头部引入 math.h:

#include <math.h>

完整的drawCure函数内容如下:

void CEXp1View::drawCure(int N, CDC* pDC)

{

pDC->TextOutW(250,10,_T("非线性函数 f(x)=x^3-sin(x)-4x+1"));//文本输出

//设置画笔,将影响画线的样式

CPen *pnewPen,*poldPen;

pnewPen=new CPen();

pnewPen->CreatePen(PS_SOLID,3,RGB(0,0,0));

poldPen=pDC->SelectObject(pnewPen);

//画坐标系

pDC->MoveTo(0,384);    pDC->LineTo(1366,384);//x轴

pDC->MoveTo(683,0);    pDC->LineTo(683,768);//Y轴

//画刻度

1   int Ex =50, Ey =50;//坐标放大倍数

CString str;  //输出刻度值用

for (int i=-8;i<=8;i++){

int xx = i*Ex+683;

pDC->MoveTo(xx,384-4);

pDC->LineTo(xx,384);

str.Format(_T("%d"),i);

pDC->TextOutW(xx,384+4,str);

}

for (int i=-6;i<=6;i++){

if (i==0){

continue;     //原点已经标定

}

int yy = -i*Ey+384;

pDC->MoveTo(683,yy);

pDC->LineTo(683+4,yy);

str.Format(_T("%d"),i);

pDC->TextOutW(683-20,yy,str);

}

//画曲线,先移动到本曲线的第一个点

//原始坐标

float x1 = -4;

float y1 = x1*x1*x1-sin(x1)-4*x1+1;

//放大

x1 = x1*Ex;

y1 = -y1*Ey;

//取整

int xx1 = (int)(x1+683);

int yy1 = (int)(y1+384);

//移动到第一个点

pDC->MoveTo(xx1,yy1);

for(int i=0;i<=N;i++){

//原始坐标

float x0=-4+8.0/N*i;

float y0= x0*x0*x0-sin(x0)-4*x0+1 ;

//坐标放大

x0=x0*Ex;

y0=-y0*Ey;

//坐标转化为整型

int x1=(int)(x0+683);

int y1=(int)(y0+384);

pDC->LineTo(x1,y1);

}

//重置画笔

pDC->SelectObject(poldPen);

}

在“CExp1View”类的“OnDraw(CDC* pDC)”函数中加入代码〔注意修改输入参数,去掉注释〕:

点击下图中的三角形,运行项目

运行结果:

由此得到三个隔根区间:(-3,-2)、(0,0.5)和(1.5,2.5)

二份法的代码:

头文件的内容(VS2019):

#pragma once
#include<iostream>
#include<math.h>
#include<iomanip>
using namespace std;
class bnary
{
public:bnary(double a,double b);~bnary();int sign(double s);//判断函数值的正负;double reustbnary(double left, double right,double(*p)(double));//方法代码块void show(double left, double right, int c, double d, int count);//c是传入sign函数的返回值,d是区间的中点值;void show2(double a, double b);private:double a;double b;
};

cpp文件:

#include"ErFen.h"
double e=pow(10,-4);
bnary::bnary(double a,double b)
{this->a = a;this->b = b;
}
bnary::~bnary()
{}
double Fx(double x)
{return x * x * x - sin(x) - 4 * x + 1;
}
int bnary::sign(double s)
{if (s > 0){return 1;//代表符号为'+'}else if (s < 0){return -1;//符号维‘-’;}else{return 0;}
}void bnary::show(double left, double right, int c, double d,int count)
{cout << setiosflags(ios::fixed) << setprecision(6) << endl;cout<<setw(5) <<count<<setw(23) << left << setw(15) << right << setw(12) << d << setw(6) << c << setw(18) << fabs(left - right)/2<<endl;//cout << setw(5)<< count <<setw(23)<<left<<setw(14)<<right<<setw(6)<<d<<setw(6)<<c<<setw(18)<< fabs(left - right)/2<< endl;
}
double bnary::reustbnary(double left, double right,double(*p)(double))
{int c;//储存函数符号的返回值;double mid;//区间的中点值;mid = (left + right) / 2;int count = 0;c = sign(Fx(mid));//计算中点的正负;while (1)//非递归{mid = (left + right) / 2;c = sign(Fx(mid));//计算中点的正负;if (c == sign(Fx(left))){count++;this->show(left, right, c, mid,count);left = mid;}else{count++;this->show(left, right, c, mid,count);right = mid;}if (fabs(right - left)< e){return mid;}}//if (fabs(left - right)< e)//递归 //{// //this->show(left, right, c, mid);// return mid;//}//if (c == sign(result(left)))//符号与区间左端点一样;//{//    this->show(left,right,c,mid);//  return reustbnary(mid, right);//}//if (c == sign(result(right)))//{// this->show(left, right, c, mid);//   return reustbnary(left,mid);//}
}
void bnary::show2(double a, double b)
{cout << "初始区间为:[" << a << "," << b << "]" << endl;cout << setiosflags(ios::fixed) << setprecision(6) << endl;cout << "f(a)=" << Fx(a) << setw(10) << "f(b)=" << Fx(b)<< endl << endl;cout << "二分的次数" << setw(16) << "[a,b]-a" << setw(16) << "[a,b]-b" << setw(10) << "mid" << setw(12) << "f(x)+/-" << setw(15) << "1/2|b-a|" << endl;
}
int main()
{bnary A(-3.0, -2.0), B(0.0, 1.0), C(1.0, 2.0);cout << "二分法求根结果如下:" << endl;A.show2(-3.0, -2.0);double s;s= A.reustbnary(-3.0, -2.0, Fx);cout << "the root is:" << setw(12) << s << endl << endl << endl;B.show2(0.0, 1.0);s = B.reustbnary(0.0, 1.0,Fx);cout << "the root is:" << setw(12) << s << endl << endl << endl;C.show2(1.0, 2.0);s=C.reustbnary(1.0, 2.0,Fx);cout << "the root is:" << setw(12) << s << endl << endl << endl;return 0;
}

牛顿迭代法的代码:

头文件:

#pragma once
#include<iostream>
#include<math.h>
#include<iomanip>
using namespace std;
double e = pow(10, -4);
class NiuDon
{
public:NiuDon(double a);double result(double x, double(*p)(double));~NiuDon();private:double a;
};

cpp代码:

#include"NewTon.h"
NiuDon::NiuDon(double x)
{this->a = x;
}NiuDon::~NiuDon()
{}
double Fx(double x)
{return (pow(x, 3) - sin(x) - 4 * x + 1) / (3 * pow(x, 2) - cos(x) - 4);
}
double NiuDon::result(double x,double(*p)(double))
{int count = 0;double x1, x2 = 0.0;x1 = x;while (1){count++;double c = 3 * pow(x1, 2) - cos(x) - 4;if (c != 0){double d = Fx(x1);x2 = x1 - d;if (fabs(x2 - x1) < e){cout << setiosflags(ios::fixed) << setprecision(6) << endl;cout<<"第"<<count<<"次迭代"<<setw(12) << x2 << setw(16) << "|x2-x1|=" << fabs(x2 - x1) << endl;return x2;break;}else{cout << setiosflags(ios::fixed) << setprecision(6) << endl;cout << "第" << count << "次迭代" << setw(12) << x2 << setw(16) << "|x2-x1|=" << fabs(x2 - x1) << endl;x1 = x2;x2 = 0.0;}}else{cout << "x1=" << x1 << "的值歧异" << endl;break;}}
}
int main()
{NiuDon A(-2.5), B(0.5), C(1.5);double s = 0.0;cout <<"迭代次数"<<setw(15) << "迭代初值:"<< setw(16) << "|x2-x1|" << endl;s = A.result(-2.5,Fx);cout << "root=" << s << endl << endl;cout << "迭代次数" << setw(15) << "迭代初值:"<< setw(16) << "|x2-x1|" << endl;s = B.result(0.5, Fx);cout << "root=" << s << endl << endl;cout << "迭代次数"<< setw(15) << "迭代初值:"<< setw(16) << "|x2-x1|" << endl;s = C.result(1.5, Fx);cout << "root" << s << endl;return 0;
}

总结:

书山有路勤为径,学海无涯苦作舟。大家一起加油!

一元非线性方程求根的算法——二分法/牛顿迭代法相关推荐

  1. 数值分析(7)-非线性方程求根

    7 非线性方程求根 文章目录 7 非线性方程求根 7.1 二分法 4.2 简单迭代法 4.2.1 一般形式 4.2.2 收敛条件 4.2.3 收敛阶 4.3 Newton迭代法 4.3.1 迭代格式 ...

  2. 【算法】牛顿迭代法求平方根的原理和误差分析

    前言 在<算法(第四版)>中的P23页,给出了经典的利用牛顿迭代法求平方根的算法,牛顿迭代法在数值计算中应用十分广泛,但是在看书中的代码时,我最困惑的是其中对收敛条件的判断,经过查阅资料和 ...

  3. 数值计算大作业:非线性方程求根(二分法、牛顿法、弦截法在Matlab实现)

    作为研究生的入门课,数值计算的大作业算是所有研究生开学的重要编程作业. 我把二分法.牛顿法.弦截法求解非线性方程求根的数值计算作业在MATLAB中编程实现.具体的程序详细标注后放在文章附录了,算法数学 ...

  4. matlab 一元方程程序,用牛顿方法解一元非线性方程的根(Matlab实现)

    题目:用牛顿法求方程x-cos(x)=0的实根(精确到1E-6). (1)要求用函数调用. (2)进一步研究和弦截法作比较. 算法分析: (1)       此题是利用牛顿方法解一元非线性方程的根.( ...

  5. 【Python】Python用牛顿迭代法求方程2x3-4x2+3x-6=0在1.5附近的根。提示:牛顿迭代法求非线性方程的根的迭代公式为x`(n+1)`=x`n`-f(x)/f'(x) 。

    用牛顿迭代法求方程2x3-4x2+3x-6=0在1.5附近的根.提示:牛顿迭代法求非线性方程的根的迭代公式为x(n+1)=xn-f(x)/f'(x) . 算法源码 def f(x): ##原函数ret ...

  6. 工程数学(数值分析)第二讲:非线性方程求根

    文章目录 第二讲:非线性方程求根 二分法 简单迭代法 收敛阶 牛顿迭代法 第二讲:非线性方程求根 二分法 简单迭代法 收敛阶 牛顿迭代法

  7. 计算物理学(数值分析)上机实验答案6、非线性方程求根

    实验六.非线性方程求根 ​ 在科学研究与工程技术中常会遇到求解非线性方程的问题.二分法简单易行, 但收敛较慢,仅有线性收敛速度.而且该方法不能用于求偶数重根或复根,但可 以用来确定迭代法的初始值.牛顿 ...

  8. 数值分析方程求根实验matlab,基于matlab的数值分析( 非线性方程求根)上机实验报告1...

    数值分析试验报告 非线性方程求根 二分法解方程 1. 题目:用二分法求方程0133 =--x x 的所有根 2. 方法:二分法 3. 程序 function x=erfenfa(a,b) if (a* ...

  9. 2021-01-07 matlab数值分析 非线性方程求根 牛顿法

    matlab数值分析 非线性方程求根 牛顿法 %牛顿法求非线性方程的根: % 输入:fun--非线性函数:dfun--非线性函数导数:x0--初始值:tol--精度: % 输出:x--非线性方程数值根 ...

  10. 一元二次方程求根计算机的代码,一元二次方程求根Java源程序代码.doc

    一元二次方程求根Java源程序代码.doc (3页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 //求解一元二次方程ax^2+bx+c= ...

最新文章

  1. DevExpress GridControl使用(二)
  2. C# 往excel出力数据
  3. boost::graph_as_tree用法的测试程序
  4. 《3D数学基础》实践1 向量类代码分析
  5. 软件测试入门随笔——软件测试基础知识(一)
  6. 玩转动态编译 - 高级篇:三,实例属性的读取与设置
  7. SQL 实战教程(八)
  8. 真甲先生 38期:2019年百度快排×××?
  9. BottomBar之Android底部菜单
  10. vc++6.0 下实现的 立体四子棋 程序 (原型来源于北京科技馆)
  11. 关于云优CMS系统模板标签调用列表随机显示的代码rand()标签适用
  12. 把音频中的某个人声去掉_如何把音乐文件里的人声去掉只保留伴奏
  13. pom.xml报错找不到jar-解决
  14. NLP入门干货:手把手教你3种中文规则分词方法
  15. 罗尔定理、拉格朗日中值定理和柯西中值定理和用他们证明不等式、
  16. 人脸识别智能服务器,智能化人脸识别服务器
  17. Activity标签设置
  18. Python数据分析入门笔记4——数据预处理之重复值
  19. 95后不喝领导敬酒被打脸,看透6个底层逻辑,你就懂酒文化结局
  20. 农村家庭暴力有什么应对的措施

热门文章

  1. 大数据可视化学期总结
  2. 职场泥潭 | 这样的IT公司绝对不宜久留
  3. html img标签alt属性吗,img标签可以不用alt属性吗
  4. html中img的title属性值,img标签中alt属性和title属性的区别是什么?
  5. Python实战 | 使用代理IP刷CSDN博客访问量
  6. 美国计算机游戏设计大学排名,USNews美国大学游戏设计专业排名
  7. 吴恩达机器学习系列课程笔记——第一章:什么是机器学习(Machine Learning)
  8. 戴尔笔记本win10系统迁移到新固态硬盘
  9. ***YZJ的牛肉干***
  10. 运放输入偏置电流方向_测试运算放大器的输入偏置电流