2016-06-20 6 views
1

Ich schreibe ein Programm, um die Wurzeln von Funktionen mit irrationalen Wurzeln numerisch durch verschiedene Methoden zu finden. Für Verfahren wie lineare Interpolation, müssen Sie hierfür den ungefähren Bereich, in dem eine Wurzel liegt, finden ich diesen Code geschrieben:Suche nach Wurzeln, aber nicht nach Asymptoten einer Funktion

bool fxn1 = false; 
bool fxn2 = false; 
vector<float> root_list; 

if(f_x(-100) < 0) 
{ 
    fxn2 = true; 
} 
for(float i = -99.99; i < 100.01; i += 0.01) 
{ 

    fxn1 = fxn2; 
    if(f_x(i) < 0) 
    { 
     fxn2 = true; 
    } 
    else 
    { 
     fxn2 = false; 
    } 
    if((fxn1 == false && fxn2 == true) || (fxn1 == true && fxn2 == false)) 
    { 
     root_list.push_back(i-0.01); 
     root_list.push_back(i); 
    } 
} 

jedoch für nicht-stetige Funktionen (dh Funktionen mit Asymptoten), das Code wird auch ausgelöst, wenn die Funktion von beiden Seiten der Asymptote von positiven zu negativen Werten wechselt. Gibt es eine Möglichkeit, das Programm den Unterschied zwischen einer Wurzel und einer Asymptote zu unterscheiden?

Dank im Voraus

+1

Das ist nicht wirklich ein Programmierproblem, sondern ein mathematisches Problem. Aber eine Asymptote hat die Eigenschaft, dass sie ins Unendliche abläuft, also wenn 'f_x (i) <0 ', dann sollten Sie' f_x (i + 0.005) haben f_x (i) '. – CompuChip

+0

Beachten Sie auch, dass Sie beide "if" -Anweisungen durch die kürzere ersetzen können: fxn2 = f_x (i) <0; if (fxn1! = fxn2) {...} ', ersetzt 9 Zeilen durch 2. – CompuChip

+0

Anstatt der Vorzeichen, sehen Sie sich einfach den absoluten Wert an und sehen Sie, ob er klein genug ist. –

Antwort

0

Wenn die Funktion, f(x), ist an einem Punkt innerhalb [a,b] konvergierenden dann der halben Strecke (a + b)/2 soll auf Null als a oder b näher.

Diese Beobachtung führt zu den folgenden Verfahren:

Let mid = (a + b)/2 
If |f(mid)| < |f(a)| AND |f(mid)| < |f(b)| Then 
    Algorithm has converged to a root 
Else 
    Algorithm has converged to an asymptote 
End 

In diesem Pseudocode |.| bezeichnet Gleitkommazahlen Absolutwert.

+1

Vorsicht, bei '1/x' und einem symmetrischen Intervall kann' f (mid) 'nicht existieren. Bereiten Sie sich darauf vor, Fehler durch Division durch Null zu behandeln. – CompuChip

+0

Sie machen einen guten Punkt, obwohl es nicht ungewöhnlich ist, dass ein Root-Finder die Funktion als Blackbox ausführt. Ich würde vorschlagen, eine Ausnahme zu werfen, wenn die Funktion an einem Punkt undefiniert ist und es entsprechend behandelt. –

+1

* Wenn die Funktion f (x) auf einen Punkt innerhalb von [a, b] konvergiert, sollte der Halb- punkt (a + b)/2 näher bei Null liegen als a oder b *. Das ist falsch. Dies gilt nur für * nice * -Funktionen, aber Sie können leicht Gegenbeispiele mit einer einfachen Funktion wie f (x) = x sin (1/x) für x # 0 und f (0) = 0 finden. Ich kann Ihnen das garantieren Es ist kontinuierlich auf 0, aber Ihre Eigenschaft ist falsch darauf. –

0

Das Finden numerisch einer Wurzel ist nur sinnvoll, wenn die Funktion nette Eigenschaften hat und mindestens kontinuierlich ist. Was würden Sie denken über diese:

f: x -> f (x) definiert:

  • 2 * i < x < 2 * i + 1 (i Element von Z): f (x) = x
  • 2 - i + 1 x < < 2 * i (i Element der Z): f (x) = -x
  • x = i (i Element der Z): f (x) = 1

Es ist perfekt auf R definiert, ist begrenzt auf jeder begrenzt Intervall, hat positive und negative Werte für jedes Intervall der Größe> 1 und ist für alle nicht ganzzahligen Punkte stetig, hat aber keine Wurzel.

Es ist einfach, weil die Regel, dass ein Root-Segment auf] x existieren muss, y [if x y oder y 0 < < x gilt nur, wenn die Funktion auf dem Intervall kontinuierlich ist.

Und viel Glück, wenn Sie Test für Stetigkeit einer Funktion numerisch wollen ...

Verwandte Themen