vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Zippen wie die Profis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Variablen/Strings · Algorithmen/Mathematik   |   VB-Versionen: VB.NET12.06.07
Die MATH.POW-Funktion

Vorschläge zur Kapselung der POW-Funktion

Autor:   Manfred BohnBewertung:     [ Jetzt bewerten ]Views:  14.689 
ohne HomepageSystem:  WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Die POW-Funktion in der Math-Klasse von VB.Net berechnet die Potenz einer Zahl.

Der erste Funktionsparameter (x) enthält die Zahl, die potenziert werden soll (mathematisch: Basis oder Grundzahl), der zweite Parameter (y) enthält den Exponenten (mathematisch auch: Hochzahl).

Die Funktion akzeptiert IEEE-Sonderwerte in den Parametern und verarbeitet die Werte nachdem 16 (+1) Fallunterscheidungen berücksichtigt worden sind. Im Funktions-Ergebnis kann ein Double-Wert oder einer der IEEE-Sonderwerte auftreten. Ausnahmen werden von Math.Pow nicht ausgelöst. Ebensowenig erfährt man, welcher der 16 (+1) Fälle bei der Bearbeitung aufgetreten ist, oder ob es zu einem Überlauf der Gleitkomma-Arithmetik bei Ermittlung der Potenz gekommen ist.

Aufgrund dieses überaus flexiblen und liberalen Verhaltens, ist bei der Verwendung der POW-Funktion einige Vorsicht geboten.

Es ist nämlich in den meisten VB-Programmen sorgfältig zu unterscheiden,

  • ob bereits die Eingabeparameter 'Nan'-Werte (d.h. undefiniert) enthalten haben
  • ob die Berechnung der Potenz angesichts der Parameter aus mathematischen Gründen unzulässig ist (z.B. ist bei negativer Basis ein ganzzahliger Exponent erforderlich)
  • ob die POW-Funktion auf ihre Unendlichkeits-Logik zurückgegriffen hat
  • ob es zu einem Überlauf bei der Ergebnis-Ermittlung (DOUBLE-Wert) gekommen ist.

Die Überprüfung des Funktionsergebnisses liefert meist nicht die benötigte eindeutige Information für eine geeignete Verzweigung im weiteren Programmablauf.

Ein 'Nan'-Wert im Ergebnis kann auf einen Nan.-Wert in den Parameter, auf mathematische Unzulässigkeit der Berechnung oder auf Anwendung der Unendlichkeitsarithmetik zurückführbar sein. Ein Infinity-Wert im Ergebnis kann auf Anwendung der Unendlichkeits-Arithmetik oder auf einen Überlauf der Gleitkomma-Darstellung des Ergebnisses zurückführbar sein. Aber auch die Zahlen-Werte 0.0 bzw. 1.0 können als Ergebnis der Unendlichkeits-Arithmetik auftreten.

Bei genauerer Betrachtung erweist sich die POW-Funktion in der Anwendung also als ein recht verzwickt zu handhabendes Werkzeug.

Übersicht über die Unendlichkeits-Arithmetik der POW-Funktion:

Enthält die Basis (x-Parameter) den Wert -unendlich, wird das POW-Resultat ...

  • 0, wenn y < 0 (z.B. auch y = -unendlich)
  • +1.0, wenn y = 0
  • -unendlich, wenn y eine positive ungerade ganze Zahl ist
  • +unendlich, wenn y > 0, aber keine ungerade ganze Zahl ist (z.B. auch y = +unendlich)

Enthält die Basis (x-Parameter) den Wert +unendlich, wird das POW-Resultat ...

  • 0, wenn y < 0 (z.B. auch y = -unendlich)
  • +1.0, wenn y = 0
  • +unendlich, wenn y > 0 (z.B. auch y = +unendlich)

Enthält der Exponent (y-Parameter) den Wert -unendlich, wird das POW-Resultat ...

  • 0, wenn x > 1 oder x < -1 (z.B. auch x = +/-unendlich)
  • +1.0, wenn x = 1
  • +unendlich, wenn -1 < x < 1
  • undefiniert, wenn x = -1

Enthält der Exponent (y-Parameter) den Wert +unendlich, wird das POW-Resultat ...

  • 0, wenn -1 < x < 1
  • +1.0, wenn x = 1
  • +unendlich, wenn x > 1 oder x < -1 (z.b. auch x = +/-unendlich)
  • undefiniert, wenn x = -1

