二分法和if ... else ... end 语句

先回顾一下二分法。要求方程\(f(x)=0\)的根。假设\(c = f(a) < 0\)和\(d = f(b) > 0\),如果\(f(x)\)是连续函数,那么方程的根\(x^*\)一定位于\(a\)和\(b\)之间。然后,我们看一下\(a\)和\(b\)中点\(x=(a+b)/2\),计算函数值\(y=f(x)\),如果函数不为0,比较\(c\)、\(d\)和\(y\)的符号,确定新的二分区间。具体来说,如果\(c\)和\(y\)同号,新的二分区间就是\([x,b]\),如果\(c\)和\(y\)异号,新的二分区间就是\([a,x]\)。如图5.1所示。



图5.1 二分法

在不同的情况下做不同的事情,在程序里,这叫做流程控制。达到这个目的,最通常的方法是通过if ... else ... end语句来实现,这个语句是我们前面讲过的if ... end语句的扩展。

误差界

二分法的一个好处是,我们一直知道方程的真实的根\(x^*\)一定位于二分区间内,这样我们就可以知道最大误差可以是多少,一定小于区间大小的一半,即

\begin{equation*}
\mid x-x^* \mid \lt \frac{b-a}{2}
\end{equation*}

其中\(x=(a+b)/2\),为区间的中点。

二分法程序如下:

  1. function [x e] = mybisect (f,a,b,n)
  2. % function [x e] = mybisect (f,a,b,n)
  3. % Does n iterations of the bisection method for a function f
  4. % Inputs : f -- an inline function
  5. % a,b -- left and right edges of the interval
  6. % n -- the number of bisections to do.
  7. % Outputs : x -- the estimated solution of f(x) = 0
  8. % e -- an upper bound on the error
  9. format long
  10. % evaluate at the ends and make sure there is a sign change
  11. c = f(a); d = f(b);
  12. if c*d > 0.0
  13. error (’Function has same sign at both endpoints .’)
  14. end
  15. disp (’ x y’)
  16. for i = 1:n
  17. % find the middle and evaluate there
  18. x = (a + b )/2;
  19. y = f(x);
  20. disp ([ x y])
  21. if y == 0.0 % solved the equation exactly
  22. e = 0;
  23. break % jumps out of the for loop
  24. end
  25. % decide which half to keep , so that the signs at the ends differ
  26. if c*y < 0
  27. b=x;
  28. else
  29. a=x;
  30. end
  31. end
  32. % set the best estimate for x and the error bound
  33. x = (a + b )/2;
  34. e = (b-a )/2;

此程序不仅给出了方程的近似根,还给出了最大可能误差。

二分法总是可以进行下去,而牛顿法,如果初值\(x_0\)不足够接近\(x^*\)的话,程序可能不会收敛。而二分法,每一步的区间都可以缩一半,最终想缩多小就能缩多小。

找根

二分法和牛顿法都可以用来找根的任意近似值,但都需要先给定初值。二分法需要两个初值\(a\)和\(b\),并要求真实的根位于二者之间,牛顿法只需要一个初值\(x_0\),要求不能离真实的根太远。如何确定合适的初值?看情况而定。如果你一次只解一个方程,最好先把函数画出来,通过图上的函数零点,可以很容易定出合适的初值。

有些情况下你不是一次就解一个方程,而是多次求解同一个方程,只是系数不同。当你开发某特定用途的软件的时候,常常会遇到这种情况。在这种情况下,首先你要利用问题的自然条件,比如选定的区间要符号实际情况。然后通过区间内某些点的符号,很容易就可以逐渐接近方程的真实的根了。方程的根一定位于符号相异的两点之间。下面的程序就是在一给定的区间\([a_0,b_0]\)之间找方程的根:

  1. function [a,b] = myrootfind (f,a0 ,b0)
  2. % function [a,b] = myrootfind (f,a0 ,b0)
  3. % Looks for subintervals where the function changes sign
  4. % Inputs : f -- an inline function
  5. % a0 -- the left edge of the domain
  6. % b0 -- the right edge of the domain
  7. % Outputs : a -- an array , giving the left edges of subintervals
  8. % on which f changes sign
  9. % b -- an array , giving the right edges of the subintervals
  10. n = 1001; % number of test points to use
  11. a = []; % start empty array
  12. b = [];
  13. % split the interval into n -1 intervals and evaluate at the break points
  14. x = linspace (a0 ,b0 ,n);
  15. y = f(x);
  16. % loop through the intervals
  17. for i = 1:(n -1)
  18. if y(i)*y(i +1) < 0 % The sign changed , record it
  19. a = [a x(i)];
  20. b = [b x(i +1)];
  21. end
  22. end
  23. if size (a ,1) == 0
  24. warning (’no roots were found ’)
  25. end

如果没有任何已知信息来找方程的根,事情就比较难办,好在这种情况在工程问题里不常见。

一旦确定出根所在的区间\([a, b]\),\(a\)和\(b\)就可以作为二分法和割线法(见下一讲)的初值。对于牛顿法,初值\(x_0\)一个明显的选法是\(x_0 = (a + b)/2\)。一个更好的选法是利用割线法选\(x_0\)。

练习

