牛頓迭代法 - 求解非線性方程根的近似解
在演算法中,牛頓迭代法主要用於求解非線性方程或最佳化問題。它是一種迭代演算法,透過不斷逼近來找到函式的根或者最小化/最大化某個目標函式。
這裡呢,我們重點講一下如何求解線性方程 \(F(X) = 0\) 近似根的大致步驟。
- 選擇一個初始猜測值\(x_0\):
- 這個初始猜測應該儘可能接近實際的根,一個好的初始猜測可以加速收斂過程,並且有助於避免演算法陷入區域性極小值或不收斂的情況。
- 定義迭代公式:
- 牛頓迭代法的迭代公式是:\(X_(n+1) = X_n - \frac{F(X_n)}{F^`(X_n)}\)
- 其中 \(F^`(X_n)\) 是函式 \(F(X)\) 在點 \(X_n\) 處的一階導數。
- 執行迭代過程:
- 使用上面的迭代公式。從$ X_0$ 開始計算 \(X_1, X_2, X_3, ...\) ,直到滿足停止條件。
- 設定停止條件:
- 停止條件通常有兩種形式:
- 當連續兩次迭代的結果足夠接近時,即 \(∣X_n+1 - X_n∣ < ϵ\) ,其中 ϵ 是預設的小正數。
- 或者當函式值足夠接近於零時,即 \(|F(X_(n+1))| < ϵ\) 。
- 有時還會設定最大迭代次數以防止無限迴圈。
- 停止條件通常有兩種形式:
- 檢查結果的有效性:
- 確認最終得到的 X 值確實是 \(F(X)=0\) 的根。如果函式在該點附近的行為複雜(如存在多個根或導數為零),可能需要進一步分析。
這裡以牛客的一道題來舉個例子:
計算一個浮點數的立方根而不使用庫函式
我們就可以使用牛頓迭代法來逼近結果。
對於求解X的立方根,我們需要找到滿足 \(Y^3 = X\) 的 \(Y\) , 這裡可以透過解方程 \(F(Y) = Y^3 - X = 0\) 來實現,牛頓迭代的公式為:
\(Y_(n+1) = Y_n - \frac{F(Y_n)}{F^`(Y_n)}\)
其中 \(F(Y) = Y^3 - X\) , 導數 \(F^`(Y) = 3Y^2\)
帶入後得到:
\(Y_(n+1) = Y_n - \frac{Y^3_n - X}{3Y_n^2}\)
下面是Java程式碼的實現:
public class Main {
public static void main(String[] args) {
double x = 27.0; // 求Math.sqrt(x)
double tolerance = 1e-10; // 允許的誤差
System.out.printf("%f\n",calculateCubeRoot(x, tolerance));
}
private static double calculateCubeRoot(double x, double tolerance) {
if (x == 0) return 0; // 特殊值處理
double y = x; // 猜測初始值
double diff; // 計算出來的誤差
do {
double nextY = y - (y * y * y - x)/(3 * y*y); // 迭代公式,計算出新的迭代值
diff = Math.abs(nextY - y); // 計算出新的迭代值與舊的迭代值之間的誤差
y = nextY; // 更新迭代後的值
} while (diff > tolerance);
return y; // 滿足誤差後跳出迴圈直接返回最終迭代後的結果
}
}
執行結果如下:
3.000000