Es werden nicht nur Infinity-Werte in der Eingabe, sondern auch Grenzübergänge bei der Infinity-Arithmetik berücksichtigt:
Das Pow-Resultat wird

  • +unendlich, falls x = 0; y < 0
  • 0, falls x = 0; y > 0
  • +1, falls x = 0; y = 0

Zusätzlich ist zu beachten, dass ein Überlauf der Gleitkomma-Arithmetik ebenfalls +/-unendlich im Ergebnis liefert.

Insbesondere die Unendlichkeits-Bedingungen, unter denen POW die Werte 0 bzw. 1 zurückgibt, sind heikel, weil sie in komplexen mathematischen Termen verschleiern können, dass Infinity-Werte bei Zwischenergebnissen aufgetreten sind (und deshalb die Unendlichkeits-Arithmetik zur Anwendung kam).

Bedingungen, unter denen die POW-Funktion ein undefiniertes Ergebnis ('NaN') liefert:

  • falls der Parameter x und/oder der Parameter y bereits den Wert 'NaN' enthält
  • die bei der Unendlichkeits-Arithmetik auftretenden Fälle (z.B. x = -1 : y = +/-unendlich)

Um die POW-Funktion bei eigenen Anwendungen in geeigneter Weise in einer Funktion zu kapseln, sind verschiedenartige Lösungen denkbar - abhängig davon, ob man die Unendlichkeits-Werte ganz oder teilweise akzeptiert und ob die Overflow-Bedingung abgefangen werden soll.

Die kapselnde Funktion 'POWER1' ist im Hinblick auf die Ausnahmen besonders restriktiv. Sie erlaubt keine IEEE-Sonderwerte in den Eingabeparametern und in der Ergebnis-Rückgabe vom POW.

Die kapselnde Funktion 'POWER2' duldet die Unendlichkeitsarithmetik weitgehend und löst eine Ausnahme nur aus, wenn 'undefinierte' Werte in den Parametern oder im Funktionsergebnis auftreten.

Die kapselnde Funktion 'POWER3' löst beim Auftreten von Sonderfällen, wie sie die VB-Dokumentation auflistet, Ausnahmen aus, meldet aber im Error-Objekt, welche Bedingung die Ausnahme verursacht hat. Im CATCH-Block des aufgefangenen Fehlers können dann für die einzelnen Sonderfälle geeignete Verzweigungen vorgenommen werden. Der optionale Parameter 'Check_Result' entscheidet darüber, ob zusätzlich noch Gleitkomma-Überläufe im Funktions-Ergebnis von POW eine Ausnahme auslösen sollen. 'POWER3' löst nicht bei allen Sonderfällen Ausnahmen aus, sondern nur bei denen, die im POW-Ergebnis zu einem IEEE-Sonderwert führen. Unter bestimmten Bedingungen werden Infinity-Werte in den Parametern toleriert - vgl oben..

Die kapselnde Funktion 'POWER4' verzichtet völlig auf Ausnahmen und meldet statt dessen im optionalen SHORT-Rückgabeparameter 'Fall' ggf. welcher der 16 Fälle, die die POW-Funktion unterscheidet, vorliegt. Falls das Ergebnis nicht auf einem Sonderfall beruht, aber den Min-Max-Bereich von DOUBLE überschreitet, wird der Fall -1 gemeldet, sonst 0.

Public Function Power1(ByVal basis As Double, _
  ByVal exponent As Double) As Double
 
  ' Die Funktion löst stets einen Fehler aus, 
  ' wenn in einem Argument oder im POW-Ergebnis
  ' ein IEEE-Sonderwert auftritt
 
  If Not Im_Double_Bereich(basis) Then
    Throw New Exception("Basis nicht im Double-Bereich")
  ElseIf Not Im_Double_Bereich(exponent) Then
    Throw New Exception("Exponent nicht im Double-Bereich")
  End If
 
  Dim Resultat As Double = Math.Pow(basis, exponent)
  If Not Im_Double_Bereich(Resultat) Then
    Throw New Exception("Resultat nicht im Double-Bereich")
  End If
 
  Return Resultat
End Function
Public Function Power2(ByVal basis As Double, _
  ByVal exponent As Double) As Double
 
  ' Die Funktion löst stets einen Fehler aus, 
  ' wenn in einem Argument oder im POW-Ergebnis
  ' der IEEE-Sonderwert 'NaN' auftritt
 
  Dim Resultat As Double = Math.Pow(basis, exponent)
 
  If Double.IsNaN(Resultat) Then
    Throw New Exception("POW-Funktion: Not a Number")
  End If
 
  Return Resultat
