Table of Contents
29.3.4 Polynomial class
The Polynomial class from gb.gsl implements a polynomial with real or complex coefficients. It acts like a read/write array and can be used like a function. The Polynomial class has two properties and three methods.
29.3.4.1 Polynomial class
A polynomial or, better, a polynomial function P(x) can be defined as follows
- The real or complex numbers ai are called coefficients.
- The natural numbers n, n-1, n-2, …,1 and 0 are possible exponents.
- The largest value of the exponents determines the degree of the polynomial.
- The Ti is referred to as a term or monomial with Tk = akxk .
- Polynomial and polynomial function P(x) are used synonymously.
29.3.4.2 Properties
The Polynomial class has two properties:
| Property | Data type | Description |
|---|---|---|
| Count | Integer | Returns the number of coefficients. |
| Degree | Integer | Returns the degree of the polynomial as the value (n ≥ 0 , n Î N) of the largest exponent. |
Table 29.3.4.2.1 : Properties of the Polynomial class
29.3.4.3 Methods
The Polynomial class has these three methods:
| Method | Return type | Description |
|---|---|---|
| Eval ( x As Variant ) | Variant | Calculates the value of a polynomial P(x) for the given argument x. |
| Solve ( [ Complex As Boolean ] ) | Array | The real roots of the polynomial with P(x)=0 are calculated and returned. |
| ToString ( [ Local As Boolean ] ) | String | The polynomial is returned as a string representation. |
Table 29.3.4.3.1 : Methods of the Polynomial class
Notes:
- The return type of the Eval (..) method is of type Variant, because the value of a polynomial function P(x) can be a real or a complex number.
- If no roots are found, an empty array is returned. If P(x) = 0 has the following structures, the roots are calculated exactly:
x³ + a*x² + b*x + c = 0 OR a*x² + b*x + c = 0
- In all other cases, approximation methods are used that do not necessarily converge for the (internally) set start value! In these (divergent) cases, an error is triggered. The occurrence of several equal roots is not emphasised as something special, as for example in the equation (x-1)³ = 0, which has exactly three equal real roots as solutions.
- All root values as solutions of P(x)=0 must be checked at the end (probe).
- Often only one sufficiently exact solution is output for the solutions - for example for the equation x³-x=0 with x2= -7.0705015914994E-17 - while the other two solutions with x1=-1 and x3=+1 provide exact root values.
- If the Local parameter has the value True, the numbers are output in the local notation, while the default value False formats the string so that it can be evaluated by the Eval(..) function.
29.3.4.4 Creating polynomials
There are several ways to generate polynomials:
- Declaration of a variable of the data type polynomial with direct value assignment.
- Declaration of a variable of data type polynomial and subsequent assignment of the coefficients in an array (with increasing powers and comma as separator), whereby missing terms must be represented by 0! The degree of the term results from its position in the array.
- Conversion of a character string from a suitable (input) component into a polynomial.
Example of the implementation of the first two options using the Count and Degree properties and the ToString(..) method:
Dim pPolynom1 As Polynomial = [-8.88, 1, 0, 0, 0.44, -6.66] ' Option 1 Dim pPolynom2 As Polynomial ' Option 2.1 Dim aRoots As Complex[] Dim iCount As Integer Print "Polynom 1 = ";; pPolynom1 Print "Polynom 1 = ";; pPolynom1.ToString(True) Print "Polynom 1 = ";; pPolynom1.ToString() ' False is standard parameter, input optional Print pPolynom1.Degree ' Degree of the polynomial Print pPolynom1.Count ' Number of terms of the polynomial pPolynom2 = [-9, -9, 1, 1] ' Option 2.2 Print "Polynom 2 = ";; pPolynom2 Print "Polynom 2 = ";; pPolynom2.ToString(True) Print "Polynom 2 = ";; pPolynom2.ToString()
This is the output in the console of the Gambas IDE:
[1] Polynom 1 = -6,66x^5+0,44x^4+x-8,88 [2] Polynom 1 = -6,66x^5+0,44x^4+x-8,88 [3] Polynom 1 = -6.66*x^5+0.44*x^4+x-8.88 [4] 5 [5] 6 [6] Polynom 2 = x^3+x^2-9x-9 [7] Polynom 2 = x^3+x^2-9x-9 [8] Polynom 2 = x^3+x^2-9*x-9
29.3.4.5 Calculating the function value of a polynomial function P(x)
The calculation of the function value of a polymom function P(x) is shown for real and complex arguments:
Dim pPolynom2, pPolynom3 As Polynomial pPolynom2 = [-9, -9, 1, 1] Print "Polynom 2 = ";; pPolynom2.ToString(True) Print "P2(2,34) = "; Eval(pPolynom2.ToString(False), ["x": 2.34]) '-- Real argument Print pPolynom3 = [-9i, 2, 1 - 2i] Print "Polynom 3 = ";; pPolynom3.ToString(False) Print "P3(1+i) = "; Eval(pPolynom3.ToString(False), ["x": 1 + 1i]) '-- Complex argument
Here are the outputs:
[1] Polynom 2 = x^3+x^2-9x-9 [2] P2(2,34) = -11,771496 [3] [4] Polynom 3 = (1-2i)*x^2+2*x-9i [5] P3(1+i) = 6-5i
29.3.4.6 Calculating the zeros of a polynomial function
The calculation of the zeros of a polynomial function or the calculation of the solutions of a polynomial equation leads to P(x)=0.
- The success of the Solve(..) method is dependent on this condition: All coefficients in the polynomial function P(x) are real numbers, otherwise an error is triggered!
- If the Complex parameter is True, all complex roots are calculated and returned in an array. If the Complex parameter is False, then only the existing real roots are calculated and returned in an array.
The calculation of the solutions of P(x)=0 is shown for real and complex arguments:
Dim pPolynom2, pPolynom4 As Polynomial Dim aRoots As Complex[] Dim iCount As Integer pPolynom2 = [-9, -9, 1, 1] Print "Polynom 2 = ";; pPolynom2.ToString(True) aRoots = pPolynom2.Solve(False) '-- Only real roots For iCount = 0 To aRoots.Max Print "Root_" & CInt(iCount + 1) & " = " & aRoots[iCount] Next Print pPolynom4 = [4, 0, 1] Print "Polynom 4 = ";; pPolynom4.ToString(True) aRoots = pPolynom4.Solve(True) '-- Only complex roots For iCount = 0 To aRoots.Max Print "Root_" & CInt(iCount + 1) & " = " & aRoots[iCount] Next
In the console of the Gambas IDE you then read:
Polynom 2 = x^3+x^2-9x-9 Wurzel_1 = -3 Wurzel_2 = -1 Wurzel_3 = 3 Polynom 4 = x^2+4 Wurzel_1 = -2i Wurzel_2 = 2i
If you set aRoots = pPolynom4.Solve(True) for aRoots = pPolynom4.Solve(False), you get the empty set as the solution set - or an empty array in Gambas - because there are no real solutions for the power function P(x)=x⁴+4=0.
29.3.4.7 Example
The following example implements the third variant for generating a polynomial by converting a character string from a suitable (input) component - here InputBox - into a polynomial. At the heart of the third variant are the following two functions, which check whether a character string can be interpreted as a polynomial and also determine the coefficients of a polynomial function P(x) - provided the input character string can be interpreted as a polynomial - whereby only real coefficients are permitted:
Private Function ValPolynomial(sInput As String) As Polynomial '-- Tobias Boege Private Function IsPolynomial(sInput As String) As Boolean
Here is the complete, sufficiently commented source code:
' Gambas class file Private $pP1 As Polynomial Private $pP2 As Polynomial Private $pResult As Polynomial Public Sub Form_Open() FMain.Center FMain.Resizable = False ' txbInputPolynom1.Clear() ' txbInputPolynom2.Clear() txbInputPolynom1.SetFocus() ' http://de.wikipedia.org/wiki/Unicodeblock_Mathematische_Operatoren btnAddieren.Text = " Adding polynomials " & String.Chr(8853) btnSubtrahieren.Text = " Subtract polynomials " & String.Chr(8854) End Public Sub btnConvert_Click() If txbInputPolynom1.Text Then txbOutputPolynom.Clear() Try txbOutputPolynom.Text = ValPolynomial(txbInputPolynom1.Text).ToString() If Error Then Message.Error("The string for P1(x) cannot be interpreted as a polynomial!") txbInputPolynom1.SetFocus Endif Endif End Public Sub txbInputPolynom1_Activate() btnConvert_Click() End Public Sub txbInputPolynom1_KeyPress() CheckInput("+-,.^0123456789x") End Public Sub txbInputPolynom2_KeyPress() CheckInput("+-,.^0123456789x") End Public Sub btnIsPolynomial_Click() If txbInputPolynom1.Text Then If IsPolynomial(txbInputPolynom1.Text) = True Then Message.Info("The input string for P1(x) can be interpreted as a polynomial!") Else Message.Error("The input string for P1(x) can NOT be interpreted as a polynomial!") txbInputPolynom1.SetFocus Endif Endif End Public Sub btnAddieren_Click() If txbInputPolynom1.Text And txbInputPolynom2.Text Then If (IsPolynomial(txbInputPolynom1.Text) = True) And (IsPolynomial(txbInputPolynom2.Text) = True) Then $pP1 = ValPolynomial(txbInputPolynom1.Text) $pP2 = ValPolynomial(txbInputPolynom2.Text) $pResult = $pP1 + $pP2 txbOutputPolynom.Text = $pResult.ToString() Else Message.Error("At least one input string cannot be interpreted as a polynomial!") Endif Endif End Public Sub btnSubtrahieren_Click() If txbInputPolynom1.Text And txbInputPolynom2.Text Then If (IsPolynomial(txbInputPolynom1.Text) = True) And (IsPolynomial(txbInputPolynom2.Text) = True) Then $pP1 = ValPolynomial(txbInputPolynom1.Text) $pP2 = ValPolynomial(txbInputPolynom2.Text) $pResult = $pP1 - $pP2 txbOutputPolynom.Text = $pResult.ToString() Else Message.Error("At least one input string cannot be interpreted as a polynomial!") Endif Endif End Public Sub btnVergleichen_Click() If txbInputPolynom1.Text And txbInputPolynom2.Text Then If (IsPolynomial(txbInputPolynom1.Text) = True) And (IsPolynomial(txbInputPolynom2.Text) = True) Then If ValPolynomial(txbInputPolynom1.Text) = ValPolynomial(txbInputPolynom2.Text) Then txbOutputPolynom.Text = "P1(x) und P2(x) sind gleich!" Else txbOutputPolynom.Text = "P1(x) and P2(x) are NOT the same!" Endif Else Message.Error("At least one input string cannot be interpreted as a polynomial!") Endif Endif End '********************************************************************************************************* Public Sub txbInputPolynom1_Change() txbOutputPolynom.Clear End Public Sub txbInputPolynom2_Change() txbOutputPolynom.Clear End Public Sub CheckInput(sAllowed As String) '-- Concept Charles Guerin Select Case Key.Code Case Key.Left, Key.Right, Key.BackSpace, Key.Delete, Key.End, Key.Home, Key.Enter, Key.Return Return Default If Key.Text And If InStr(sAllowed, Key.Text) Then Return Endif End Select Stop Event End Private Function ValPolynomial(sInput As String) As Polynomial Dim hRegexp As New RegExp Dim hPolynom As New Polynomial(1) Dim fKoeffizient As Float Dim iExponent As Integer Dim sMiddle As String ' Replace the decimal separator of the current locale - here de - with the dot sInput = Replace$(sInput, Left$(Format$(0, ".0")), ".") ' Normalise the input: The first term (monomial) in the polynomial requires a sign If Left$(sInput) Not Like "[+-]" Then sInput = "+" & sInput hRegexp.Compile("([+-][0-9]+(\\.[0-9]+)?)(x)?(\\^([0-9]+))?|[+-]x(\\^([0-9]+))?") hRegexp.Exec(sInput) While hRegexp.Offset <> -1 ' If no coefficient is entered in the term, then coefficient = 1, ' If no exponent is entered in the term, then exponent = 1, ' If the argument x is not contained in the term, then exponent = 0. If hRegexp[0].Text Like "[+-]x*" Then fKoeffizient = IIf(hRegexp.Text Begins "+", 1.0, -1.0) If hRegexp.Count = 7 Then iExponent = CInt(Right$(hRegexp[6].Text, -1)) Else iExponent = 1 Endif Else fKoeffizient = CFloat(hRegexp[1].Text) If hRegexp.Count = 5 Then iExponent = CInt(Right$(hRegexp[4].Text, -1)) Else If hRegexp.Count = 3 Then iExponent = 1 Else iExponent = 0 Endif Endif hPolynom[iExponent] += fKoeffizient sMiddle = Mid$(sInput, hRegexp.Offset sInput = Mid$(sInput, 1, hRegexp.Offset) & sMiddle + Len(hRegexp[0].Text) + 1) If Not sInput Then Return hPolynom hRegexp.Exec(sInput) Wend Finally Return Null End Private Function IsPolynomial(sInput As String) As Boolean Dim sPattern, sTerm As String Dim aResult, aTmp As New String[] Dim iI, iJ As Integer Dim sExpression As String sInput = Trim(sInput) sInput = Replace$(sInput, Left$(Format$(0, ".0")), ".") ' Separate all terms linked by + aResult = Split(sInput, "+", "", True) ' While loop instead of For loop, because aResult is modified in the loop iI = 0 While iI < aResult.Count ' First replicate the sign on the term (-> restore) sExpression = IIf(aResult[iI] Not Begins "-", "+", "") & aResult[iI] ' The polynomial P(x) is then replaced by an array of simple terms aResult.Remove(iI) ' Then separate all terms linked by - aTmp = Split(sExpression, "-", "", True) For iJ = 0 To aTmp.Max aTmp[iJ] = IIf(aTmp[iJ] Not Begins "+", "-", "") & aTmp[iJ] Next ' Finally, the array of simple terms takes the place of sExpression aResult.Insert(aTmp, iI) iI += aTmp.Count Wend sPattern = "^[+-]?([0-9]+(\\.[0-9]+)?)?(x([\\^][0-9]+)?)?$" For Each sTerm In aResult If sTerm Not Match sPattern Then Return False Endif ' Match Pattern Next ' sTerm Return True End
The example also demonstrates the addition, subtraction and comparison of two polynomials:
Figure 29.3.4.7.1: Generating polynomials
The function
Private Function ValPolynomial(sInput As String) As Polynomial ' Tobias Boege
function also contains an internal check (→ While hRegexp.Offset <> -1) as to whether the character string passed as an argument can be interpreted as a polynomial. This is not necessary here because only valid character strings are passed to this function in the programme presented.
You can use the above function
Private Function IsPolynomial(sInput As String) As Boolean
with the following function:
' IsPolynomial() uses the same procedure as ValPolynomial() above. ' It is therefore not significantly faster than the comparison ValPolynomial = zero. Private Function IsPolynomial(sInput As String) As Boolean sInput = Replace$(sInput, Left$(Format$(0, ".0")), ".") If Left$(sInput) Not Like "[+-]" Then sInput = "+" & sInput $hRegexp.Exec(sInput) While $hRegexp.Offset <> -1 sInput = Mid$(sInput, 1, $hRegexp.Offset) & Mid$(sInput, $hRegexp.Offset + Len($hRegexp[0].Text) + 1) If Not sInput Then Return True $hRegexp.Exec(sInput) Wend Finally Return False End


