Java練習:牛頓迭代法 Vs. 不動點
阿新 • • 發佈:2019-01-10
SICP中,說明了功能抽象的一種型別:一般化函式的設計。通用函式在通常的Java/C語言的教學中,通常放在後面作為高階內容。如在講解C的函式指標、Java的模板方法模式的時候。
1.求平方根
牛頓的逐步逼近方法是通用的方法。例如,求一個數n的平方根,先給出一個猜測值x(如初始化為1或n),如果n- x* x不滿足精度(設定精度引數),按照某個規則例如x =( x + n/ x)/2再猜測,直到滿足精度。
滿足精度的條件 Math.abs(x*x-n ) >epsilon,對於很小的數,精度不夠因而不能計算出正確的答案;對於特別大的數,因為小數精度不足以表示兩個大數之間的差,所以sqrt 會陷入死迴圈。這些我們現在不予理會。 求一個數n的平方根,即求f(x) = x2-n =0的解。而任意的f(x)可以使用泰勒級數表示。 牛頓迭代法就是利用了泰勒公式的前兩項和,是泰勒公式的簡化。 xn+1= xn−f(xn) /f′(xn)package semantics.statement; import static tips.Print.*; /** * 牛頓迭代逼近法 * * @author (yqj2065) * @version (2016.6) */ public class NewtonMethod{ static double epsilon = 1e-15;// relative error tolerance public static double sqrt(double n) { double x = 1.0;//x不能夠為0,下面x作為分母;修改為while語句,則可以令 x = n; do{ x = (x + n/x)/2.0;// }while( Math.abs(x*x-n ) >epsilon); return x; } public static void test(double x){ pln("sqrt("+x +")="+sqrt(x) ); } }
- 按照簡化的泰勒公式,對於f(x) = x2-n,xn+1=xn−( xn2-n)
/2xn=( xn2+n)
/2xn 因此猜測值的變化規則為
x = (x + n/x)/2.0;
- 牛頓逼近法與數列/級數求和的關係?任意的f(x)可以使用泰勒級數表示,兩者本質上一致。但是在不方便採用item與sum的方式計算時,簡化的牛頓迭代法容易獲得猜測值的變化規則,也容易比較f(x)>精度.
public static double cube_root(double n) { double x = n;// while (Math.abs(x*x*x-n ) >epsilon) { x = (2*x + n/(x*x))/3.0;//pln(x); } return x; }
2.求方程的解
牛頓逼近法可以用於求方程的解。一個數n的平方根,其實是方程 x2-n=0的正數解(而且n被引數化)。假設求f(x) = x3-2x-3的某個根(注意,它可能有3個實根,我們沒有指定求1和2之間的根)。 public static double f1() {
double x = 0;//
while (Math.abs(x*x*x-2*x-3 ) >epsilon) {
x = (2*x*x*x + 3)/(3*x*x-2);//pln(x);
}
return x;
}
3.不動點
不動點是指對於函式f(x),若f(n)=n。既然f(n)=n,自然有n=f(n)=f(f(n))=f(f(f(f(n))))... 那麼方程f(x)=0的解,也就是f(x)+x=x的解,或者說f(x)+x的不動點。 很容易寫出: public static double getFixedPoint(DoubleUnaryOperator duo){
double x = 1.0;//
while (Math.abs(x-duo.applyAsDouble(x) ) >epsilon) {
x = duo.applyAsDouble(x);//pln(x);
}
return x;
}
雖然yqj2065覺得Java的高階函式是人妖,但是看起來像女人,那就是女人。
pln(getFixedPoint(y->Math.cos(y))); 0.7390893414033927pln(getFixedPoint(y->Math.sin(y)+Math.cos(y))); 1.2587228743052672
public static void test(double x){
pln("sqrt("+x +")="+sqrt(x) );
pln(getFixedPoint(y->(y+x/y)/2.0 ));
}
sqrt(9.0)=3.0000000013969843.000000001396984
關於收斂問題,那是數學問題,yqj2065搞不定! 無意中看見了老早的文章:Java語言學校的危險性 “如果真是這樣,課程6.001就是你的完美選擇。你可以先講Scheme語言,這種教學語言簡單到聰明學生大約只用10分鐘,就能全部學會。然後,你將這個學期剩下的時間,都用來講解不動點。”
我們敢不敢說:用10分鐘講一下不動點,然後,你將這個學期剩下的時間,都用來講解Java API程式設計。”