End Function
Public Function Power3(ByVal basis As Double, _
  ByVal exponent As Double, _
  Optional ByVal Check_Result As Boolean = True) As Double
 
  ' Die Funktion kapselt die MATH.POW-Funktion
  ' und löst bei Parameter-Bedingungen, die zu 
  ' IEEE-Sonderwerten in der Rückgabe führen würden, 
  ' einen auffangbaren Fehler aus
 
  ' Die als Kommentar angegebenen Fallnummern beziehen 
  ' sich auf die Reihenfolge der Bedingungen in der Liste, 
  ' die in der VB-Doku zur MATH.POW-Methode enthalten ist
 
  ' Check_Result entscheidet darüber, ob ermittelt wird,
  ' ob das POW-Ergebnis als Double-Wert darstellbar ist
  ' (--> Gleitkomma-Überlauf abfangen)
 
  Dim m As String = ""
  Dim erg As Double ' Ergebnis von POW
 
  ' Hilfswertre für +/-Unendlich im Exponenten
  Dim ExpoNegInf As Boolean = Double.IsNegativeInfinity(exponent)
  Dim ExpoPosInf As Boolean = Double.IsPositiveInfinity(exponent)
 
  Dim BasisNegInf As Boolean = Double.IsNegativeInfinity(basis)
 
  ' Fall 1 
  If Double.IsNaN(basis) Then
    Throw New Exception("POW: Basis ist keine Zahl")
  End If
  If Double.IsNaN(exponent) Then
    Throw New Exception("POW: Exponent ist keine Zahl")
  End If
 
  ' Fall 4/5
  If BasisNegInf Then
    If exponent > 0 Then
      Throw New Exception("POW: Basis = -unendlich, Exponent > 0")
    End If
  End If
 
  ' Fall 6/7
  If basis < 0 Then
    If basis < -1 And ExpoNegInf Then
      ' OK: hier kommt im Ergebnis 0 (Fall 10) 
    ElseIf ExpoNegInf Then
      Throw New Exception("POW: Basis < 0, Exponent -unendlich")
    ElseIf ExpoPosInf Then
      If basis > -1 Then
        ' OK: hier kommt im Ergebnis 0 (Fall 9)
      Else
        Throw New Exception("POW: Basis < 0, Exponent +unendlich")
      End If
    End If
    If Not BasisNegInf Then
      If exponent <> Fix(exponent) Then
        Throw New Exception("POW: Basis < 0, Exponent nicht ganzzahlig")
      End If
    End If
  End If
 
  If basis > -1 And basis < 1 Then
    ' Fall 8
    If ExpoNegInf Then
      Throw New Exception("POW: -1 < Basis < 1, Exponent -unendlich")
    End If
  ElseIf basis < -1 Or basis > 1 Then
    ' Fall 11
    If basis < -1 Then m = "POW: Basis < -1"
    If basis > 1 Then m = "POW: Basis > 1"
    If ExpoPosInf Then
      Throw New Exception(m + " , Exponent +unendlich")
    End If
  End If
 
  ' Fall 12
  If basis = 0 And exponent < 0 Then
    Throw New Exception("Basis = 0, Exponent < 0")
  End If
 
  ' Fall 16
  If Double.IsPositiveInfinity(basis) Then
    If exponent > 0 Then
      Throw New Exception("Basis = +unendlich, Exponent > 0")
    End If
  End If
 
  ' Aufruf der POW-Funktion
  erg = Math.Pow(basis, exponent)
 
  If Check_Result Then
    ' zusätzliche Ausnahme, falls Überlauf der 
    ' Gleitkomma-Arithmetik im Datentyp DOUBLE 
    ' bei Zuweisung des Ergebnisses auftritt
    If Not Im_Double_Bereich(erg) Then
      Throw New Exception("POW: Ergebnis nicht in DOUBLE-Spannweite")
    End If
  End If
 
  Return erg
