一维搜索:二分法

二分法是用来求函数零点的方法,如果函数可导,那么函数的一阶导的零点就是原函数的极值点。但是如果原函数没有极值点,比如一个单调函数,其最值在某一端点。这样求导后就不满足二分法求零点的条件。

1.二分法算法步骤:

  • (1) 初始化搜索区间 [x1,x2] [ x 1 , x 2 ] 均值 xm=0.5(x1+x2) x m = 0.5 ( x 1 + x 2 ) , 给定精度要求 ϵ>0 ϵ > 0 , 计算导数 f=dfdx f ′ = d f d x ;
  • (2) 如果 |x1x2|<ϵ | x 1 − x 2 | < ϵ 算法结束。如果 fx1×fxm>0 f x 1 ′ × f x m ′ > 0 , 转到步骤(3),如果 fx1×fxm<0 f x 1 ′ × f x m ′ < 0 ,转到步骤(4)。如果 fx1×fxm=0 f x 1 ′ × f x m ′ = 0 xm x m 即为结果,算法结束;
  • (3) 置 x1=xm x 1 = x m ,转步骤(5);
  • (4) 置 x2=xm x 2 = x m ,转步骤(5);
  • (5) 置 xm=0.5(x1+x2) x m = 0.5 ( x 1 + x 2 ) ,转步骤(2);

1.二分法代码MALTAB实现:
测试函数:

clc,clear
f = @(x) 2*x.^2 - x - 1; %原函数
df = @(x)4*x - 1;       %一阶导数
a = -3;
b = 0.25;
epsilon = 1e-4;
tic
res = binarySearch(df,a,b,epsilon)
toc
% 符号函数实现
func = sym('2*x^2 - x - 1');
tic
res1 = binarySearch1(func,a,b,epsilon)
toc

传函数句柄方式:

% binarySearch 二分法
%   - 优点:计算量少,而且总能收敛到一个局部极小点,不需要计算导数
%   - 缺点:收敛速度慢,需要函数可导
% Inputs:
%   - df      函数的一阶导数
%   - a       搜索区间下限
%   - b       搜索区间下限
%   - epsilon 精度:用区间长度衡量
% Outputs:
%   -res      搜索结果 
function res = binarySearch(df,a,b,epsilon)
% 检查输入
if df(a)*df(b) > 0 
    display('BinarySearch: 二分法区间端点值同号……'); 
    return; 
end
%初始化
x1 = a;
x2 = b;
mean = 0.5*(x1 + x2);
%计算
while(true)
%     state = [x1 x2]
    if(abs(x1-x2)<epsilon) break; end
    if(df(x1)*df(mean) > 0) 
        x1 = mean;
    elseif(df(x1)*df(mean) < 0)
        x2 = mean;
    elseif(df(x1)*df(mean) == 0)
        res = mean; break;
    end
    mean = 0.5*(x1 + x2);
end
res = 0.5*(x1 + x2);
end

传符号函数方式:

% binarySearch 二分法
%   - 优点:计算量少,而且总能收敛到一个局部极小点,不需要计算导数
%   - 缺点:收敛速度慢
% Inputs:
%   - func    原函数的符号函数
%   - a       搜索区间下限
%   - b       搜索区间下限
%   - epsilon 精度:用区间长度衡量
% Outputs:
%   -res      搜索结果 
function res = binarySearch1(func,a,b,epsilon)
df = diff(func);
% 检查输入
if subs(df,a)*subs(df,b) > 0 
    display('BinarySearch: 二分法区间端点值同号……'); 
    return; 
end
%初始化
x1 = a;
x2 = b;
mean = 0.5*(x1 + x2);
%计算
while(true)
%     state = [x1 x2]
    if(abs(x1-x2)<epsilon) break; end
    if(subs(df,x1)*subs(df,mean) > 0) 
        x1 = mean;
    elseif(subs(df,x1)*subs(df,mean) < 0)
        x2 = mean;
    elseif(subs(df,x1)*subs(df,mean) == 0)
        res = mean; break;
    end
    mean = 0.5*(x1 + x2);
end
res = 0.5*(x1 + x2);
end

结果如下图(函数句柄的方式比符号函数方式计算速度快很多):
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值