1 修改程序mybisect,在给定公差下解方程。应用你的程序,求解方程\(f(x) = 2x^3 + 3x − 1=0\)的根,初始区间是\([0,1]\),公差为\(10^{-8}\)。程序需要运行多少步能达到公差的要求?最终残量有多大?

2 用纸和计算器对于函数\(f(x) = x^3 − 4\)和初始区间\([1,3]\)进行3步二分法迭代,计算每步结果的误差和相对误差,并与第3讲练习3的结果比较。

Todd's Matlab讲义第5讲:二分法和找根的更多相关文章

  1. Todd's Matlab讲义第4讲:控制误差和条件语句

    误差和残量 数值求解方程\(f(x)=0\)的根,有多种方法测算结果的近似程度.最直接的方法是计算误差.第\(n\)步迭代结果与真值\(x^\*\)的差即为第\(n\)步迭代的误差: \begin{e ...

  2. Todd's Matlab讲义第3讲:牛顿法和for循环

    方程数值求解 下面几讲,我们将聚集如下方程的解法: \begin{equation} f(x)=0 \tag{3.1}\label{3.1} \end{equation} 在微积分课程中,我们知道,许 ...

  3. Todd's Matlab讲义第2讲:Matlab 编程

    Matlab也可以编程,可存为以.m为后缀的文件,称为M文件.M文件有两种:函数和脚本. 函数程序 点击新建图标,在打开的窗口里输入如下内容: function y = myfunc (x) y = ...

  4. Todd's Matlab讲义第1讲:向量,函数和作图

    向量 Matlab 中最基本的对象是矩阵,向量是特殊的矩阵.行向量是\(1\times n\)矩阵,列向量是\(m\times 1\)矩阵.输入如下行向量: >> v=[0 1 2 3] ...

  5. Todd's Matlab讲义第6讲:割线法

    割线法 割线法求解方程\(f(x)=0\)的根需要两个接近真实根\(x^\*\)的初值\(x_0\)和\(x_1\),于是得到函数\(f(x)\)上两个点\((x_0,y_0=f(x_0))\)和\( ...

  6. 二分法和牛顿迭代实现开根号函数:OC的实现

    最近有人贴出BAT的面试题,题目链接. 就是实现系统的开根号的操作,并且要求一定的误差,其实这类题就是两种方法,二分法和牛顿迭代,现在用OC的方法实现如下: 第一:二分法实现 -(double)sqr ...

  7. Python实现二分法和黄金分割法

    运筹学课上,首先介绍了非线性规划算法中的无约束规划算法.二分法和黄金分割法是属于无约束规划算法的一维搜索法中的代表. 二分法:$$x_{1}^{(k+1)}=\frac{1}{2}(x_{R}^{(k ...

  8. Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法

    /** 题目:Flow construction SGU - 176 链接:https://vjudge.net/problem/SGU-176 题意: 有源汇有上下界的最小流. 给定n个点,m个管道 ...

  9. Matlab 之meshgrid, interp, griddata 用法和实例

    http://blog.sina.com.cn/s/blog_67f37e760101bu4e.html 实例结果http://wenku.baidu.com/link?url=SiGsFZIxuS1 ...

随机推荐

  1. pack、unpack自制二进制“数据库”

    引言 pack.unpack函数,如果没有接触过socket,这个可能会比较陌生,这两个函数在socket交互的作用是组包,将数据装进一个二进制字符串,和对二进制字符串中的数据进行解包,这个里面有好多 ...

  2. 使用uWSGI部署django项目

    先说说什么是uWSGI吧,他是实现了WSGI协议.uwsgi.http等协议的一个web服务器,那什么是WSGI呢? WSGI是一种Web服务器网关接口.它是一个Web服务器(如nginx)与应用服务 ...

  3. JS-制作可伸缩的水平菜单栏

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  4. json转换成对象

    在json转换成对象时,json的key会与java 类的字段一一对应.如果没有映射上的java字段会在该数据类型上填充默认值,如int 0,String null 等. 没有映射的json key在 ...

  5. nginx常用命令

    ps -ef | grep nginx在进程列表里面找master进程,它的编号就是主进程号了. 步骤2:发送信号 从容停止Nginx: kill -QUIT 主进程号 快速停止Nginx: kill ...

  6. Linux开放1521端口允许网络连接Oracle Listene

    症状:1. TCP/IP连接是通的.可以用ping 命令测试. 2. 服务器上Oracle Listener已经启动.  lsnrctl status  查看listener状态  lsnrctl s ...

  7. bootstrap panel 和table的使用

    一.HTML中的页面内容 <div class="col-sm-12"> <!-- <div class="m-b-md" style= ...

  8. 9月9日HTML上午表单元素2(框架、样式表)

    五.框架 1.frameset是双标签框架集,如果使用框架集,当前页面不能有body. frameset属性:①cols代表左右拆分.cols=“300,*”表示左边框架宽300,右边宽剩余的宽度.* ...

  9. 如何查看crontab的日志记录

    在Unix和类Unix的操作系统之中,crontab命令常用于设置周期性被执行的指令,也可以理解为设置定时任务. crontab中的定时任务有时候没有成功执行,什么原因呢?这时就需要去日志里去分析一下 ...

  10. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【外传】——Attribute Routing

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 题外话:由于这个技术点是新学的,并不属于原系列,但借助了原系列的项目背景,故命名外传系列,以后也可 ...