End Function
Public Function Power4(ByVal Basis As Double, _
  ByVal Exponent As Double, _
  Optional ByRef Fall As Short = -1) As Double
 
  ' Die Funktion ermittelt im opt. Parameter 'Fall'
  ' welcher Fall der VB-Doku-Liste bei Anwendung von POW 
  ' vorliegt:
  ' Fall = 0 keine IEEE-Sonderwerte
  ' Fall = 1 bis 16 Nummer des Sonderfalls 
  ' Fall = -1 Ergebnis nicht als Double darstellbar
  ' Fall = -2 nicht beabsichtigt
 
  Dim erg As Double  ' POW-Rückgabe
  Dim ierg As Double ' intern: erwartete Rückgabe im Sonderfall
 
  ' Hilfswerte 'Infinity'-Parameter
  Dim BasisNegInf As Boolean = Double.IsNegativeInfinity(Basis)
  Dim BasisPosInf As Boolean = Double.IsPositiveInfinity(Basis)
  Dim ExpoNegInf As Boolean = Double.IsNegativeInfinity(Exponent)
  Dim ExpoPosInf As Boolean = Double.IsPositiveInfinity(Exponent)
 
  ' Rückgabe initialisieren
  Fall = -1
 
  ' Sonderfälle ermitteln und ggf. notieren 
  If Double.IsNaN(Basis) Or Double.IsNaN(Exponent) Then
    Fall = 1 : ierg = Double.NaN
  ElseIf Basis = 1 Then
    Fall = 14 : ierg = 1
  ElseIf Basis = 0 Then
    If Exponent < 0 Then
      Fall = 12 : ierg = Double.PositiveInfinity
    ElseIf Exponent > 0 Then
      Fall = 13 : ierg = 0
    End If
  ElseIf Exponent = 0 Then
    Fall = 2 : ierg = 1
  ElseIf BasisNegInf Then
    If Exponent < 0 Then
      Fall = 3 : ierg = 0
    ElseIf Exponent > 0 Then
      If Exponent - Fix(Exponent) = 0 And Exponent Mod 2 <> 0 Then
        ' ganzzahlig, positiv, ungerade
        Fall = 4 : ierg = Double.NegativeInfinity
      Else
        Fall = 5 : ierg = Double.PositiveInfinity
      End If
    End If
  ElseIf BasisPosInf Then
    If Exponent < 0 Then
      Fall = 15 : ierg = 0 ' 0
    ElseIf Exponent > 0 Then
      Fall = 16 : ierg = Double.PositiveInfinity
    End If
  ElseIf Basis = -1 Then
    If ExpoPosInf Or ExpoNegInf Then
      Fall = 7 : ierg = Double.NaN
    End If
  ElseIf Basis > -1 And Basis < 1 Then
    If ExpoNegInf Then
      Fall = 8 : ierg = Double.PositiveInfinity 
    ElseIf ExpoPosInf Then
      Fall = 9 : ierg = 0
    End If
  ElseIf Basis < -1 Or Basis > 1 Then
    If ExpoNegInf Then
      Fall = 10 : ierg = 0
    ElseIf ExpoPosInf Then
      Fall = 11 : ierg = Double.PositiveInfinity 
    End If
  End If
  If Basis < 0 And Fall = -1 Then
    If ExpoNegInf Or ExpoPosInf Or Exponent <> Fix(Exponent) Then
      Fall = 6 : ierg = Double.NaN 
    End If
  End If
 
  ' POW ausführen
  erg = Math.Pow(Basis, Exponent)
 
  If Fall = -1 Then
    ' Ergebnis im DOUBLE-Wertebereich? (--> Fall 0) 
    If Im_Double_Bereich(erg) Then Fall = 0
  Else
    ' Bei Sonderfall:
    ' Erwartete Rückgabe = tatsächliche Pow-Rückgabe ??
    If Not Double_Vergleich(erg, ierg) Then
      Fall = -2 'Diese Bedingung sollte nicht auftreten
    End If
  End If
 
  ' POW-Ergebnis zurückgeben
  Return erg
End Function
Public Function Im_Double_Bereich( _
  ByVal x As Double) As Boolean
 
  ' Hilfsfunktion: Prüfung der Double-Spannweite
  If x >= Double.MinValue And x <= Double.MaxValue Then 
    Return True
  Else
    ' IEEE-Sonderwert (Infinity, NaN)
    Return False
  End If
End Function
Public Function Double_Vergleich( _
  ByVal x As Double, ByVal y As Double) As Boolean
 
  ' Die Funktion prüft, ob der Inhalt von
  ' zwei Double-Variablen identisch ist
  If Double.IsNaN(x) And Double.IsNaN(y) Then
    Return True
  ElseIf x = y Then
    Return True
  Else
    Return False
  End If
End Function 

Dieser Tipp wurde bereits 14.689 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel