Nullstellen von Polynomen - Bairstow-Verfahren


Die Lösung von Polynomausdrücken, die (fast) jeder für den Fall des Polynomgrades 2 gerade noch beherrscht, was man auch Nullstellensuche nennt, wird richtig unbequem, wenn das Polynom etwa vom Grade 5 oder 25 ist. Für unbequeme Sachen hat man heute den Computer. Wie man so etwas programmiert, hat der Herr Bairstow herausbekommen, nach dem dann auch der Algorithmus benannt ist.
Wie es geht? Man spaltet in einer Iteration quadratische Faktoren ab, die dann in bekannter Weise (Vieta!) gelöst werden, und das so lange, bis das Restpolynom vom Grade 0 oder 1 ist.
Was der Nutzer tun muß, ist, den Grad des Polynoms (= höchste vorkommende Potenz) und die Koeffizienten des in Normalform (Polynom = 0) gebrachten Polynoms in der Reihenfolge fallender Potenz irgendwo bereitzustellen. Wir packen sie hier in ein Array A(), also 1. Koeffizient nach A(Grad), 2. nach A(Grad-1), ... das absolute Glied also nach A(0). Schon geht's los:

Sub Bairstow()
Dim ... 'bißchen was solltet Ihr schon selber tun!

Do While Grad > 2
R = 0
P1 = 1
Q1 = -1
B(Grad) = A(Grad)
C(Grad) = A(Grad)
Do
P = P1
Q = Q1
B(Grad - 1) = B(Grad) * P + A(Grad - 1)
C(Grad - 1) = B(Grad - 1) + B(Grad) * P
For i = Grad - 2 To 0 Step -1
B(i) = B(i + 2) * Q + B(i + 1) * P + A(i)
C(i) = C(i + 2) * Q + C(i + 1) * P + B(i)
Next
Ce = C(2) ^ 2 - C(1) * C(3)
If Ce = 0 Then pic.Print "andere Startwerte nötig"
P1 = P - (B(1) * C(2) - B(0) * C(3)) / Ce
Q1 = Q - (B(0) * C(2) - B(1) * C(1)) / Ce
R = R + 1
If R > 1000 Then
pic.Print "Keine Konvergenz nach 1000 Runden"
End If
Loop Until Abs(B(0)) + Abs(B(1)) < 1E-12
'Nullstelle des quad. Faktors
s = P1 / 2
t = P1 ^ 2 + 4 * Q1
If t < 0 Then
pic.Print s & " + " & 0.5 * Sqr(-t) & "*i"
pic.Print s & " - " & 0.5 * Sqr(-t) & "*i"
Else
pic.Print s + 0.5 * Sqr(t)
pic.Print s - 0.5 * Sqr(t)
End If
For i = 2 To Grad
A(i - 2) = B(i)
Next
Grad = Grad - 2
Loop
If Grad = 1 Then
pic.Print -A(0) / A(1)
Else
s = -0.5 * A(1) / A(2)
t = A(1) ^ 2 - 4 * A(2) * A(0)
If t < 0 Then
pic.Print s & " + " & 0.5 * Sqr(-t) / A(2) & "*i"
pic.Print s & " - " & 0.5 * Sqr(-t) / A(2) & "*i"
Else
pic.Print s + 0.5 * Sqr(t) / A(2)
pic.Print s - 0.5 * Sqr(t) / A(2)
End If
End If
End Sub

Wie man sieht, habe ich die Lösungen hier unformatiert, also mit idiotisch hoher Stellenzahl, in eine Picture-Box namens "pic" ausgegeben, was man mit ihnen tut, ist ja Geschmackssache.

zum Anfang

© R. Hirte * 2003