黄金分割法编程,黄金分割法程序代码
00-1010 1.概述2。黄金分割法3。改进的黄金分割算法4。编程实现改进的黄金分割算法。
00-1010黄金分割法是一种区间收缩法。
所谓区间收缩法,是指逐渐缩小包含最优解的区间,直至区间长度为零的方法。例如,为了找到函数f(x)在区间[a,b]中的最小点,可以在这个区间中选择两个点x1,x2。通过比较函数f(x)在这两点上的函数值或导数值,决定去掉区间[a,x1]或[x2,b]的一部分,使搜索区间的长度变小,以此类推,直到区间收缩到一点。
对于区间[a,b]中的单峰函数f(x),可以任意选取两个点x1,x2。通过比较这两点的函数值,可以缩小搜索区间。例如,如果f(x1 )f(x2),选择[a1,b1 ]=[a,x2];如果f(x1) f(x2),选择[a1,b1 ]=[x1,b];如果f(x1 )=f(x2),选择[a1,x2]
所以对于预先给定的某个精度,当
,f(x)的最小点可以近似地取为
单峰函数和搜索区间的定义如下:
如何选择x1和x2使算法更高效?
这里不详细讨论推导过程,直接给出满足对称点选取、等比例收缩、单点计算三个原则的点。
或者
00-1010算法描述如下:
这个算法非常理想。在整个迭代过程中。除了初始计算点所用的乘法,后续所有的点都用加法和减法完成,每次迭代只需要计算一个点的函数值。然而,在实际应用中,这种方法存在一些缺陷。这个缺陷主要来自于无理数(-1 5)/2的值。我们在这里只取了小数点后的三位数。所以存在一定的误差,所以在迭代过程中,经过多次积累,误差会非常大,导致最终选取的两点不一定是我们预期的两点。事实上,经常会出现x2小于x1的情况。
要避免这种情况,我们也可以通过增加无理数小数点后的位数(-1 5)/2来避免算法的这种缺陷。但是,这样做的效果可能不会很好。因为我们不知道算法中需要多少次迭代,当迭代次数很大的时候,这个方法还是行不通。所以我们每次在程序中计算点的时候,都要根据算法原理使用乘法,也就是直接用乘法而不是加减法计算第二个点。因此,可以避免由累积误差引起的缺陷。我们仍然假设f(x)是区间[a,b]上的单峰函数。修正黄金分割法的计算框图如下图所示。
目录
修正的黄金分割算法如下:
00-1010用黄金分割法求函数f (x)=x-12x-11在区间[0,10]的极小点,取=0.01。
导入Java . math . bigdecimal;/* * *黄金分割测试*/公共类黄金分割{公共静态最终bigdecimal c=new bigdecimal( 0.01 );public static BigDecimal end=null;/* * * x 3-12x-11 * @ param x输入参数x * @ return x 3-12x-11 */public static bigdecimal computefx(bigdecimal x){ return x . pow(3)。subtract(新的BigDecimal(12 )。乘以(x))。减法(新的BigDecimal(11 ))。setScale(10,BigDecimal。ROUND _ HALF _偶数);} /** * a 0
.382*(b-a) * @param a * @param b * @return a+0.382*(b-a) */ public static BigDecimal Compute382(BigDecimal a,BigDecimal b){ return a.add(new BigDecimal("0.382").multiply(b.subtract(a))) .setScale(10,BigDecimal.ROUND_HALF_EVEN); } /** * a+0.618(b-a) * @param a * @param b * @return */ public static BigDecimal Compute618(BigDecimal a,BigDecimal b){ return a.add(new BigDecimal("0.618").multiply(b.subtract(a))) .setScale(10,BigDecimal.ROUND_HALF_EVEN); } /** * a+b-x1 * @param a * @param b * @param x1 * @return */ public static BigDecimal Subtractabx1(BigDecimal a,BigDecimal b,BigDecimal x1){ return a.add(b).subtract(x1) .setScale(10,BigDecimal.ROUND_HALF_EVEN); } //判断是否满足精度 b-a<C? public static boolean OK(BigDecimal a,BigDecimal b){ return b.subtract(a).compareTo(C) < 0; } //输出最优解 public static BigDecimal Success(BigDecimal a, BigDecimal b){ return (a.add(b)).divide(new BigDecimal("2")) .setScale(10,BigDecimal.ROUND_HALF_EVEN); } //修改后的黄金分割法 public static void goldenTest1(BigDecimal a,BigDecimal b){ System.out.println("初始化"); BigDecimal x1=Compute382(a,b); BigDecimal x2=Subtractabx1(a,b,x1); BigDecimal f1=ComputeFx(x1); BigDecimal f2=ComputeFx(x2); System.out.println("x1="+x1); System.out.println("x2="+x2); System.out.println("f1="+f1); System.out.println("f2="+f2); System.out.println("迭代区间如下:"); int count=0; //迭代次数 while(!OK(a,b)){//只要不满足精度就一直迭代 System.out.println("["+a+"t,t"+b+"]"); count++; //迭代次数+1 if(f1.compareTo(f2)==1){//f1>f2 a=x1; if(OK(a,b)){ //精度判断 end = Success(a, b); break; }else{ f1=f2; x1=x2; x2=Compute618(a,b); f2=ComputeFx(x2); } }else{ b=x2; if(OK(a,b)){ end = Success(a, b); break; }else{ f2=f1; x2=x1; x1=Compute382(a,b); f1=ComputeFx(x1); } } } System.out.println("迭代结束,迭代次数"+count); } public static void main(String[] args) { BigDecimal a=new BigDecimal("0"); BigDecimal b=new BigDecimal("10"); goldenTest1(a,b); System.out.println("最优解为x*="+end); System.out.println("f(x*)="+ComputeFx(end)); }}
由运行结果可以看到,迭代次数15次,最优解为x*=2.0009942948,f(x*)=-26.9999940673。迭代区间如下:
可以证明,黄金分割法是线性收敛的。
到此这篇关于Java实现黄金分割法的示例代码的文章就介绍到这了,更多相关Java黄金分割法内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。