二分法与黄金分割法求函数方程最小值
程序设计语言:C++
输入:线性搜索模型(目标函数系数,搜索区间,误差限等)
输出:最优解及对应目标函数值
实验数据
区间[0.3,1],误差ε=1e-4
结果
二分法最后结果为:导数在0.637009处取零点,函数在区间【0.3,1】取得最小值11.252754.
(二分法结果图)
黄金分割法最后结果为:输入初始值0.3,导数在0.636939处取零点,函数在区间【0.46,0.94】取得最小值11.252756.
(黄金分割法结果图)
两种方法所求无论是极小值点还是最小值点结果在所限制误差内基本一致,表明结果正确。
代码:
二分法:
#include <stdio.h>
#include <math.h>
double fun(double x)
{
return -2*(x-0.3)/ (((x-0.3)*(x-0.3) + 0.01)*((x-0.3)*(x-0.3) + 0.01) )- 2*(x-0.9)/ (((x-0.9)*(x-0.9) + 0.04)*((x-0.9)*(x-0.9) + 0.04));
}
double solve(double l, double r)
{
double t = fun((l + r) / 2.0);
while(fabs(t) >= 1e-4)
{
l = t < 0 ? (l + r) / 2.0 : l;
r = t > 0 ? (l + r) / 2.0 : r;
t = fun((l + r) / 2.0);
}
return (l + r) / 2.0;
}
int main(int argc, char *argv[])
{
printf("导数的零点为:%f\n", solve(0.3, 1));
//printf("%f\n", fun(0.637009));
float b=solve(0.3, 1);
printf("函数最小值为:%f \n",1 / (pow((b - 0.3), 2) + 0.01) + 1 / (pow((b - 0.9), 2) + 0.04) - 6);
return 0;
}
黄金分割法代码:
// 黄金分割法.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<windows.h>
#define e 0.001 /*收敛精度*/
#define tt 0.01 /*一维搜索步长*/
float function(float x) /*定义已知函数*/
{
float y=1 / (pow((x - 0.3), 2) + 0.01) + 1 / (pow((x - 0.9), 2) + 0.04) - 6;
return(y);
}
void finding(float a[4]) /*进退法求区间[a,b]*/
{
double h = tt; /*初始步长*/
float x0, x1, f1, x2, f2, x3, f3;
int i;
printf("输入一个初始值:");
scanf("%f", &x0);
x1 = x0, x2 = x1 + h;
f1 = function(x1), f2 = function(x2);
if (f1 == f2)
a[0] = x1, a[3] = x2;
else
{
if (f1>f2) /*作前进计算*/
{
x3 = x2 + h;
f3 = function(x3);
if (f3<f2) /*若满足条件,继续做前进计算*/
for (i = 0;; i++)
{
h = 2 * h;
x1 = x2, f1 = f2;
x2 = x3, f2 = f3;
x3 = x2 + h;
f3 = function(x3);
if (f2<f3) break; /*到此条件停止前进计算*/
}
}
else
{
x2 = x1 - h; /*作后退计算*/
f2 = function(x2);
x3 = x2 - h;
f3 = function(x3);
if (f3<f2) /*若满足条件,继续做后退计算*/
for (i = 0;; i++)
{
h = 2 * h;
x1 = x2, f1 = f2;
x2 = x3, f2 = f3;
x3 = x2 - h;
f3 = function(x3);
if (f2<f3) break; /*到此条件停止后退计算*/
}
}
}
if (x1<x3)
a[0] = x1, a[3] = x3; /*将所求区间值赋给a,b用以输出*/
else
a[0] = x3, a[3] = x1;
printf("所求搜索区间[a,b]=[%.2f,%.2f]\n", a[0], a[3]);
return;
}
float gold(float *ff) /*黄金分割法求解*/
{
float a1[3], f1[3], a[4], f[4];
float aa;
int i;
finding(a);
a[1] = a[0] + 0.382*(a[3] - a[0]), a[2] = a[0] + 0.618*(a[3] - a[0]);
f[0] = function(a[0]), f[1] = function(a[1]), f[2] = function(a[2]), f[3] = function(a[3]);
for (i = 1;; i++) /*计算迭代次数*/
{
if (f[1] >= f[2])
{
a[0] = a[1]; f[0] = f[1];
a[1] = a[2]; f[1] = f[2];
a[2] = a[0] + 0.618*(a[3] - a[0]); f[2] = function(a[2]);
}
else{
a[3] = a[2]; f[3] = f[2];
a[2] = a[1]; f[2] = f[1];
a[1] = a[0] + 0.382*(a[3] - a[0]); f[1] = function(a[1]);
}
if (a[3] - a[0]<e)
{
aa = (a[1] + a[2]) / 2;
*ff = function(aa);
printf("\n迭代次数n=%d\n", i);
break;
}
}
return(aa);
}
void main()
{
printf("**黄金分割法求函数极小值点**\n");
float xx, ff;
xx = gold(&ff);
printf("优化设计的结果是:\n");
printf("x*=%f\nf*=%f\n", xx, ff);
printf("**Bug Wang!**\n");
system("pause");
}
时间: 2024-11-08 23:40:25