先看一下斐波那契數列
這個很容易理解,就是當前的值等於前兩個值的和
斐波那契法的遞歸結構如下
步驟一:我們首先要知道需要精確到的區間長度,例如要在[1, 10]之間搜索極小值點,希望精確到0.5之間,那麼也就是我最後要求得的Ln的長度要小於等於0.5。所以這個時候就能知道經過幾輪計算可以達到這個精度,斐波那契數列指的是:Fn=F(n-1)+F(n-2)。上圖可知Ln與Fn是有關係的,所以可以求得滿足Ln小於等於0.5的Fn,也就知道了可以迭代幾輪。
步驟二:求出L2,L2=L1*F(n-1)/F(n),這個式子可以由上圖得到,就是要確定最開始的t1、t2點,然後比較t1、t2點對應的函數值得大小,縮小區間,縮小區間的方法跟通用方法一致,如果t1的函數值f1大於t2的函數值f2,那麼區間縮小爲[t1, 10],否則區間縮小爲[1, t2]
步驟三:如果區間縮小爲[t1, 10],這個時候t1=t2,而t2的值等於t1在這個區間內的對稱值。其實我們可以看到只有第一步需要計算兩個點的函數值,其他步都只要計算一個點的函數值就行,因爲另外一個點的函數值由上一步遺留下來
代碼實現如下
- private static void fibonacci(float start, float end, float eps) {
- float Fn_1, Fn;
- int n;
- float L1 = end - start;
- float Ln = eps;
- n = 2;
- Fn = F(n);
- //求要經過幾輪區間長度纔可以小於eps
- while(Fn <= L1 / Ln) {
- n ++;
- Fn = F(n);
- }
- Fn_1 = F(n - 1);
- float t1, t2, f1, f2;
- float a = Math.min(start, end);
- float b = Math.max(start, end);
- t1 = b - (b - a) * Fn_1 / Fn;
- t2 = a + b - t1;
- f1 = fun(t1);
- f2 = fun(t2);
- while(b - a >= Ln) {
- if(f2 < f1) {
- a = t1;
- t1 = t2;
- t2 = a + b - t1;
- f1 = f2;
- f2 = fun(t2);
- } else {
- b = t2;
- t2 = t1;
- t1 = a + b - t2;
- f2 = f1;
- f1 = fun(t1);
- }
- }
- System.out.println((b + a) / 2);
- }
- private static float F(int n) {
- if(n == 0 || n == 1) return 1;
- return F(n - 1) + F(n - 2);
- }
- private static float fun(float x) {
- return (float) Math.sin(x);
- }