问题描述:
给定函数,设计fibnacci算法,进退算法分别求在区间[0,3]上的极小值区间,要求区间长度不大于原始区间的
Fibnacci算法:
算法设计:
给定区间以及精度,函数
①预处理出一定数量的斐波那契数列,然后根据求解区间和求解精度得到计算次数n。因为我们设定间隔两个单位区间长度的时候结束,所以
②令
③判断是否小于等于,如果是,则结束计算,得到结果区间,否则比较和
的大小,若,跳到④,否则跳到⑤。
④令.跳到③
⑤令.跳到③
代码实现:
#include<bits/stdc++.h>
using namespace std;
int fib[40];
double f(double x){
return x*(x-1)+2;
}
void init(){
fib[0] = 1; fib[1] = 1; for(int i = 2; i < 40; ++i) fib[i] = fib[i-1] + fib[i-2];
}
void sol(double l, double r, double eps){
int s = 2*(r-l)/eps+1;
int n = 0;
while(fib[n+1] <= s) ++n;//获取迭代次数
double lmid = r - (double)fib[n]/fib[n+1] * (r-l);
double rmid = l + (double)fib[n]/fib[n+1] * (r-l);
int ca = 0;
while(r-l > eps){
cout<<setprecision(4)<<fixed<<"test"<<++ca<<": l = "<<l<<" r = "<<r<<" lmid = "<<lmid<<" rmid:"<<rmid;
cout<<" f(lmid) = "<<f(lmid)<<" f(rmid) = "<<f(rmid)<<endl<<endl;
if(f(lmid) > f(rmid)){
l = lmid;
lmid = rmid;
rmid = l + r - lmid;
}
else{
r = rmid;
rmid = lmid;
lmid = l + r - rmid;
}
}
cout<<"\n result : \nl:"<<l<<" r:"<<r<<endl;
}
int main()
{
init();
double l, r;cout<<"输入搜索区间:"; cin>>l>>r;
sol(l, r, (r-l)*0.09);
}
进退法:
ps: 这里写的进退法经过修改,在找到单峰但是不满足精度的时候通过减少步长来继续下降。不知道还算不算进退法:D
算法设计:
给定初始点,精度和函数,初始步长
①先确定很小的步数,比较和来确定下降方向,若,令,若,令,否则可确定为满足条件的区间,结束算法。
②令.如果,转③,否则如果,已经找到满足条件单峰区间,结束算法。如果,转④
③令。转②
④令。转②
代码实现:
#include<bits/stdc++.h>
using namespace std;
double f(double x){
return x*(x-1)+2;
}
void sol(double x0, double eps, double h0){
double dx = eps/100;
double x1, x2;
if(f(x0) < f(x0 + dx) && f(x0) < f(x0 - dx)) {
cout<<"结果区间为:["<<x0-dx<<","<<x0+dx<<"]\n";return;
}
else if(f(x0) > f(x0 + dx)) dx = h0;
else dx = -h0;
int num = 0;
while(1){
num++;
x1 = x0 + dx; x2 = x1 + dx;
cout<<setprecision(3)<<fixed<<"x0 = "<<x0<<"\tx1 = "<<x1<<"\tx2 = "<<x2;
cout<<"\tf(x0) = "<<f(x0)<<"\tf(x1) = "<<f(x1)<<"\tf(x2) = "<<f(x2)<<endl;
if(f(x0) > f(x1) && f(x1) > f(x2)){
x0 = x1;
dx = dx*2.0;
continue;
}
else{
if(abs(x2-x0) > eps){
dx = dx/2.0;
}
else{
cout<<"迭代次数:"<<num<<endl;
cout<<"结果区间为:["<<min(x0,x2)<<","<<max(x0, x2)<<"]\n";return;
}
}
}
}
int main()
{
double x0, e, h0;
cout<<"输入初始点:";cin>>x0;
cout<<"输入需求区间精度:";cin>>e;
cout<<"输入初始步长:";cin>>h0;
sol(x0, e, 0.1);
}