2010年1月24日 星期日

牛頓法(Newton-Raphson)尋根

在金融領域裡,我們經常需要求得某線性方程式的根

要求得一條方程式 f(x) = 0 的根時,其實有很多種解法

但是當這條方程式為非線性時,就沒有辦法使用簡單的推導求得

這時候我們即可使用牛頓法來求解

牛頓法的詳細說明請參考維基百科,其中述及該方法需要使用一階微分迭代近似

在此我實作了 NewtonRaphson 這個虛擬類別,建構其處理流程

並在這個虛擬類別中實作了 Derivative 這個函式,以推估該方程式的一階微分,

其理論源自於微分使用極限值(limit)逼近

當要求一個方程式的根時,我們只要繼承這個類別並實作 F 這個函式即可計算出其解。


class Program
{
static void Main(string[] args)
{
NewtonRaphson n = new CosRoot();
NewtonRaphson s = new SquareRoot();
int counter;
double result = n.GetRoot(0.5, out counter);
Console.WriteLine("{0} its root is {1}. {2}", n.ToString(), result, counter);

result = s.GetRoot(1, out counter);
Console.WriteLine("{0} its root is {1}. {2}", s.ToString(), result, counter);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}

abstract class NewtonRaphson
{
private int iteratorCount;
public NewtonRaphson()
{
iteratorCount = 10000;
}

abstract protected double F(double x);

private double Derivative(double x){
double h = 0.0000001;
return (F(x + h) - F(x)) / h;
}

public double GetRoot(double initValue, out int counter)
{
double tmpValue = initValue;
counter = 0;
for (int i = 0; i < iteratorCount; i++)
{
initValue = initValue - F(initValue) / Derivative(initValue);
if (Math.Abs(initValue - tmpValue) <= 0.00000000001)
break;
tmpValue = initValue;
counter++;
}
return initValue;
}
}

class CosRoot : NewtonRaphson
{
protected override double F(double x)
{
return Math.Cos(x) - Math.Pow(x, 3);
}

public override string ToString()
{
return "Cos(x) - x^3";
}
}

class SquareRoot : NewtonRaphson
{
protected override double F(double x)
{
return x * x - 612;
}

public override string ToString()
{
return "x^2 - 612";
}
}

沒有留言:

張貼留言